s3:libsmb: don't handle CLI_FULL_CONNECTION_* flags in cli_start_connection()
[Samba.git] / source3 / libsmb / cliconnect.c
blob70089e5f08ad84637ae992902cd9b4fce371fe83
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(TALLOC_CTX *mem_ctx,
63 char *inbuf,
64 char **dest,
65 uint8_t *src,
66 size_t srclen,
67 ssize_t *destlen)
69 *destlen = clistr_pull_talloc(mem_ctx,
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(mem_ctx, "");
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_state_set_uid(state->cli, 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_state_capabilities(cli) & (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_state_get_vc_num(cli));
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_state_set_uid(state->cli, 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_state_get_vc_num(cli));
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_state_set_uid(state->cli, 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. Windows clients also don't
865 * use hostname...
867 names_blob = NTLMv2_generate_names_blob(
868 NULL, NULL, 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_state_get_vc_num(cli));
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_state_set_uid(state->cli, 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_state_set_uid(state->cli, SVAL(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 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
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 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
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 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1789 const char *user,
1790 const char *pass,
1791 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;
1855 const char *remote_name = cli_state_remote_name(cli);
1857 if (pass && *pass) {
1858 int ret;
1860 use_in_memory_ccache();
1861 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1863 if (ret){
1864 TALLOC_FREE(principal);
1865 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1866 if (cli->fallback_after_kerberos)
1867 goto ntlmssp;
1868 return ADS_ERROR_KRB5(ret);
1872 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1874 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1875 TALLOC_FREE(principal);
1878 if (principal == NULL &&
1879 !is_ipaddress(remote_name) &&
1880 !strequal(STAR_SMBSERVER,
1881 remote_name)) {
1882 char *realm = NULL;
1883 char *host = NULL;
1884 DEBUG(3,("cli_session_setup_spnego: using target "
1885 "hostname not SPNEGO principal\n"));
1887 host = strchr_m(remote_name, '.');
1888 if (dest_realm) {
1889 realm = SMB_STRDUP(dest_realm);
1890 if (!realm) {
1891 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1893 strupper_m(realm);
1894 } else {
1895 if (host) {
1896 /* DNS name. */
1897 realm = kerberos_get_realm_from_hostname(remote_name);
1898 } else {
1899 /* NetBIOS name - use our realm. */
1900 realm = kerberos_get_default_realm_from_ccache();
1904 if (realm == NULL || *realm == '\0') {
1905 realm = SMB_STRDUP(lp_realm());
1906 if (!realm) {
1907 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1909 strupper_m(realm);
1910 DEBUG(3,("cli_session_setup_spnego: cannot "
1911 "get realm from dest_realm %s, "
1912 "desthost %s. Using default "
1913 "smb.conf realm %s\n",
1914 dest_realm ? dest_realm : "<null>",
1915 remote_name,
1916 realm));
1919 principal = talloc_asprintf(talloc_tos(),
1920 "cifs/%s@%s",
1921 remote_name,
1922 realm);
1923 if (!principal) {
1924 SAFE_FREE(realm);
1925 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1927 DEBUG(3,("cli_session_setup_spnego: guessed "
1928 "server principal=%s\n",
1929 principal ? principal : "<null>"));
1931 SAFE_FREE(realm);
1934 if (principal) {
1935 rc = cli_session_setup_kerberos(cli, principal);
1936 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1937 TALLOC_FREE(principal);
1938 return rc;
1942 #endif
1944 TALLOC_FREE(principal);
1946 ntlmssp:
1948 account = talloc_strdup(talloc_tos(), user);
1949 if (!account) {
1950 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1953 /* when falling back to ntlmssp while authenticating with a machine
1954 * account strip off the realm - gd */
1956 if ((p = strchr_m(user, '@')) != NULL) {
1957 account[PTR_DIFF(p,user)] = '\0';
1960 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1963 /****************************************************************************
1964 Send a session setup. The username and workgroup is in UNIX character
1965 format and must be converted to DOS codepage format before sending. If the
1966 password is in plaintext, the same should be done.
1967 ****************************************************************************/
1969 NTSTATUS cli_session_setup(struct cli_state *cli,
1970 const char *user,
1971 const char *pass, int passlen,
1972 const char *ntpass, int ntpasslen,
1973 const char *workgroup)
1975 char *p;
1976 char *user2;
1978 if (user) {
1979 user2 = talloc_strdup(talloc_tos(), user);
1980 } else {
1981 user2 = talloc_strdup(talloc_tos(), "");
1983 if (user2 == NULL) {
1984 return NT_STATUS_NO_MEMORY;
1987 if (!workgroup) {
1988 workgroup = "";
1991 /* allow for workgroups as part of the username */
1992 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1993 (p=strchr_m(user2,*lp_winbind_separator()))) {
1994 *p = 0;
1995 user = p+1;
1996 strupper_m(user2);
1997 workgroup = user2;
2000 if (cli_state_protocol(cli) < PROTOCOL_LANMAN1) {
2001 return NT_STATUS_OK;
2004 /* now work out what sort of session setup we are going to
2005 do. I have split this into separate functions to make the
2006 flow a bit easier to understand (tridge) */
2008 /* if its an older server then we have to use the older request format */
2010 if (cli_state_protocol(cli) < PROTOCOL_NT1) {
2011 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2012 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2013 " or 'client ntlmv2 auth = yes'\n"));
2014 return NT_STATUS_ACCESS_DENIED;
2017 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2018 !lp_client_plaintext_auth() && (*pass)) {
2019 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2020 " or 'client ntlmv2 auth = yes'\n"));
2021 return NT_STATUS_ACCESS_DENIED;
2024 return cli_session_setup_lanman2(cli, user, pass, passlen,
2025 workgroup);
2028 /* if no user is supplied then we have to do an anonymous connection.
2029 passwords are ignored */
2031 if (!user || !*user)
2032 return cli_session_setup_guest(cli);
2034 /* if the server is share level then send a plaintext null
2035 password at this point. The password is sent in the tree
2036 connect */
2038 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2039 return cli_session_setup_plain(cli, user, "", workgroup);
2041 /* if the server doesn't support encryption then we have to use
2042 plaintext. The second password is ignored */
2044 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2045 if (!lp_client_plaintext_auth() && (*pass)) {
2046 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2047 " or 'client ntlmv2 auth = yes'\n"));
2048 return NT_STATUS_ACCESS_DENIED;
2050 return cli_session_setup_plain(cli, user, pass, workgroup);
2053 /* if the server supports extended security then use SPNEGO */
2055 if (cli_state_capabilities(cli) & CAP_EXTENDED_SECURITY) {
2056 const char *remote_realm = cli_state_remote_realm(cli);
2057 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2058 workgroup,
2059 remote_realm);
2060 if (!ADS_ERR_OK(status)) {
2061 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2062 return ads_ntstatus(status);
2064 } else {
2065 NTSTATUS status;
2067 /* otherwise do a NT1 style session setup */
2068 status = cli_session_setup_nt1(cli, user, pass, passlen,
2069 ntpass, ntpasslen, workgroup);
2070 if (!NT_STATUS_IS_OK(status)) {
2071 DEBUG(3,("cli_session_setup: NT1 session setup "
2072 "failed: %s\n", nt_errstr(status)));
2073 return status;
2077 if (strstr(cli->server_type, "Samba")) {
2078 cli->is_samba = True;
2081 return NT_STATUS_OK;
2084 /****************************************************************************
2085 Send a uloggoff.
2086 *****************************************************************************/
2088 struct cli_ulogoff_state {
2089 struct cli_state *cli;
2090 uint16_t vwv[3];
2093 static void cli_ulogoff_done(struct tevent_req *subreq);
2095 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2096 struct tevent_context *ev,
2097 struct cli_state *cli)
2099 struct tevent_req *req, *subreq;
2100 struct cli_ulogoff_state *state;
2102 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2103 if (req == NULL) {
2104 return NULL;
2106 state->cli = cli;
2108 SCVAL(state->vwv+0, 0, 0xFF);
2109 SCVAL(state->vwv+1, 0, 0);
2110 SSVAL(state->vwv+2, 0, 0);
2112 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2113 0, NULL);
2114 if (tevent_req_nomem(subreq, req)) {
2115 return tevent_req_post(req, ev);
2117 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2118 return req;
2121 static void cli_ulogoff_done(struct tevent_req *subreq)
2123 struct tevent_req *req = tevent_req_callback_data(
2124 subreq, struct tevent_req);
2125 struct cli_ulogoff_state *state = tevent_req_data(
2126 req, struct cli_ulogoff_state);
2127 NTSTATUS status;
2129 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2130 if (!NT_STATUS_IS_OK(status)) {
2131 tevent_req_nterror(req, status);
2132 return;
2134 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2135 tevent_req_done(req);
2138 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2140 return tevent_req_simple_recv_ntstatus(req);
2143 NTSTATUS cli_ulogoff(struct cli_state *cli)
2145 struct tevent_context *ev;
2146 struct tevent_req *req;
2147 NTSTATUS status = NT_STATUS_NO_MEMORY;
2149 if (cli_has_async_calls(cli)) {
2150 return NT_STATUS_INVALID_PARAMETER;
2152 ev = tevent_context_init(talloc_tos());
2153 if (ev == NULL) {
2154 goto fail;
2156 req = cli_ulogoff_send(ev, ev, cli);
2157 if (req == NULL) {
2158 goto fail;
2160 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2161 goto fail;
2163 status = cli_ulogoff_recv(req);
2164 fail:
2165 TALLOC_FREE(ev);
2166 return status;
2169 /****************************************************************************
2170 Send a tconX.
2171 ****************************************************************************/
2173 struct cli_tcon_andx_state {
2174 struct cli_state *cli;
2175 uint16_t vwv[4];
2176 struct iovec bytes;
2179 static void cli_tcon_andx_done(struct tevent_req *subreq);
2181 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2182 struct event_context *ev,
2183 struct cli_state *cli,
2184 const char *share, const char *dev,
2185 const char *pass, int passlen,
2186 struct tevent_req **psmbreq)
2188 struct tevent_req *req, *subreq;
2189 struct cli_tcon_andx_state *state;
2190 uint8_t p24[24];
2191 uint16_t *vwv;
2192 char *tmp = NULL;
2193 uint8_t *bytes;
2195 *psmbreq = NULL;
2197 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2198 if (req == NULL) {
2199 return NULL;
2201 state->cli = cli;
2202 vwv = state->vwv;
2204 cli->share = talloc_strdup(cli, share);
2205 if (!cli->share) {
2206 return NULL;
2209 /* in user level security don't send a password now */
2210 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2211 passlen = 1;
2212 pass = "";
2213 } else if (pass == NULL) {
2214 DEBUG(1, ("Server not using user level security and no "
2215 "password supplied.\n"));
2216 goto access_denied;
2219 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2220 *pass && passlen != 24) {
2221 if (!lp_client_lanman_auth()) {
2222 DEBUG(1, ("Server requested LANMAN password "
2223 "(share-level security) but "
2224 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2225 goto access_denied;
2229 * Non-encrypted passwords - convert to DOS codepage before
2230 * encryption.
2232 SMBencrypt(pass, cli->secblob.data, p24);
2233 passlen = 24;
2234 pass = (const char *)p24;
2235 } else {
2236 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2237 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2238 == 0) {
2239 uint8_t *tmp_pass;
2241 if (!lp_client_plaintext_auth() && (*pass)) {
2242 DEBUG(1, ("Server requested plaintext "
2243 "password but "
2244 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2245 goto access_denied;
2249 * Non-encrypted passwords - convert to DOS codepage
2250 * before using.
2252 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2253 if (tevent_req_nomem(tmp_pass, req)) {
2254 return tevent_req_post(req, ev);
2256 tmp_pass = trans2_bytes_push_str(tmp_pass,
2257 false, /* always DOS */
2258 pass,
2259 passlen,
2260 NULL);
2261 if (tevent_req_nomem(tmp_pass, req)) {
2262 return tevent_req_post(req, ev);
2264 pass = (const char *)tmp_pass;
2265 passlen = talloc_get_size(tmp_pass);
2269 SCVAL(vwv+0, 0, 0xFF);
2270 SCVAL(vwv+0, 1, 0);
2271 SSVAL(vwv+1, 0, 0);
2272 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2273 SSVAL(vwv+3, 0, passlen);
2275 if (passlen && pass) {
2276 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2277 } else {
2278 bytes = talloc_array(state, uint8_t, 0);
2282 * Add the sharename
2284 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2285 cli_state_remote_name(cli), share);
2286 if (tmp == NULL) {
2287 TALLOC_FREE(req);
2288 return NULL;
2290 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2291 NULL);
2292 TALLOC_FREE(tmp);
2295 * Add the devicetype
2297 tmp = talloc_strdup_upper(talloc_tos(), dev);
2298 if (tmp == NULL) {
2299 TALLOC_FREE(req);
2300 return NULL;
2302 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2303 TALLOC_FREE(tmp);
2305 if (bytes == NULL) {
2306 TALLOC_FREE(req);
2307 return NULL;
2310 state->bytes.iov_base = (void *)bytes;
2311 state->bytes.iov_len = talloc_get_size(bytes);
2313 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2314 1, &state->bytes);
2315 if (subreq == NULL) {
2316 TALLOC_FREE(req);
2317 return NULL;
2319 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2320 *psmbreq = subreq;
2321 return req;
2323 access_denied:
2324 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2325 return tevent_req_post(req, ev);
2328 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2329 struct event_context *ev,
2330 struct cli_state *cli,
2331 const char *share, const char *dev,
2332 const char *pass, int passlen)
2334 struct tevent_req *req, *subreq;
2335 NTSTATUS status;
2337 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2338 &subreq);
2339 if (req == NULL) {
2340 return NULL;
2342 if (subreq == NULL) {
2343 return req;
2345 status = cli_smb_req_send(subreq);
2346 if (!NT_STATUS_IS_OK(status)) {
2347 tevent_req_nterror(req, status);
2348 return tevent_req_post(req, ev);
2350 return req;
2353 static void cli_tcon_andx_done(struct tevent_req *subreq)
2355 struct tevent_req *req = tevent_req_callback_data(
2356 subreq, struct tevent_req);
2357 struct cli_tcon_andx_state *state = tevent_req_data(
2358 req, struct cli_tcon_andx_state);
2359 struct cli_state *cli = state->cli;
2360 uint8_t *in;
2361 char *inbuf;
2362 uint8_t wct;
2363 uint16_t *vwv;
2364 uint32_t num_bytes;
2365 uint8_t *bytes;
2366 NTSTATUS status;
2368 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2369 &num_bytes, &bytes);
2370 TALLOC_FREE(subreq);
2371 if (!NT_STATUS_IS_OK(status)) {
2372 tevent_req_nterror(req, status);
2373 return;
2376 inbuf = (char *)in;
2378 if (num_bytes) {
2379 if (clistr_pull_talloc(cli,
2380 inbuf,
2381 SVAL(inbuf, smb_flg2),
2382 &cli->dev,
2383 bytes,
2384 num_bytes,
2385 STR_TERMINATE|STR_ASCII) == -1) {
2386 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2387 return;
2389 } else {
2390 cli->dev = talloc_strdup(cli, "");
2391 if (cli->dev == NULL) {
2392 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2393 return;
2397 if ((cli_state_protocol(cli) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2398 /* almost certainly win95 - enable bug fixes */
2399 cli->win95 = True;
2403 * Make sure that we have the optional support 16-bit field. WCT > 2.
2404 * Avoids issues when connecting to Win9x boxes sharing files
2407 cli->dfsroot = false;
2409 if ((wct > 2) && (cli_state_protocol(cli) >= PROTOCOL_LANMAN2)) {
2410 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2413 cli->smb1.tid = SVAL(inbuf,smb_tid);
2414 tevent_req_done(req);
2417 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2419 return tevent_req_simple_recv_ntstatus(req);
2422 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2423 const char *dev, const char *pass, int passlen)
2425 TALLOC_CTX *frame = talloc_stackframe();
2426 struct event_context *ev;
2427 struct tevent_req *req;
2428 NTSTATUS status = NT_STATUS_OK;
2430 if (cli_has_async_calls(cli)) {
2432 * Can't use sync call while an async call is in flight
2434 status = NT_STATUS_INVALID_PARAMETER;
2435 goto fail;
2438 ev = event_context_init(frame);
2439 if (ev == NULL) {
2440 status = NT_STATUS_NO_MEMORY;
2441 goto fail;
2444 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2445 if (req == NULL) {
2446 status = NT_STATUS_NO_MEMORY;
2447 goto fail;
2450 if (!tevent_req_poll(req, ev)) {
2451 status = map_nt_error_from_unix(errno);
2452 goto fail;
2455 status = cli_tcon_andx_recv(req);
2456 fail:
2457 TALLOC_FREE(frame);
2458 return status;
2461 /****************************************************************************
2462 Send a tree disconnect.
2463 ****************************************************************************/
2465 struct cli_tdis_state {
2466 struct cli_state *cli;
2469 static void cli_tdis_done(struct tevent_req *subreq);
2471 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2472 struct tevent_context *ev,
2473 struct cli_state *cli)
2475 struct tevent_req *req, *subreq;
2476 struct cli_tdis_state *state;
2478 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2479 if (req == NULL) {
2480 return NULL;
2482 state->cli = cli;
2484 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2485 if (tevent_req_nomem(subreq, req)) {
2486 return tevent_req_post(req, ev);
2488 tevent_req_set_callback(subreq, cli_tdis_done, req);
2489 return req;
2492 static void cli_tdis_done(struct tevent_req *subreq)
2494 struct tevent_req *req = tevent_req_callback_data(
2495 subreq, struct tevent_req);
2496 struct cli_tdis_state *state = tevent_req_data(
2497 req, struct cli_tdis_state);
2498 NTSTATUS status;
2500 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2501 TALLOC_FREE(subreq);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 tevent_req_nterror(req, status);
2504 return;
2506 state->cli->smb1.tid = UINT16_MAX;
2507 tevent_req_done(req);
2510 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2512 return tevent_req_simple_recv_ntstatus(req);
2515 NTSTATUS cli_tdis(struct cli_state *cli)
2517 struct tevent_context *ev;
2518 struct tevent_req *req;
2519 NTSTATUS status = NT_STATUS_NO_MEMORY;
2521 if (cli_has_async_calls(cli)) {
2522 return NT_STATUS_INVALID_PARAMETER;
2524 ev = tevent_context_init(talloc_tos());
2525 if (ev == NULL) {
2526 goto fail;
2528 req = cli_tdis_send(ev, ev, cli);
2529 if (req == NULL) {
2530 goto fail;
2532 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2533 goto fail;
2535 status = cli_tdis_recv(req);
2536 fail:
2537 TALLOC_FREE(ev);
2538 return status;
2541 /****************************************************************************
2542 Send a negprot command.
2543 ****************************************************************************/
2545 struct cli_negprot_state {
2546 struct cli_state *cli;
2549 static void cli_negprot_done(struct tevent_req *subreq);
2551 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2552 struct event_context *ev,
2553 struct cli_state *cli)
2555 struct tevent_req *req, *subreq;
2556 struct cli_negprot_state *state;
2557 uint8_t *bytes = NULL;
2558 int numprots;
2560 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2561 if (req == NULL) {
2562 return NULL;
2564 state->cli = cli;
2566 if (cli_state_protocol(cli) < PROTOCOL_NT1)
2567 cli->use_spnego = False;
2569 /* setup the protocol strings */
2570 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2571 uint8_t c = 2;
2572 if (prots[numprots].prot > cli_state_protocol(cli)) {
2573 break;
2575 bytes = (uint8_t *)talloc_append_blob(
2576 state, bytes, data_blob_const(&c, sizeof(c)));
2577 if (tevent_req_nomem(bytes, req)) {
2578 return tevent_req_post(req, ev);
2580 bytes = smb_bytes_push_str(bytes, false,
2581 prots[numprots].name,
2582 strlen(prots[numprots].name)+1,
2583 NULL);
2584 if (tevent_req_nomem(bytes, req)) {
2585 return tevent_req_post(req, ev);
2589 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2590 talloc_get_size(bytes), bytes);
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_state_protocol(cli))) {
2626 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2627 return;
2630 cli->protocol = prots[protnum].prot;
2632 if ((cli_state_protocol(cli) < 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_state_protocol(cli) >= 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_state_capabilities(cli) & 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_state_capabilities(cli) & 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_state_protocol(cli) >= 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, const struct sockaddr_storage *dest_ss,
2848 uint16_t port, int name_type, const char *myname,
2849 int signing_state, int flags, 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;
2858 desthost = talloc_strdup(talloc_tos(), host);
2859 if (desthost == NULL) {
2860 goto fail;
2863 p = strchr(host, '#');
2864 if (p != NULL) {
2865 name_type = strtol(p+1, NULL, 16);
2866 host = talloc_strndup(talloc_tos(), host, p - host);
2867 if (host == NULL) {
2868 goto fail;
2872 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
2873 20, &fd, &port);
2874 if (!NT_STATUS_IS_OK(status)) {
2875 goto fail;
2878 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
2879 if (cli == NULL) {
2880 goto fail;
2883 *pcli = cli;
2884 status = NT_STATUS_OK;
2885 fail:
2886 TALLOC_FREE(frame);
2887 return status;
2891 establishes a connection to after the negprot.
2892 @param output_cli A fully initialised cli structure, non-null only on success
2893 @param dest_host The netbios name of the remote host
2894 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2895 @param port (optional) The destination port (0 for default)
2897 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2898 const char *my_name,
2899 const char *dest_host,
2900 const struct sockaddr_storage *dest_ss, int port,
2901 int signing_state, int flags)
2903 NTSTATUS nt_status;
2904 struct cli_state *cli;
2906 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2907 signing_state, flags, &cli);
2908 if (!NT_STATUS_IS_OK(nt_status)) {
2909 DEBUG(10, ("cli_connect_nb failed: %s\n",
2910 nt_errstr(nt_status)));
2911 return nt_status;
2914 nt_status = cli_negprot(cli);
2915 if (!NT_STATUS_IS_OK(nt_status)) {
2916 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2917 cli_shutdown(cli);
2918 return nt_status;
2921 *output_cli = cli;
2922 return NT_STATUS_OK;
2927 establishes a connection right up to doing tconX, password specified.
2928 @param output_cli A fully initialised cli structure, non-null only on success
2929 @param dest_host The netbios name of the remote host
2930 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2931 @param port (optional) The destination port (0 for default)
2932 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2933 @param service_type The 'type' of serivice.
2934 @param user Username, unix string
2935 @param domain User's domain
2936 @param password User's password, unencrypted unix string.
2939 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2940 const char *my_name,
2941 const char *dest_host,
2942 const struct sockaddr_storage *dest_ss, int port,
2943 const char *service, const char *service_type,
2944 const char *user, const char *domain,
2945 const char *password, int flags,
2946 int signing_state)
2948 NTSTATUS nt_status;
2949 struct cli_state *cli = NULL;
2950 int pw_len = password ? strlen(password)+1 : 0;
2952 *output_cli = NULL;
2954 if (password == NULL) {
2955 password = "";
2958 nt_status = cli_start_connection(&cli, my_name, dest_host,
2959 dest_ss, port, signing_state,
2960 flags);
2962 if (!NT_STATUS_IS_OK(nt_status)) {
2963 return nt_status;
2966 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2967 cli->use_level_II_oplocks =
2968 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2970 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2971 pw_len, domain);
2972 if (!NT_STATUS_IS_OK(nt_status)) {
2974 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2975 DEBUG(1,("failed session setup with %s\n",
2976 nt_errstr(nt_status)));
2977 cli_shutdown(cli);
2978 return nt_status;
2981 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2982 if (!NT_STATUS_IS_OK(nt_status)) {
2983 DEBUG(1,("anonymous failed session setup with %s\n",
2984 nt_errstr(nt_status)));
2985 cli_shutdown(cli);
2986 return nt_status;
2990 if (service) {
2991 nt_status = cli_tcon_andx(cli, service, service_type, password,
2992 pw_len);
2993 if (!NT_STATUS_IS_OK(nt_status)) {
2994 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2995 cli_shutdown(cli);
2996 if (NT_STATUS_IS_OK(nt_status)) {
2997 nt_status = NT_STATUS_UNSUCCESSFUL;
2999 return nt_status;
3003 nt_status = cli_init_creds(cli, user, domain, password);
3004 if (!NT_STATUS_IS_OK(nt_status)) {
3005 cli_shutdown(cli);
3006 return nt_status;
3009 *output_cli = cli;
3010 return NT_STATUS_OK;
3013 /****************************************************************************
3014 Send an old style tcon.
3015 ****************************************************************************/
3016 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3017 const char *service, const char *pass, const char *dev,
3018 uint16 *max_xmit, uint16 *tid)
3020 struct tevent_req *req;
3021 uint16_t *ret_vwv;
3022 uint8_t *bytes;
3023 NTSTATUS status;
3025 if (!lp_client_plaintext_auth() && (*pass)) {
3026 DEBUG(1, ("Server requested plaintext password but 'client "
3027 "plaintext auth' is disabled\n"));
3028 return NT_STATUS_ACCESS_DENIED;
3031 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3032 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3033 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3034 service, strlen(service)+1, NULL);
3035 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3036 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3037 pass, strlen(pass)+1, NULL);
3038 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3039 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3040 dev, strlen(dev)+1, NULL);
3042 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3043 talloc_get_size(bytes), bytes, &req,
3044 2, NULL, &ret_vwv, NULL, NULL);
3045 if (!NT_STATUS_IS_OK(status)) {
3046 return status;
3049 *max_xmit = SVAL(ret_vwv + 0, 0);
3050 *tid = SVAL(ret_vwv + 1, 0);
3052 return NT_STATUS_OK;
3055 /* Return a cli_state pointing at the IPC$ share for the given server */
3057 struct cli_state *get_ipc_connect(char *server,
3058 struct sockaddr_storage *server_ss,
3059 const struct user_auth_info *user_info)
3061 struct cli_state *cli;
3062 NTSTATUS nt_status;
3063 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3065 if (user_info->use_kerberos) {
3066 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3069 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3070 user_info->username ? user_info->username : "",
3071 lp_workgroup(),
3072 user_info->password ? user_info->password : "",
3073 flags,
3074 Undefined);
3076 if (NT_STATUS_IS_OK(nt_status)) {
3077 return cli;
3078 } else if (is_ipaddress(server)) {
3079 /* windows 9* needs a correct NMB name for connections */
3080 fstring remote_name;
3082 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3083 cli = get_ipc_connect(remote_name, server_ss, user_info);
3084 if (cli)
3085 return cli;
3088 return NULL;
3092 * Given the IP address of a master browser on the network, return its
3093 * workgroup and connect to it.
3095 * This function is provided to allow additional processing beyond what
3096 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3097 * browsers and obtain each master browsers' list of domains (in case the
3098 * first master browser is recently on the network and has not yet
3099 * synchronized with other master browsers and therefore does not yet have the
3100 * entire network browse list)
3103 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3104 struct sockaddr_storage *mb_ip,
3105 const struct user_auth_info *user_info,
3106 char **pp_workgroup_out)
3108 char addr[INET6_ADDRSTRLEN];
3109 fstring name;
3110 struct cli_state *cli;
3111 struct sockaddr_storage server_ss;
3113 *pp_workgroup_out = NULL;
3115 print_sockaddr(addr, sizeof(addr), mb_ip);
3116 DEBUG(99, ("Looking up name of master browser %s\n",
3117 addr));
3120 * Do a name status query to find out the name of the master browser.
3121 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3122 * master browser will not respond to a wildcard query (or, at least,
3123 * an NT4 server acting as the domain master browser will not).
3125 * We might be able to use ONLY the query on MSBROWSE, but that's not
3126 * yet been tested with all Windows versions, so until it is, leave
3127 * the original wildcard query as the first choice and fall back to
3128 * MSBROWSE if the wildcard query fails.
3130 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3131 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3133 DEBUG(99, ("Could not retrieve name status for %s\n",
3134 addr));
3135 return NULL;
3138 if (!find_master_ip(name, &server_ss)) {
3139 DEBUG(99, ("Could not find master ip for %s\n", name));
3140 return NULL;
3143 *pp_workgroup_out = talloc_strdup(ctx, name);
3145 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3147 print_sockaddr(addr, sizeof(addr), &server_ss);
3148 cli = get_ipc_connect(addr, &server_ss, user_info);
3150 return cli;
3154 * Return the IP address and workgroup of a master browser on the network, and
3155 * connect to it.
3158 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3159 const struct user_auth_info *user_info,
3160 char **pp_workgroup_out)
3162 struct sockaddr_storage *ip_list;
3163 struct cli_state *cli;
3164 int i, count;
3165 NTSTATUS status;
3167 *pp_workgroup_out = NULL;
3169 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3171 /* Go looking for workgroups by broadcasting on the local network */
3173 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3174 &ip_list, &count);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 DEBUG(99, ("No master browsers responded: %s\n",
3177 nt_errstr(status)));
3178 return False;
3181 for (i = 0; i < count; i++) {
3182 char addr[INET6_ADDRSTRLEN];
3183 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3184 DEBUG(99, ("Found master browser %s\n", addr));
3186 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3187 user_info, pp_workgroup_out);
3188 if (cli)
3189 return(cli);
3192 return NULL;