s3:libsmb: move cli->vuid to cli->smb1.uid and hide it behind cli_state_[g|s]et_uid()
[Samba/gbeck.git] / source3 / libsmb / cliconnect.c
blob9b9d7512849539cf8994b1fde42563a48bfac6d7
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->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_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. 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_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 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 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
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->smb1.tid = 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->smb1.tid = UINT16_MAX;
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;
2555 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2556 if (req == NULL) {
2557 return NULL;
2559 state->cli = cli;
2561 if (cli->protocol < PROTOCOL_NT1)
2562 cli->use_spnego = False;
2564 /* setup the protocol strings */
2565 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2566 uint8_t c = 2;
2567 if (prots[numprots].prot > cli->protocol) {
2568 break;
2570 bytes = (uint8_t *)talloc_append_blob(
2571 state, bytes, data_blob_const(&c, sizeof(c)));
2572 if (tevent_req_nomem(bytes, req)) {
2573 return tevent_req_post(req, ev);
2575 bytes = smb_bytes_push_str(bytes, false,
2576 prots[numprots].name,
2577 strlen(prots[numprots].name)+1,
2578 NULL);
2579 if (tevent_req_nomem(bytes, req)) {
2580 return tevent_req_post(req, ev);
2584 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2585 talloc_get_size(bytes), bytes);
2587 if (tevent_req_nomem(subreq, req)) {
2588 return tevent_req_post(req, ev);
2590 tevent_req_set_callback(subreq, cli_negprot_done, req);
2591 return req;
2594 static void cli_negprot_done(struct tevent_req *subreq)
2596 struct tevent_req *req = tevent_req_callback_data(
2597 subreq, struct tevent_req);
2598 struct cli_negprot_state *state = tevent_req_data(
2599 req, struct cli_negprot_state);
2600 struct cli_state *cli = state->cli;
2601 uint8_t wct;
2602 uint16_t *vwv;
2603 uint32_t num_bytes;
2604 uint8_t *bytes;
2605 NTSTATUS status;
2606 uint16_t protnum;
2607 uint8_t *inbuf;
2609 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2610 &num_bytes, &bytes);
2611 TALLOC_FREE(subreq);
2612 if (!NT_STATUS_IS_OK(status)) {
2613 tevent_req_nterror(req, status);
2614 return;
2617 protnum = SVAL(vwv, 0);
2619 if ((protnum >= ARRAY_SIZE(prots))
2620 || (prots[protnum].prot > cli->protocol)) {
2621 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2622 return;
2625 cli->protocol = prots[protnum].prot;
2627 if ((cli->protocol < PROTOCOL_NT1) &&
2628 client_is_signing_mandatory(cli)) {
2629 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2630 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2631 return;
2634 if (cli->protocol >= PROTOCOL_NT1) {
2635 struct timespec ts;
2636 bool negotiated_smb_signing = false;
2638 /* NT protocol */
2639 cli->sec_mode = CVAL(vwv + 1, 0);
2640 cli->max_mux = SVAL(vwv + 1, 1);
2641 cli->max_xmit = IVAL(vwv + 3, 1);
2642 cli->sesskey = IVAL(vwv + 7, 1);
2643 cli->serverzone = SVALS(vwv + 15, 1);
2644 cli->serverzone *= 60;
2645 /* this time arrives in real GMT */
2646 ts = interpret_long_date(((char *)(vwv+11))+1);
2647 cli->servertime = ts.tv_sec;
2648 cli->secblob = data_blob(bytes, num_bytes);
2649 cli->capabilities = IVAL(vwv + 9, 1);
2650 if (cli->capabilities & CAP_RAW_MODE) {
2651 cli->readbraw_supported = True;
2652 cli->writebraw_supported = True;
2654 /* work out if they sent us a workgroup */
2655 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2656 smb_buflen(inbuf) > 8) {
2657 ssize_t ret;
2658 status = smb_bytes_talloc_string(
2659 cli, (char *)inbuf, &cli->server_domain,
2660 bytes + 8, num_bytes - 8, &ret);
2661 if (tevent_req_nterror(req, status)) {
2662 return;
2667 * As signing is slow we only turn it on if either the client or
2668 * the server require it. JRA.
2671 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2672 /* Fail if server says signing is mandatory and we don't want to support it. */
2673 if (!client_is_signing_allowed(cli)) {
2674 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2675 tevent_req_nterror(req,
2676 NT_STATUS_ACCESS_DENIED);
2677 return;
2679 negotiated_smb_signing = true;
2680 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2681 /* Fail if client says signing is mandatory and the server doesn't support it. */
2682 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2683 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2684 tevent_req_nterror(req,
2685 NT_STATUS_ACCESS_DENIED);
2686 return;
2688 negotiated_smb_signing = true;
2689 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2690 negotiated_smb_signing = true;
2693 if (negotiated_smb_signing) {
2694 cli_set_signing_negotiated(cli);
2697 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2698 cli->use_spnego = False;
2699 cli->sec_mode = SVAL(vwv + 1, 0);
2700 cli->max_xmit = SVAL(vwv + 2, 0);
2701 cli->max_mux = SVAL(vwv + 3, 0);
2702 cli->sesskey = IVAL(vwv + 6, 0);
2703 cli->serverzone = SVALS(vwv + 10, 0);
2704 cli->serverzone *= 60;
2705 /* this time is converted to GMT by make_unix_date */
2706 cli->servertime = make_unix_date(
2707 (char *)(vwv + 8), cli->serverzone);
2708 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2709 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2710 cli->secblob = data_blob(bytes, num_bytes);
2711 } else {
2712 /* the old core protocol */
2713 cli->use_spnego = False;
2714 cli->sec_mode = 0;
2715 cli->serverzone = get_time_zone(time(NULL));
2718 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2720 /* a way to force ascii SMB */
2721 if (getenv("CLI_FORCE_ASCII"))
2722 cli->capabilities &= ~CAP_UNICODE;
2724 tevent_req_done(req);
2727 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2729 return tevent_req_simple_recv_ntstatus(req);
2732 NTSTATUS cli_negprot(struct cli_state *cli)
2734 TALLOC_CTX *frame = talloc_stackframe();
2735 struct event_context *ev;
2736 struct tevent_req *req;
2737 NTSTATUS status = NT_STATUS_OK;
2739 if (cli_has_async_calls(cli)) {
2741 * Can't use sync call while an async call is in flight
2743 status = NT_STATUS_INVALID_PARAMETER;
2744 goto fail;
2747 ev = event_context_init(frame);
2748 if (ev == NULL) {
2749 status = NT_STATUS_NO_MEMORY;
2750 goto fail;
2753 req = cli_negprot_send(frame, ev, cli);
2754 if (req == NULL) {
2755 status = NT_STATUS_NO_MEMORY;
2756 goto fail;
2759 if (!tevent_req_poll(req, ev)) {
2760 status = map_nt_error_from_unix(errno);
2761 goto fail;
2764 status = cli_negprot_recv(req);
2765 fail:
2766 TALLOC_FREE(frame);
2767 return status;
2770 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2771 const struct sockaddr_storage *pss,
2772 const char *myname, uint16_t port,
2773 int sec_timeout, int *pfd, uint16_t *pport)
2775 TALLOC_CTX *frame = talloc_stackframe();
2776 const char *prog;
2777 unsigned int i, num_addrs;
2778 const char **called_names;
2779 const char **calling_names;
2780 int *called_types;
2781 NTSTATUS status;
2782 int fd;
2784 prog = getenv("LIBSMB_PROG");
2785 if (prog != NULL) {
2786 fd = sock_exec(prog);
2787 if (fd == -1) {
2788 return map_nt_error_from_unix(errno);
2790 port = 0;
2791 goto done;
2794 if ((pss == NULL) || is_zero_addr(pss)) {
2795 struct sockaddr_storage *addrs;
2796 status = resolve_name_list(talloc_tos(), host, name_type,
2797 &addrs, &num_addrs);
2798 if (!NT_STATUS_IS_OK(status)) {
2799 goto fail;
2801 pss = addrs;
2802 } else {
2803 num_addrs = 1;
2806 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2807 if (called_names == NULL) {
2808 status = NT_STATUS_NO_MEMORY;
2809 goto fail;
2811 called_types = talloc_array(talloc_tos(), int, num_addrs);
2812 if (called_types == NULL) {
2813 status = NT_STATUS_NO_MEMORY;
2814 goto fail;
2816 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2817 if (calling_names == NULL) {
2818 status = NT_STATUS_NO_MEMORY;
2819 goto fail;
2821 for (i=0; i<num_addrs; i++) {
2822 called_names[i] = host;
2823 called_types[i] = name_type;
2824 calling_names[i] = myname;
2826 status = smbsock_any_connect(pss, called_names, called_types,
2827 calling_names, NULL, num_addrs, port,
2828 sec_timeout, &fd, NULL, &port);
2829 if (!NT_STATUS_IS_OK(status)) {
2830 goto fail;
2832 set_socket_options(fd, lp_socket_options());
2833 done:
2834 *pfd = fd;
2835 *pport = port;
2836 status = NT_STATUS_OK;
2837 fail:
2838 TALLOC_FREE(frame);
2839 return status;
2842 NTSTATUS cli_connect_nb(const char *host, struct sockaddr_storage *pss,
2843 uint16_t port, int name_type, const char *myname,
2844 int signing_state, struct cli_state **pcli)
2846 TALLOC_CTX *frame = talloc_stackframe();
2847 struct cli_state *cli;
2848 NTSTATUS status = NT_STATUS_NO_MEMORY;
2849 int fd = -1;
2850 char *desthost;
2851 char *p;
2852 socklen_t length;
2853 int ret;
2855 desthost = talloc_strdup(talloc_tos(), host);
2856 if (desthost == NULL) {
2857 goto fail;
2860 p = strchr(host, '#');
2861 if (p != NULL) {
2862 name_type = strtol(p+1, NULL, 16);
2863 host = talloc_strndup(talloc_tos(), host, p - host);
2864 if (host == NULL) {
2865 goto fail;
2869 cli = cli_initialise_ex(signing_state);
2870 if (cli == NULL) {
2871 goto fail;
2873 cli->desthost = talloc_move(cli, &desthost);
2875 status = cli_connect_sock(host, name_type, pss, myname, port, 20, &fd,
2876 &port);
2877 if (!NT_STATUS_IS_OK(status)) {
2878 cli_shutdown(cli);
2879 goto fail;
2881 cli->fd = fd;
2883 length = sizeof(cli->src_ss);
2884 ret = getsockname(fd, (struct sockaddr *)(void *)&cli->src_ss,
2885 &length);
2886 if (ret == -1) {
2887 status = map_nt_error_from_unix(errno);
2888 cli_shutdown(cli);
2889 goto fail;
2891 length = sizeof(cli->dest_ss);
2892 ret = getpeername(fd, (struct sockaddr *)(void *)&cli->dest_ss,
2893 &length);
2894 if (ret == -1) {
2895 status = map_nt_error_from_unix(errno);
2896 cli_shutdown(cli);
2897 goto fail;
2900 if (pss != NULL) {
2901 *pss = cli->dest_ss;
2904 *pcli = cli;
2905 status = NT_STATUS_OK;
2906 fail:
2907 TALLOC_FREE(frame);
2908 return status;
2912 establishes a connection to after the negprot.
2913 @param output_cli A fully initialised cli structure, non-null only on success
2914 @param dest_host The netbios name of the remote host
2915 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2916 @param port (optional) The destination port (0 for default)
2918 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2919 const char *my_name,
2920 const char *dest_host,
2921 struct sockaddr_storage *dest_ss, int port,
2922 int signing_state, int flags)
2924 NTSTATUS nt_status;
2925 struct cli_state *cli;
2927 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2928 signing_state, &cli);
2929 if (!NT_STATUS_IS_OK(nt_status)) {
2930 DEBUG(10, ("cli_connect_nb failed: %s\n",
2931 nt_errstr(nt_status)));
2932 return nt_status;
2935 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2936 cli->use_spnego = False;
2937 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2938 cli->use_kerberos = True;
2940 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2941 cli->use_kerberos) {
2942 cli->fallback_after_kerberos = true;
2944 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2945 cli->use_ccache = true;
2948 nt_status = cli_negprot(cli);
2949 if (!NT_STATUS_IS_OK(nt_status)) {
2950 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2951 cli_shutdown(cli);
2952 return nt_status;
2955 *output_cli = cli;
2956 return NT_STATUS_OK;
2961 establishes a connection right up to doing tconX, password specified.
2962 @param output_cli A fully initialised cli structure, non-null only on success
2963 @param dest_host The netbios name of the remote host
2964 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2965 @param port (optional) The destination port (0 for default)
2966 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2967 @param service_type The 'type' of serivice.
2968 @param user Username, unix string
2969 @param domain User's domain
2970 @param password User's password, unencrypted unix string.
2973 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2974 const char *my_name,
2975 const char *dest_host,
2976 struct sockaddr_storage *dest_ss, int port,
2977 const char *service, const char *service_type,
2978 const char *user, const char *domain,
2979 const char *password, int flags,
2980 int signing_state)
2982 NTSTATUS nt_status;
2983 struct cli_state *cli = NULL;
2984 int pw_len = password ? strlen(password)+1 : 0;
2986 *output_cli = NULL;
2988 if (password == NULL) {
2989 password = "";
2992 nt_status = cli_start_connection(&cli, my_name, dest_host,
2993 dest_ss, port, signing_state,
2994 flags);
2996 if (!NT_STATUS_IS_OK(nt_status)) {
2997 return nt_status;
3000 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3001 cli->use_level_II_oplocks =
3002 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3004 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3005 pw_len, domain);
3006 if (!NT_STATUS_IS_OK(nt_status)) {
3008 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3009 DEBUG(1,("failed session setup with %s\n",
3010 nt_errstr(nt_status)));
3011 cli_shutdown(cli);
3012 return nt_status;
3015 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3016 if (!NT_STATUS_IS_OK(nt_status)) {
3017 DEBUG(1,("anonymous failed session setup with %s\n",
3018 nt_errstr(nt_status)));
3019 cli_shutdown(cli);
3020 return nt_status;
3024 if (service) {
3025 nt_status = cli_tcon_andx(cli, service, service_type, password,
3026 pw_len);
3027 if (!NT_STATUS_IS_OK(nt_status)) {
3028 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3029 cli_shutdown(cli);
3030 if (NT_STATUS_IS_OK(nt_status)) {
3031 nt_status = NT_STATUS_UNSUCCESSFUL;
3033 return nt_status;
3037 nt_status = cli_init_creds(cli, user, domain, password);
3038 if (!NT_STATUS_IS_OK(nt_status)) {
3039 cli_shutdown(cli);
3040 return nt_status;
3043 *output_cli = cli;
3044 return NT_STATUS_OK;
3047 /****************************************************************************
3048 Send an old style tcon.
3049 ****************************************************************************/
3050 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3051 const char *service, const char *pass, const char *dev,
3052 uint16 *max_xmit, uint16 *tid)
3054 struct tevent_req *req;
3055 uint16_t *ret_vwv;
3056 uint8_t *bytes;
3057 NTSTATUS status;
3059 if (!lp_client_plaintext_auth() && (*pass)) {
3060 DEBUG(1, ("Server requested plaintext password but 'client "
3061 "plaintext auth' is disabled\n"));
3062 return NT_STATUS_ACCESS_DENIED;
3065 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3066 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3067 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3068 service, strlen(service)+1, NULL);
3069 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3070 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3071 pass, strlen(pass)+1, NULL);
3072 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3073 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3074 dev, strlen(dev)+1, NULL);
3076 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3077 talloc_get_size(bytes), bytes, &req,
3078 2, NULL, &ret_vwv, NULL, NULL);
3079 if (!NT_STATUS_IS_OK(status)) {
3080 return status;
3083 *max_xmit = SVAL(ret_vwv + 0, 0);
3084 *tid = SVAL(ret_vwv + 1, 0);
3086 return NT_STATUS_OK;
3089 /* Return a cli_state pointing at the IPC$ share for the given server */
3091 struct cli_state *get_ipc_connect(char *server,
3092 struct sockaddr_storage *server_ss,
3093 const struct user_auth_info *user_info)
3095 struct cli_state *cli;
3096 NTSTATUS nt_status;
3097 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3099 if (user_info->use_kerberos) {
3100 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3103 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3104 user_info->username ? user_info->username : "",
3105 lp_workgroup(),
3106 user_info->password ? user_info->password : "",
3107 flags,
3108 Undefined);
3110 if (NT_STATUS_IS_OK(nt_status)) {
3111 return cli;
3112 } else if (is_ipaddress(server)) {
3113 /* windows 9* needs a correct NMB name for connections */
3114 fstring remote_name;
3116 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3117 cli = get_ipc_connect(remote_name, server_ss, user_info);
3118 if (cli)
3119 return cli;
3122 return NULL;
3126 * Given the IP address of a master browser on the network, return its
3127 * workgroup and connect to it.
3129 * This function is provided to allow additional processing beyond what
3130 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3131 * browsers and obtain each master browsers' list of domains (in case the
3132 * first master browser is recently on the network and has not yet
3133 * synchronized with other master browsers and therefore does not yet have the
3134 * entire network browse list)
3137 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3138 struct sockaddr_storage *mb_ip,
3139 const struct user_auth_info *user_info,
3140 char **pp_workgroup_out)
3142 char addr[INET6_ADDRSTRLEN];
3143 fstring name;
3144 struct cli_state *cli;
3145 struct sockaddr_storage server_ss;
3147 *pp_workgroup_out = NULL;
3149 print_sockaddr(addr, sizeof(addr), mb_ip);
3150 DEBUG(99, ("Looking up name of master browser %s\n",
3151 addr));
3154 * Do a name status query to find out the name of the master browser.
3155 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3156 * master browser will not respond to a wildcard query (or, at least,
3157 * an NT4 server acting as the domain master browser will not).
3159 * We might be able to use ONLY the query on MSBROWSE, but that's not
3160 * yet been tested with all Windows versions, so until it is, leave
3161 * the original wildcard query as the first choice and fall back to
3162 * MSBROWSE if the wildcard query fails.
3164 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3165 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3167 DEBUG(99, ("Could not retrieve name status for %s\n",
3168 addr));
3169 return NULL;
3172 if (!find_master_ip(name, &server_ss)) {
3173 DEBUG(99, ("Could not find master ip for %s\n", name));
3174 return NULL;
3177 *pp_workgroup_out = talloc_strdup(ctx, name);
3179 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3181 print_sockaddr(addr, sizeof(addr), &server_ss);
3182 cli = get_ipc_connect(addr, &server_ss, user_info);
3184 return cli;
3188 * Return the IP address and workgroup of a master browser on the network, and
3189 * connect to it.
3192 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3193 const struct user_auth_info *user_info,
3194 char **pp_workgroup_out)
3196 struct sockaddr_storage *ip_list;
3197 struct cli_state *cli;
3198 int i, count;
3199 NTSTATUS status;
3201 *pp_workgroup_out = NULL;
3203 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3205 /* Go looking for workgroups by broadcasting on the local network */
3207 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3208 &ip_list, &count);
3209 if (!NT_STATUS_IS_OK(status)) {
3210 DEBUG(99, ("No master browsers responded: %s\n",
3211 nt_errstr(status)));
3212 return False;
3215 for (i = 0; i < count; i++) {
3216 char addr[INET6_ADDRSTRLEN];
3217 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3218 DEBUG(99, ("Found master browser %s\n", addr));
3220 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3221 user_info, pp_workgroup_out);
3222 if (cli)
3223 return(cli);
3226 return NULL;