s3:utils change data_blob_dup_talloc() to take a DATA_BLOB by value
[Samba/bb.git] / source3 / libsmb / cliconnect.c
blobbba7b0323abebbc38f70b510d9f59eb53b79c2b9
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"
36 #include "librpc/ndr/libndr.h"
38 static const struct {
39 int prot;
40 const char name[24];
41 } prots[10] = {
42 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
43 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
44 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
45 {PROTOCOL_LANMAN1, "LANMAN1.0"},
46 {PROTOCOL_LANMAN2, "LM1.2X002"},
47 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
48 {PROTOCOL_LANMAN2, "LANMAN2.1"},
49 {PROTOCOL_LANMAN2, "Samba"},
50 {PROTOCOL_NT1, "NT LANMAN 1.0"},
51 {PROTOCOL_NT1, "NT LM 0.12"},
54 #define STAR_SMBSERVER "*SMBSERVER"
56 /********************************************************
57 Utility function to ensure we always return at least
58 a valid char * pointer to an empty string for the
59 cli->server_os, cli->server_type and cli->server_domain
60 strings.
61 *******************************************************/
63 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
64 char *inbuf,
65 char **dest,
66 uint8_t *src,
67 size_t srclen,
68 ssize_t *destlen)
70 *destlen = clistr_pull_talloc(mem_ctx,
71 inbuf,
72 SVAL(inbuf, smb_flg2),
73 dest,
74 (char *)src,
75 srclen,
76 STR_TERMINATE);
77 if (*destlen == -1) {
78 return NT_STATUS_NO_MEMORY;
81 if (*dest == NULL) {
82 *dest = talloc_strdup(mem_ctx, "");
83 if (*dest == NULL) {
84 return NT_STATUS_NO_MEMORY;
87 return NT_STATUS_OK;
90 /**
91 * Set the user session key for a connection
92 * @param cli The cli structure to add it too
93 * @param session_key The session key used. (A copy of this is taken for the cli struct)
97 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
99 cli->user_session_key = data_blob(session_key.data, session_key.length);
102 /****************************************************************************
103 Do an old lanman2 style session setup.
104 ****************************************************************************/
106 struct cli_session_setup_lanman2_state {
107 struct cli_state *cli;
108 uint16_t vwv[10];
109 const char *user;
112 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
114 static struct tevent_req *cli_session_setup_lanman2_send(
115 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
116 struct cli_state *cli, const char *user,
117 const char *pass, size_t passlen,
118 const char *workgroup)
120 struct tevent_req *req, *subreq;
121 struct cli_session_setup_lanman2_state *state;
122 DATA_BLOB lm_response = data_blob_null;
123 uint16_t *vwv;
124 uint8_t *bytes;
125 char *tmp;
126 uint16_t sec_mode = cli_state_security_mode(cli);
128 req = tevent_req_create(mem_ctx, &state,
129 struct cli_session_setup_lanman2_state);
130 if (req == NULL) {
131 return NULL;
133 state->cli = cli;
134 state->user = user;
135 vwv = state->vwv;
138 * if in share level security then don't send a password now
140 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
141 passlen = 0;
144 if (passlen > 0
145 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
146 && passlen != 24) {
148 * Encrypted mode needed, and non encrypted password
149 * supplied.
151 lm_response = data_blob(NULL, 24);
152 if (tevent_req_nomem(lm_response.data, req)) {
153 return tevent_req_post(req, ev);
156 if (!SMBencrypt(pass, cli_state_server_challenge(cli),
157 (uint8_t *)lm_response.data)) {
158 DEBUG(1, ("Password is > 14 chars in length, and is "
159 "therefore incompatible with Lanman "
160 "authentication\n"));
161 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
162 return tevent_req_post(req, ev);
164 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
165 && passlen == 24) {
167 * Encrypted mode needed, and encrypted password
168 * supplied.
170 lm_response = data_blob(pass, passlen);
171 if (tevent_req_nomem(lm_response.data, req)) {
172 return tevent_req_post(req, ev);
174 } else if (passlen > 0) {
175 uint8_t *buf;
176 size_t converted_size;
178 * Plaintext mode needed, assume plaintext supplied.
180 buf = talloc_array(talloc_tos(), uint8_t, 0);
181 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
182 &converted_size);
183 if (tevent_req_nomem(buf, req)) {
184 return tevent_req_post(req, ev);
186 lm_response = data_blob(pass, passlen);
187 TALLOC_FREE(buf);
188 if (tevent_req_nomem(lm_response.data, req)) {
189 return tevent_req_post(req, ev);
193 SCVAL(vwv+0, 0, 0xff);
194 SCVAL(vwv+0, 1, 0);
195 SSVAL(vwv+1, 0, 0);
196 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
197 SSVAL(vwv+3, 0, 2);
198 SSVAL(vwv+4, 0, 1);
199 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
200 SSVAL(vwv+7, 0, lm_response.length);
202 bytes = talloc_array(state, uint8_t, lm_response.length);
203 if (tevent_req_nomem(bytes, req)) {
204 return tevent_req_post(req, ev);
206 if (lm_response.length != 0) {
207 memcpy(bytes, lm_response.data, lm_response.length);
209 data_blob_free(&lm_response);
211 tmp = talloc_strdup_upper(talloc_tos(), user);
212 if (tevent_req_nomem(tmp, req)) {
213 return tevent_req_post(req, ev);
215 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
216 NULL);
217 TALLOC_FREE(tmp);
219 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
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 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
226 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
228 if (tevent_req_nomem(bytes, req)) {
229 return tevent_req_post(req, ev);
232 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
233 talloc_get_size(bytes), bytes);
234 if (tevent_req_nomem(subreq, req)) {
235 return tevent_req_post(req, ev);
237 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
238 return req;
241 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
243 struct tevent_req *req = tevent_req_callback_data(
244 subreq, struct tevent_req);
245 struct cli_session_setup_lanman2_state *state = tevent_req_data(
246 req, struct cli_session_setup_lanman2_state);
247 struct cli_state *cli = state->cli;
248 uint32_t num_bytes;
249 uint8_t *in;
250 char *inbuf;
251 uint8_t *bytes;
252 uint8_t *p;
253 NTSTATUS status;
254 ssize_t ret;
255 uint8_t wct;
256 uint16_t *vwv;
258 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
259 &num_bytes, &bytes);
260 TALLOC_FREE(subreq);
261 if (!NT_STATUS_IS_OK(status)) {
262 tevent_req_nterror(req, status);
263 return;
266 inbuf = (char *)in;
267 p = bytes;
269 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
270 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
272 status = smb_bytes_talloc_string(cli,
273 inbuf,
274 &cli->server_os,
276 bytes+num_bytes-p,
277 &ret);
279 if (!NT_STATUS_IS_OK(status)) {
280 tevent_req_nterror(req, status);
281 return;
283 p += ret;
285 status = smb_bytes_talloc_string(cli,
286 inbuf,
287 &cli->server_type,
289 bytes+num_bytes-p,
290 &ret);
292 if (!NT_STATUS_IS_OK(status)) {
293 tevent_req_nterror(req, status);
294 return;
296 p += ret;
298 status = smb_bytes_talloc_string(cli,
299 inbuf,
300 &cli->server_domain,
302 bytes+num_bytes-p,
303 &ret);
305 if (!NT_STATUS_IS_OK(status)) {
306 tevent_req_nterror(req, status);
307 return;
309 p += ret;
311 status = cli_set_username(cli, state->user);
312 if (tevent_req_nterror(req, status)) {
313 return;
315 tevent_req_done(req);
318 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
320 return tevent_req_simple_recv_ntstatus(req);
323 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
324 const char *pass, size_t passlen,
325 const char *workgroup)
327 TALLOC_CTX *frame = talloc_stackframe();
328 struct event_context *ev;
329 struct tevent_req *req;
330 NTSTATUS status = NT_STATUS_NO_MEMORY;
332 if (cli_has_async_calls(cli)) {
334 * Can't use sync call while an async call is in flight
336 status = NT_STATUS_INVALID_PARAMETER;
337 goto fail;
339 ev = event_context_init(frame);
340 if (ev == NULL) {
341 goto fail;
343 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
344 workgroup);
345 if (req == NULL) {
346 goto fail;
348 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
349 goto fail;
351 status = cli_session_setup_lanman2_recv(req);
352 fail:
353 TALLOC_FREE(frame);
354 return status;
357 /****************************************************************************
358 Work out suitable capabilities to offer the server.
359 ****************************************************************************/
361 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
362 uint32_t sesssetup_capabilities)
364 uint32_t client_capabilities = cli_state_capabilities(cli);
367 * We only send capabilities based on the mask for:
368 * - client only flags
369 * - flags used in both directions
371 * We do not echo the server only flags.
373 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_CLIENT_MASK);
376 * Session Setup specific flags CAP_DYNAMIC_REAUTH
377 * and CAP_EXTENDED_SECURITY are passed by the caller.
378 * We need that in order to do guest logins even if
379 * CAP_EXTENDED_SECURITY is negotiated.
381 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
382 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
383 client_capabilities |= sesssetup_capabilities;
385 return client_capabilities;
388 /****************************************************************************
389 Do a NT1 guest session setup.
390 ****************************************************************************/
392 struct cli_session_setup_guest_state {
393 struct cli_state *cli;
394 uint16_t vwv[13];
395 struct iovec bytes;
398 static void cli_session_setup_guest_done(struct tevent_req *subreq);
400 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
401 struct event_context *ev,
402 struct cli_state *cli,
403 struct tevent_req **psmbreq)
405 struct tevent_req *req, *subreq;
406 struct cli_session_setup_guest_state *state;
407 uint16_t *vwv;
408 uint8_t *bytes;
410 req = tevent_req_create(mem_ctx, &state,
411 struct cli_session_setup_guest_state);
412 if (req == NULL) {
413 return NULL;
415 state->cli = cli;
416 vwv = state->vwv;
418 SCVAL(vwv+0, 0, 0xFF);
419 SCVAL(vwv+0, 1, 0);
420 SSVAL(vwv+1, 0, 0);
421 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
422 SSVAL(vwv+3, 0, 2);
423 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
424 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
425 SSVAL(vwv+7, 0, 0);
426 SSVAL(vwv+8, 0, 0);
427 SSVAL(vwv+9, 0, 0);
428 SSVAL(vwv+10, 0, 0);
429 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
431 bytes = talloc_array(state, uint8_t, 0);
433 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
434 NULL);
435 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
436 NULL);
437 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
438 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
440 if (bytes == NULL) {
441 TALLOC_FREE(req);
442 return NULL;
445 state->bytes.iov_base = (void *)bytes;
446 state->bytes.iov_len = talloc_get_size(bytes);
448 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
449 1, &state->bytes);
450 if (subreq == NULL) {
451 TALLOC_FREE(req);
452 return NULL;
454 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
455 *psmbreq = subreq;
456 return req;
459 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
460 struct event_context *ev,
461 struct cli_state *cli)
463 struct tevent_req *req, *subreq;
464 NTSTATUS status;
466 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
467 if (req == NULL) {
468 return NULL;
471 status = cli_smb_req_send(subreq);
472 if (NT_STATUS_IS_OK(status)) {
473 tevent_req_nterror(req, status);
474 return tevent_req_post(req, ev);
476 return req;
479 static void cli_session_setup_guest_done(struct tevent_req *subreq)
481 struct tevent_req *req = tevent_req_callback_data(
482 subreq, struct tevent_req);
483 struct cli_session_setup_guest_state *state = tevent_req_data(
484 req, struct cli_session_setup_guest_state);
485 struct cli_state *cli = state->cli;
486 uint32_t num_bytes;
487 uint8_t *in;
488 char *inbuf;
489 uint8_t *bytes;
490 uint8_t *p;
491 NTSTATUS status;
492 ssize_t ret;
493 uint8_t wct;
494 uint16_t *vwv;
496 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
497 &num_bytes, &bytes);
498 TALLOC_FREE(subreq);
499 if (!NT_STATUS_IS_OK(status)) {
500 tevent_req_nterror(req, status);
501 return;
504 inbuf = (char *)in;
505 p = bytes;
507 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
508 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
510 status = smb_bytes_talloc_string(cli,
511 inbuf,
512 &cli->server_os,
514 bytes+num_bytes-p,
515 &ret);
517 if (!NT_STATUS_IS_OK(status)) {
518 tevent_req_nterror(req, status);
519 return;
521 p += ret;
523 status = smb_bytes_talloc_string(cli,
524 inbuf,
525 &cli->server_type,
527 bytes+num_bytes-p,
528 &ret);
530 if (!NT_STATUS_IS_OK(status)) {
531 tevent_req_nterror(req, status);
532 return;
534 p += ret;
536 status = smb_bytes_talloc_string(cli,
537 inbuf,
538 &cli->server_domain,
540 bytes+num_bytes-p,
541 &ret);
543 if (!NT_STATUS_IS_OK(status)) {
544 tevent_req_nterror(req, status);
545 return;
547 p += ret;
549 status = cli_set_username(cli, "");
550 if (!NT_STATUS_IS_OK(status)) {
551 tevent_req_nterror(req, status);
552 return;
554 tevent_req_done(req);
557 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
559 return tevent_req_simple_recv_ntstatus(req);
562 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
564 TALLOC_CTX *frame = talloc_stackframe();
565 struct event_context *ev;
566 struct tevent_req *req;
567 NTSTATUS status = NT_STATUS_OK;
569 if (cli_has_async_calls(cli)) {
571 * Can't use sync call while an async call is in flight
573 status = NT_STATUS_INVALID_PARAMETER;
574 goto fail;
577 ev = event_context_init(frame);
578 if (ev == NULL) {
579 status = NT_STATUS_NO_MEMORY;
580 goto fail;
583 req = cli_session_setup_guest_send(frame, ev, cli);
584 if (req == NULL) {
585 status = NT_STATUS_NO_MEMORY;
586 goto fail;
589 if (!tevent_req_poll(req, ev)) {
590 status = map_nt_error_from_unix(errno);
591 goto fail;
594 status = cli_session_setup_guest_recv(req);
595 fail:
596 TALLOC_FREE(frame);
597 return status;
600 /****************************************************************************
601 Do a NT1 plaintext session setup.
602 ****************************************************************************/
604 struct cli_session_setup_plain_state {
605 struct cli_state *cli;
606 uint16_t vwv[13];
607 const char *user;
610 static void cli_session_setup_plain_done(struct tevent_req *subreq);
612 static struct tevent_req *cli_session_setup_plain_send(
613 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
614 struct cli_state *cli,
615 const char *user, const char *pass, const char *workgroup)
617 struct tevent_req *req, *subreq;
618 struct cli_session_setup_plain_state *state;
619 uint16_t *vwv;
620 uint8_t *bytes;
621 size_t passlen;
622 char *version;
624 req = tevent_req_create(mem_ctx, &state,
625 struct cli_session_setup_plain_state);
626 if (req == NULL) {
627 return NULL;
629 state->cli = cli;
630 state->user = user;
631 vwv = state->vwv;
633 SCVAL(vwv+0, 0, 0xff);
634 SCVAL(vwv+0, 1, 0);
635 SSVAL(vwv+1, 0, 0);
636 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
637 SSVAL(vwv+3, 0, 2);
638 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
639 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
640 SSVAL(vwv+7, 0, 0);
641 SSVAL(vwv+8, 0, 0);
642 SSVAL(vwv+9, 0, 0);
643 SSVAL(vwv+10, 0, 0);
644 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
646 bytes = talloc_array(state, uint8_t, 0);
647 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
648 &passlen);
649 if (tevent_req_nomem(bytes, req)) {
650 return tevent_req_post(req, ev);
652 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
654 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
655 user, strlen(user)+1, NULL);
656 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
657 workgroup, strlen(workgroup)+1, NULL);
658 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
659 "Unix", 5, NULL);
661 version = talloc_asprintf(talloc_tos(), "Samba %s",
662 samba_version_string());
663 if (tevent_req_nomem(version, req)){
664 return tevent_req_post(req, ev);
666 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
667 version, strlen(version)+1, NULL);
668 TALLOC_FREE(version);
670 if (tevent_req_nomem(bytes, req)) {
671 return tevent_req_post(req, ev);
674 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
675 talloc_get_size(bytes), bytes);
676 if (tevent_req_nomem(subreq, req)) {
677 return tevent_req_post(req, ev);
679 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
680 return req;
683 static void cli_session_setup_plain_done(struct tevent_req *subreq)
685 struct tevent_req *req = tevent_req_callback_data(
686 subreq, struct tevent_req);
687 struct cli_session_setup_plain_state *state = tevent_req_data(
688 req, struct cli_session_setup_plain_state);
689 struct cli_state *cli = state->cli;
690 uint32_t num_bytes;
691 uint8_t *in;
692 char *inbuf;
693 uint8_t *bytes;
694 uint8_t *p;
695 NTSTATUS status;
696 ssize_t ret;
697 uint8_t wct;
698 uint16_t *vwv;
700 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
701 &num_bytes, &bytes);
702 TALLOC_FREE(subreq);
703 if (tevent_req_nterror(req, status)) {
704 return;
707 inbuf = (char *)in;
708 p = bytes;
710 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
711 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
713 status = smb_bytes_talloc_string(cli,
714 inbuf,
715 &cli->server_os,
717 bytes+num_bytes-p,
718 &ret);
720 if (!NT_STATUS_IS_OK(status)) {
721 tevent_req_nterror(req, status);
722 return;
724 p += ret;
726 status = smb_bytes_talloc_string(cli,
727 inbuf,
728 &cli->server_type,
730 bytes+num_bytes-p,
731 &ret);
733 if (!NT_STATUS_IS_OK(status)) {
734 tevent_req_nterror(req, status);
735 return;
737 p += ret;
739 status = smb_bytes_talloc_string(cli,
740 inbuf,
741 &cli->server_domain,
743 bytes+num_bytes-p,
744 &ret);
746 if (!NT_STATUS_IS_OK(status)) {
747 tevent_req_nterror(req, status);
748 return;
750 p += ret;
752 status = cli_set_username(cli, state->user);
753 if (tevent_req_nterror(req, status)) {
754 return;
757 tevent_req_done(req);
760 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
762 return tevent_req_simple_recv_ntstatus(req);
765 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
766 const char *user, const char *pass,
767 const char *workgroup)
769 TALLOC_CTX *frame = talloc_stackframe();
770 struct event_context *ev;
771 struct tevent_req *req;
772 NTSTATUS status = NT_STATUS_NO_MEMORY;
774 if (cli_has_async_calls(cli)) {
776 * Can't use sync call while an async call is in flight
778 status = NT_STATUS_INVALID_PARAMETER;
779 goto fail;
781 ev = event_context_init(frame);
782 if (ev == NULL) {
783 goto fail;
785 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
786 workgroup);
787 if (req == NULL) {
788 goto fail;
790 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
791 goto fail;
793 status = cli_session_setup_plain_recv(req);
794 fail:
795 TALLOC_FREE(frame);
796 return status;
799 /****************************************************************************
800 do a NT1 NTLM/LM encrypted session setup - for when extended security
801 is not negotiated.
802 @param cli client state to create do session setup on
803 @param user username
804 @param pass *either* cleartext password (passlen !=24) or LM response.
805 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
806 @param workgroup The user's domain.
807 ****************************************************************************/
809 struct cli_session_setup_nt1_state {
810 struct cli_state *cli;
811 uint16_t vwv[13];
812 DATA_BLOB response;
813 DATA_BLOB session_key;
814 const char *user;
817 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
819 static struct tevent_req *cli_session_setup_nt1_send(
820 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
821 struct cli_state *cli, const char *user,
822 const char *pass, size_t passlen,
823 const char *ntpass, size_t ntpasslen,
824 const char *workgroup)
826 struct tevent_req *req, *subreq;
827 struct cli_session_setup_nt1_state *state;
828 DATA_BLOB lm_response = data_blob_null;
829 DATA_BLOB nt_response = data_blob_null;
830 DATA_BLOB session_key = data_blob_null;
831 uint16_t *vwv;
832 uint8_t *bytes;
833 char *workgroup_upper;
835 req = tevent_req_create(mem_ctx, &state,
836 struct cli_session_setup_nt1_state);
837 if (req == NULL) {
838 return NULL;
840 state->cli = cli;
841 state->user = user;
842 vwv = state->vwv;
844 if (passlen == 0) {
845 /* do nothing - guest login */
846 } else if (passlen != 24) {
847 if (lp_client_ntlmv2_auth()) {
848 DATA_BLOB server_chal;
849 DATA_BLOB names_blob;
851 server_chal =
852 data_blob_const(cli_state_server_challenge(cli),
856 * note that the 'workgroup' here is a best
857 * guess - we don't know the server's domain
858 * at this point. Windows clients also don't
859 * use hostname...
861 names_blob = NTLMv2_generate_names_blob(
862 NULL, NULL, workgroup);
864 if (tevent_req_nomem(names_blob.data, req)) {
865 return tevent_req_post(req, ev);
868 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
869 &server_chal, &names_blob,
870 &lm_response, &nt_response,
871 NULL, &session_key)) {
872 data_blob_free(&names_blob);
873 tevent_req_nterror(
874 req, NT_STATUS_ACCESS_DENIED);
875 return tevent_req_post(req, ev);
877 data_blob_free(&names_blob);
879 } else {
880 uchar nt_hash[16];
881 E_md4hash(pass, nt_hash);
883 #ifdef LANMAN_ONLY
884 nt_response = data_blob_null;
885 #else
886 nt_response = data_blob(NULL, 24);
887 if (tevent_req_nomem(nt_response.data, req)) {
888 return tevent_req_post(req, ev);
891 SMBNTencrypt(pass, cli_state_server_challenge(cli),
892 nt_response.data);
893 #endif
894 /* non encrypted password supplied. Ignore ntpass. */
895 if (lp_client_lanman_auth()) {
897 lm_response = data_blob(NULL, 24);
898 if (tevent_req_nomem(lm_response.data, req)) {
899 return tevent_req_post(req, ev);
902 if (!SMBencrypt(pass,
903 cli_state_server_challenge(cli),
904 lm_response.data)) {
906 * Oops, the LM response is
907 * invalid, just put the NT
908 * response there instead
910 data_blob_free(&lm_response);
911 lm_response = data_blob(
912 nt_response.data,
913 nt_response.length);
915 } else {
917 * LM disabled, place NT# in LM field
918 * instead
920 lm_response = data_blob(
921 nt_response.data, nt_response.length);
924 if (tevent_req_nomem(lm_response.data, req)) {
925 return tevent_req_post(req, ev);
928 session_key = data_blob(NULL, 16);
929 if (tevent_req_nomem(session_key.data, req)) {
930 return tevent_req_post(req, ev);
932 #ifdef LANMAN_ONLY
933 E_deshash(pass, session_key.data);
934 memset(&session_key.data[8], '\0', 8);
935 #else
936 SMBsesskeygen_ntv1(nt_hash, session_key.data);
937 #endif
939 } else {
940 /* pre-encrypted password supplied. Only used for
941 security=server, can't do
942 signing because we don't have original key */
944 lm_response = data_blob(pass, passlen);
945 if (tevent_req_nomem(lm_response.data, req)) {
946 return tevent_req_post(req, ev);
949 nt_response = data_blob(ntpass, ntpasslen);
950 if (tevent_req_nomem(nt_response.data, req)) {
951 return tevent_req_post(req, ev);
955 #ifdef LANMAN_ONLY
956 state->response = data_blob_talloc(
957 state, lm_response.data, lm_response.length);
958 #else
959 state->response = data_blob_talloc(
960 state, nt_response.data, nt_response.length);
961 #endif
962 if (tevent_req_nomem(state->response.data, req)) {
963 return tevent_req_post(req, ev);
966 if (session_key.data) {
967 state->session_key = data_blob_talloc(
968 state, session_key.data, session_key.length);
969 if (tevent_req_nomem(state->session_key.data, req)) {
970 return tevent_req_post(req, ev);
973 data_blob_free(&session_key);
975 SCVAL(vwv+0, 0, 0xff);
976 SCVAL(vwv+0, 1, 0);
977 SSVAL(vwv+1, 0, 0);
978 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
979 SSVAL(vwv+3, 0, 2);
980 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
981 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
982 SSVAL(vwv+7, 0, lm_response.length);
983 SSVAL(vwv+8, 0, nt_response.length);
984 SSVAL(vwv+9, 0, 0);
985 SSVAL(vwv+10, 0, 0);
986 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
988 bytes = talloc_array(state, uint8_t,
989 lm_response.length + nt_response.length);
990 if (tevent_req_nomem(bytes, req)) {
991 return tevent_req_post(req, ev);
993 if (lm_response.length != 0) {
994 memcpy(bytes, lm_response.data, lm_response.length);
996 if (nt_response.length != 0) {
997 memcpy(bytes + lm_response.length,
998 nt_response.data, nt_response.length);
1000 data_blob_free(&lm_response);
1001 data_blob_free(&nt_response);
1003 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1004 user, strlen(user)+1, NULL);
1007 * Upper case here might help some NTLMv2 implementations
1009 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1010 if (tevent_req_nomem(workgroup_upper, req)) {
1011 return tevent_req_post(req, ev);
1013 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1014 workgroup_upper, strlen(workgroup_upper)+1,
1015 NULL);
1016 TALLOC_FREE(workgroup_upper);
1018 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1019 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1020 if (tevent_req_nomem(bytes, req)) {
1021 return tevent_req_post(req, ev);
1024 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1025 talloc_get_size(bytes), bytes);
1026 if (tevent_req_nomem(subreq, req)) {
1027 return tevent_req_post(req, ev);
1029 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1030 return req;
1033 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1035 struct tevent_req *req = tevent_req_callback_data(
1036 subreq, struct tevent_req);
1037 struct cli_session_setup_nt1_state *state = tevent_req_data(
1038 req, struct cli_session_setup_nt1_state);
1039 struct cli_state *cli = state->cli;
1040 uint32_t num_bytes;
1041 uint8_t *in;
1042 char *inbuf;
1043 uint8_t *bytes;
1044 uint8_t *p;
1045 NTSTATUS status;
1046 ssize_t ret;
1047 uint8_t wct;
1048 uint16_t *vwv;
1050 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1051 &num_bytes, &bytes);
1052 TALLOC_FREE(subreq);
1053 if (!NT_STATUS_IS_OK(status)) {
1054 tevent_req_nterror(req, status);
1055 return;
1058 inbuf = (char *)in;
1059 p = bytes;
1061 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
1062 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1064 status = smb_bytes_talloc_string(cli,
1065 inbuf,
1066 &cli->server_os,
1068 bytes+num_bytes-p,
1069 &ret);
1070 if (!NT_STATUS_IS_OK(status)) {
1071 tevent_req_nterror(req, status);
1072 return;
1074 p += ret;
1076 status = smb_bytes_talloc_string(cli,
1077 inbuf,
1078 &cli->server_type,
1080 bytes+num_bytes-p,
1081 &ret);
1082 if (!NT_STATUS_IS_OK(status)) {
1083 tevent_req_nterror(req, status);
1084 return;
1086 p += ret;
1088 status = smb_bytes_talloc_string(cli,
1089 inbuf,
1090 &cli->server_domain,
1092 bytes+num_bytes-p,
1093 &ret);
1094 if (!NT_STATUS_IS_OK(status)) {
1095 tevent_req_nterror(req, status);
1096 return;
1098 p += ret;
1100 status = cli_set_username(cli, state->user);
1101 if (tevent_req_nterror(req, status)) {
1102 return;
1104 if (cli_simple_set_signing(cli, state->session_key, state->response)
1105 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1106 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1107 return;
1109 if (state->session_key.data) {
1110 /* Have plaintext orginal */
1111 cli_set_session_key(cli, state->session_key);
1113 tevent_req_done(req);
1116 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1118 return tevent_req_simple_recv_ntstatus(req);
1121 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1122 const char *pass, size_t passlen,
1123 const char *ntpass, size_t ntpasslen,
1124 const char *workgroup)
1126 TALLOC_CTX *frame = talloc_stackframe();
1127 struct event_context *ev;
1128 struct tevent_req *req;
1129 NTSTATUS status = NT_STATUS_NO_MEMORY;
1131 if (cli_has_async_calls(cli)) {
1133 * Can't use sync call while an async call is in flight
1135 status = NT_STATUS_INVALID_PARAMETER;
1136 goto fail;
1138 ev = event_context_init(frame);
1139 if (ev == NULL) {
1140 goto fail;
1142 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1143 ntpass, ntpasslen, workgroup);
1144 if (req == NULL) {
1145 goto fail;
1147 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1148 goto fail;
1150 status = cli_session_setup_nt1_recv(req);
1151 fail:
1152 TALLOC_FREE(frame);
1153 return status;
1156 /* The following is calculated from :
1157 * (smb_size-4) = 35
1158 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1159 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1160 * end of packet.
1163 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1165 struct cli_sesssetup_blob_state {
1166 struct tevent_context *ev;
1167 struct cli_state *cli;
1168 DATA_BLOB blob;
1169 uint16_t max_blob_size;
1170 uint16_t vwv[12];
1171 uint8_t *buf;
1173 NTSTATUS status;
1174 char *inbuf;
1175 DATA_BLOB ret_blob;
1178 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1179 struct tevent_req **psubreq);
1180 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1182 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1183 struct tevent_context *ev,
1184 struct cli_state *cli,
1185 DATA_BLOB blob)
1187 struct tevent_req *req, *subreq;
1188 struct cli_sesssetup_blob_state *state;
1189 uint32_t usable_space;
1191 req = tevent_req_create(mem_ctx, &state,
1192 struct cli_sesssetup_blob_state);
1193 if (req == NULL) {
1194 return NULL;
1196 state->ev = ev;
1197 state->blob = blob;
1198 state->cli = cli;
1200 usable_space = cli_state_available_size(cli,
1201 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1203 if (usable_space == 0) {
1204 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1205 "(not possible to send %u bytes)\n",
1206 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1207 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1208 return tevent_req_post(req, ev);
1210 state->max_blob_size = MIN(usable_space, 0xFFFF);
1212 if (!cli_sesssetup_blob_next(state, &subreq)) {
1213 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1214 return tevent_req_post(req, ev);
1216 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1217 return req;
1220 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1221 struct tevent_req **psubreq)
1223 struct tevent_req *subreq;
1224 uint16_t thistime;
1226 SCVAL(state->vwv+0, 0, 0xFF);
1227 SCVAL(state->vwv+0, 1, 0);
1228 SSVAL(state->vwv+1, 0, 0);
1229 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1230 SSVAL(state->vwv+3, 0, 2);
1231 SSVAL(state->vwv+4, 0, 1);
1232 SIVAL(state->vwv+5, 0, 0);
1234 thistime = MIN(state->blob.length, state->max_blob_size);
1235 SSVAL(state->vwv+7, 0, thistime);
1237 SSVAL(state->vwv+8, 0, 0);
1238 SSVAL(state->vwv+9, 0, 0);
1239 SIVAL(state->vwv+10, 0,
1240 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1242 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1243 thistime);
1244 if (state->buf == NULL) {
1245 return false;
1247 state->blob.data += thistime;
1248 state->blob.length -= thistime;
1250 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1251 "Unix", 5, NULL);
1252 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1253 "Samba", 6, NULL);
1254 if (state->buf == NULL) {
1255 return false;
1257 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1258 12, state->vwv,
1259 talloc_get_size(state->buf), state->buf);
1260 if (subreq == NULL) {
1261 return false;
1263 *psubreq = subreq;
1264 return true;
1267 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1269 struct tevent_req *req = tevent_req_callback_data(
1270 subreq, struct tevent_req);
1271 struct cli_sesssetup_blob_state *state = tevent_req_data(
1272 req, struct cli_sesssetup_blob_state);
1273 struct cli_state *cli = state->cli;
1274 uint8_t wct;
1275 uint16_t *vwv;
1276 uint32_t num_bytes;
1277 uint8_t *bytes;
1278 NTSTATUS status;
1279 uint8_t *p;
1280 uint16_t blob_length;
1281 uint8_t *inbuf;
1282 ssize_t ret;
1284 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
1285 &num_bytes, &bytes);
1286 TALLOC_FREE(subreq);
1287 if (!NT_STATUS_IS_OK(status)
1288 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1289 tevent_req_nterror(req, status);
1290 return;
1293 state->status = status;
1294 TALLOC_FREE(state->buf);
1296 state->inbuf = (char *)inbuf;
1297 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
1298 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1300 blob_length = SVAL(vwv+3, 0);
1301 if (blob_length > num_bytes) {
1302 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1303 return;
1305 state->ret_blob = data_blob_const(bytes, blob_length);
1307 p = bytes + blob_length;
1309 status = smb_bytes_talloc_string(cli,
1310 (char *)inbuf,
1311 &cli->server_os,
1313 bytes+num_bytes-p,
1314 &ret);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 tevent_req_nterror(req, status);
1318 return;
1320 p += ret;
1322 status = smb_bytes_talloc_string(cli,
1323 (char *)inbuf,
1324 &cli->server_type,
1326 bytes+num_bytes-p,
1327 &ret);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 tevent_req_nterror(req, status);
1331 return;
1333 p += ret;
1335 status = smb_bytes_talloc_string(cli,
1336 (char *)inbuf,
1337 &cli->server_domain,
1339 bytes+num_bytes-p,
1340 &ret);
1342 if (!NT_STATUS_IS_OK(status)) {
1343 tevent_req_nterror(req, status);
1344 return;
1346 p += ret;
1348 if (state->blob.length != 0) {
1350 * More to send
1352 if (!cli_sesssetup_blob_next(state, &subreq)) {
1353 tevent_req_oom(req);
1354 return;
1356 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1357 return;
1359 tevent_req_done(req);
1362 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1363 TALLOC_CTX *mem_ctx,
1364 DATA_BLOB *pblob,
1365 char **pinbuf)
1367 struct cli_sesssetup_blob_state *state = tevent_req_data(
1368 req, struct cli_sesssetup_blob_state);
1369 NTSTATUS status;
1370 char *inbuf;
1372 if (tevent_req_is_nterror(req, &status)) {
1373 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1374 return status;
1377 inbuf = talloc_move(mem_ctx, &state->inbuf);
1378 if (pblob != NULL) {
1379 *pblob = state->ret_blob;
1381 if (pinbuf != NULL) {
1382 *pinbuf = inbuf;
1384 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1385 return state->status;
1388 #ifdef HAVE_KRB5
1390 /****************************************************************************
1391 Use in-memory credentials cache
1392 ****************************************************************************/
1394 static void use_in_memory_ccache(void) {
1395 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1398 /****************************************************************************
1399 Do a spnego/kerberos encrypted session setup.
1400 ****************************************************************************/
1402 struct cli_session_setup_kerberos_state {
1403 struct cli_state *cli;
1404 DATA_BLOB negTokenTarg;
1405 DATA_BLOB session_key_krb5;
1406 ADS_STATUS ads_status;
1409 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1411 static struct tevent_req *cli_session_setup_kerberos_send(
1412 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1413 const char *principal)
1415 struct tevent_req *req, *subreq;
1416 struct cli_session_setup_kerberos_state *state;
1417 int rc;
1419 DEBUG(2,("Doing kerberos session setup\n"));
1421 req = tevent_req_create(mem_ctx, &state,
1422 struct cli_session_setup_kerberos_state);
1423 if (req == NULL) {
1424 return NULL;
1426 state->cli = cli;
1427 state->ads_status = ADS_SUCCESS;
1430 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1431 * we have to acquire a ticket. To be fixed later :-)
1433 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1434 &state->session_key_krb5, 0, NULL);
1435 if (rc) {
1436 DEBUG(1, ("cli_session_setup_kerberos: "
1437 "spnego_gen_krb5_negTokenInit failed: %s\n",
1438 error_message(rc)));
1439 state->ads_status = ADS_ERROR_KRB5(rc);
1440 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1441 return tevent_req_post(req, ev);
1444 #if 0
1445 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1446 state->negTokenTarg.length);
1447 #endif
1449 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1450 if (tevent_req_nomem(subreq, req)) {
1451 return tevent_req_post(req, ev);
1453 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1454 return req;
1457 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1459 struct tevent_req *req = tevent_req_callback_data(
1460 subreq, struct tevent_req);
1461 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1462 req, struct cli_session_setup_kerberos_state);
1463 char *inbuf = NULL;
1464 NTSTATUS status;
1466 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1467 TALLOC_FREE(subreq);
1468 if (!NT_STATUS_IS_OK(status)) {
1469 tevent_req_nterror(req, status);
1470 return;
1473 cli_set_session_key(state->cli, state->session_key_krb5);
1475 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1476 data_blob_null)
1477 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1478 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1479 return;
1482 tevent_req_done(req);
1485 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1487 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1488 req, struct cli_session_setup_kerberos_state);
1489 NTSTATUS status;
1491 if (tevent_req_is_nterror(req, &status)) {
1492 return ADS_ERROR_NT(status);
1494 return state->ads_status;
1497 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1498 const char *principal)
1500 struct tevent_context *ev;
1501 struct tevent_req *req;
1502 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1504 if (cli_has_async_calls(cli)) {
1505 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1507 ev = tevent_context_init(talloc_tos());
1508 if (ev == NULL) {
1509 goto fail;
1511 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1512 if (req == NULL) {
1513 goto fail;
1515 if (!tevent_req_poll(req, ev)) {
1516 status = ADS_ERROR_SYSTEM(errno);
1517 goto fail;
1519 status = cli_session_setup_kerberos_recv(req);
1520 fail:
1521 TALLOC_FREE(ev);
1522 return status;
1524 #endif /* HAVE_KRB5 */
1526 /****************************************************************************
1527 Do a spnego/NTLMSSP encrypted session setup.
1528 ****************************************************************************/
1530 struct cli_session_setup_ntlmssp_state {
1531 struct tevent_context *ev;
1532 struct cli_state *cli;
1533 struct ntlmssp_state *ntlmssp_state;
1534 int turn;
1535 DATA_BLOB blob_out;
1538 static int cli_session_setup_ntlmssp_state_destructor(
1539 struct cli_session_setup_ntlmssp_state *state)
1541 if (state->ntlmssp_state != NULL) {
1542 TALLOC_FREE(state->ntlmssp_state);
1544 return 0;
1547 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1549 static struct tevent_req *cli_session_setup_ntlmssp_send(
1550 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1551 const char *user, const char *pass, const char *domain)
1553 struct tevent_req *req, *subreq;
1554 struct cli_session_setup_ntlmssp_state *state;
1555 NTSTATUS status;
1556 DATA_BLOB blob_out;
1557 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1559 req = tevent_req_create(mem_ctx, &state,
1560 struct cli_session_setup_ntlmssp_state);
1561 if (req == NULL) {
1562 return NULL;
1564 state->ev = ev;
1565 state->cli = cli;
1566 state->turn = 1;
1568 state->ntlmssp_state = NULL;
1569 talloc_set_destructor(
1570 state, cli_session_setup_ntlmssp_state_destructor);
1572 status = ntlmssp_client_start(state,
1573 lp_netbios_name(),
1574 lp_workgroup(),
1575 lp_client_ntlmv2_auth(),
1576 &state->ntlmssp_state);
1577 if (!NT_STATUS_IS_OK(status)) {
1578 goto fail;
1580 ntlmssp_want_feature(state->ntlmssp_state,
1581 NTLMSSP_FEATURE_SESSION_KEY);
1582 if (cli->use_ccache) {
1583 ntlmssp_want_feature(state->ntlmssp_state,
1584 NTLMSSP_FEATURE_CCACHE);
1586 status = ntlmssp_set_username(state->ntlmssp_state, user);
1587 if (!NT_STATUS_IS_OK(status)) {
1588 goto fail;
1590 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 goto fail;
1594 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1595 if (!NT_STATUS_IS_OK(status)) {
1596 goto fail;
1598 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1599 &blob_out);
1600 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1601 goto fail;
1604 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1605 data_blob_free(&blob_out);
1607 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1608 if (tevent_req_nomem(subreq, req)) {
1609 return tevent_req_post(req, ev);
1611 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1612 return req;
1613 fail:
1614 tevent_req_nterror(req, status);
1615 return tevent_req_post(req, ev);
1618 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1620 struct tevent_req *req = tevent_req_callback_data(
1621 subreq, struct tevent_req);
1622 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1623 req, struct cli_session_setup_ntlmssp_state);
1624 DATA_BLOB blob_in, msg_in, blob_out;
1625 char *inbuf = NULL;
1626 bool parse_ret;
1627 NTSTATUS status;
1629 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1630 &inbuf);
1631 TALLOC_FREE(subreq);
1632 data_blob_free(&state->blob_out);
1634 if (NT_STATUS_IS_OK(status)) {
1635 if (state->cli->server_domain[0] == '\0') {
1636 TALLOC_FREE(state->cli->server_domain);
1637 state->cli->server_domain = talloc_strdup(state->cli,
1638 state->ntlmssp_state->server.netbios_domain);
1639 if (state->cli->server_domain == NULL) {
1640 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1641 return;
1644 cli_set_session_key(
1645 state->cli, state->ntlmssp_state->session_key);
1647 if (cli_simple_set_signing(
1648 state->cli, state->ntlmssp_state->session_key,
1649 data_blob_null)
1650 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1651 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1652 return;
1654 TALLOC_FREE(state->ntlmssp_state);
1655 tevent_req_done(req);
1656 return;
1658 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1659 tevent_req_nterror(req, status);
1660 return;
1663 if (blob_in.length == 0) {
1664 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1665 return;
1668 if ((state->turn == 1)
1669 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1670 DATA_BLOB tmp_blob = data_blob_null;
1671 /* the server might give us back two challenges */
1672 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1673 &tmp_blob);
1674 data_blob_free(&tmp_blob);
1675 } else {
1676 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1677 OID_NTLMSSP, &msg_in);
1679 state->turn += 1;
1681 if (!parse_ret) {
1682 DEBUG(3,("Failed to parse auth response\n"));
1683 if (NT_STATUS_IS_OK(status)
1684 || NT_STATUS_EQUAL(status,
1685 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1686 tevent_req_nterror(
1687 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1688 return;
1692 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1694 if (!NT_STATUS_IS_OK(status)
1695 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1696 TALLOC_FREE(state->ntlmssp_state);
1697 tevent_req_nterror(req, status);
1698 return;
1701 state->blob_out = spnego_gen_auth(state, blob_out);
1702 if (tevent_req_nomem(state->blob_out.data, req)) {
1703 return;
1706 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1707 state->blob_out);
1708 if (tevent_req_nomem(subreq, req)) {
1709 return;
1711 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1714 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1716 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1717 req, struct cli_session_setup_ntlmssp_state);
1718 NTSTATUS status;
1720 if (tevent_req_is_nterror(req, &status)) {
1721 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1722 return status;
1724 return NT_STATUS_OK;
1727 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1728 const char *user,
1729 const char *pass,
1730 const char *domain)
1732 struct tevent_context *ev;
1733 struct tevent_req *req;
1734 NTSTATUS status = NT_STATUS_NO_MEMORY;
1736 if (cli_has_async_calls(cli)) {
1737 return NT_STATUS_INVALID_PARAMETER;
1739 ev = tevent_context_init(talloc_tos());
1740 if (ev == NULL) {
1741 goto fail;
1743 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1744 if (req == NULL) {
1745 goto fail;
1747 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1748 goto fail;
1750 status = cli_session_setup_ntlmssp_recv(req);
1751 fail:
1752 TALLOC_FREE(ev);
1753 return status;
1756 /****************************************************************************
1757 Do a spnego encrypted session setup.
1759 user_domain: The shortname of the domain the user/machine is a member of.
1760 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1761 ****************************************************************************/
1763 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1764 const char *user,
1765 const char *pass,
1766 const char *user_domain,
1767 const char * dest_realm)
1769 char *principal = NULL;
1770 char *OIDs[ASN1_MAX_OIDS];
1771 int i;
1772 DATA_BLOB *server_blob;
1773 DATA_BLOB blob = data_blob_null;
1774 const char *p = NULL;
1775 char *account = NULL;
1776 NTSTATUS status;
1778 server_blob = cli_state_server_gss_blob(cli);
1779 if (server_blob) {
1780 blob = data_blob(server_blob->data, server_blob->length);
1783 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)blob.length));
1785 /* the server might not even do spnego */
1786 if (blob.length == 0) {
1787 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1788 goto ntlmssp;
1791 #if 0
1792 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1793 #endif
1795 /* The server sent us the first part of the SPNEGO exchange in the
1796 * negprot reply. It is WRONG to depend on the principal sent in the
1797 * negprot reply, but right now we do it. If we don't receive one,
1798 * we try to best guess, then fall back to NTLM. */
1799 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1800 OIDs[0] == NULL) {
1801 data_blob_free(&blob);
1802 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1804 data_blob_free(&blob);
1806 /* make sure the server understands kerberos */
1807 for (i=0;OIDs[i];i++) {
1808 if (i == 0)
1809 DEBUG(3,("got OID=%s\n", OIDs[i]));
1810 else
1811 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1812 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1813 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1814 cli->got_kerberos_mechanism = True;
1816 talloc_free(OIDs[i]);
1819 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1821 status = cli_set_username(cli, user);
1822 if (!NT_STATUS_IS_OK(status)) {
1823 TALLOC_FREE(principal);
1824 return ADS_ERROR_NT(status);
1827 #ifdef HAVE_KRB5
1828 /* If password is set we reauthenticate to kerberos server
1829 * and do not store results */
1831 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1832 ADS_STATUS rc;
1833 const char *remote_name = cli_state_remote_name(cli);
1835 if (pass && *pass) {
1836 int ret;
1838 use_in_memory_ccache();
1839 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1841 if (ret){
1842 TALLOC_FREE(principal);
1843 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1844 if (cli->fallback_after_kerberos)
1845 goto ntlmssp;
1846 return ADS_ERROR_KRB5(ret);
1850 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1852 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1853 TALLOC_FREE(principal);
1856 if (principal == NULL &&
1857 !is_ipaddress(remote_name) &&
1858 !strequal(STAR_SMBSERVER,
1859 remote_name)) {
1860 char *realm = NULL;
1861 char *host = NULL;
1862 DEBUG(3,("cli_session_setup_spnego: using target "
1863 "hostname not SPNEGO principal\n"));
1865 host = strchr_m(remote_name, '.');
1866 if (dest_realm) {
1867 realm = SMB_STRDUP(dest_realm);
1868 if (!realm) {
1869 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1871 strupper_m(realm);
1872 } else {
1873 if (host) {
1874 /* DNS name. */
1875 realm = kerberos_get_realm_from_hostname(remote_name);
1876 } else {
1877 /* NetBIOS name - use our realm. */
1878 realm = kerberos_get_default_realm_from_ccache();
1882 if (realm == NULL || *realm == '\0') {
1883 realm = SMB_STRDUP(lp_realm());
1884 if (!realm) {
1885 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1887 strupper_m(realm);
1888 DEBUG(3,("cli_session_setup_spnego: cannot "
1889 "get realm from dest_realm %s, "
1890 "desthost %s. Using default "
1891 "smb.conf realm %s\n",
1892 dest_realm ? dest_realm : "<null>",
1893 remote_name,
1894 realm));
1897 principal = talloc_asprintf(talloc_tos(),
1898 "cifs/%s@%s",
1899 remote_name,
1900 realm);
1901 if (!principal) {
1902 SAFE_FREE(realm);
1903 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1905 DEBUG(3,("cli_session_setup_spnego: guessed "
1906 "server principal=%s\n",
1907 principal ? principal : "<null>"));
1909 SAFE_FREE(realm);
1912 if (principal) {
1913 rc = cli_session_setup_kerberos(cli, principal);
1914 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1915 TALLOC_FREE(principal);
1916 return rc;
1920 #endif
1922 TALLOC_FREE(principal);
1924 ntlmssp:
1926 account = talloc_strdup(talloc_tos(), user);
1927 if (!account) {
1928 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1931 /* when falling back to ntlmssp while authenticating with a machine
1932 * account strip off the realm - gd */
1934 if ((p = strchr_m(user, '@')) != NULL) {
1935 account[PTR_DIFF(p,user)] = '\0';
1938 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1941 /****************************************************************************
1942 Send a session setup. The username and workgroup is in UNIX character
1943 format and must be converted to DOS codepage format before sending. If the
1944 password is in plaintext, the same should be done.
1945 ****************************************************************************/
1947 NTSTATUS cli_session_setup(struct cli_state *cli,
1948 const char *user,
1949 const char *pass, int passlen,
1950 const char *ntpass, int ntpasslen,
1951 const char *workgroup)
1953 char *p;
1954 char *user2;
1955 uint16_t sec_mode = cli_state_security_mode(cli);
1957 if (user) {
1958 user2 = talloc_strdup(talloc_tos(), user);
1959 } else {
1960 user2 = talloc_strdup(talloc_tos(), "");
1962 if (user2 == NULL) {
1963 return NT_STATUS_NO_MEMORY;
1966 if (!workgroup) {
1967 workgroup = "";
1970 /* allow for workgroups as part of the username */
1971 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1972 (p=strchr_m(user2,*lp_winbind_separator()))) {
1973 *p = 0;
1974 user = p+1;
1975 strupper_m(user2);
1976 workgroup = user2;
1979 if (cli_state_protocol(cli) < PROTOCOL_LANMAN1) {
1981 * Ensure cli->server_domain,
1982 * cli->server_os and cli->server_type
1983 * are valid pointers.
1985 cli->server_domain = talloc_strdup(cli, "");
1986 cli->server_os = talloc_strdup(cli, "");
1987 cli->server_type = talloc_strdup(cli, "");
1988 if (cli->server_domain == NULL ||
1989 cli->server_os == NULL ||
1990 cli->server_type == NULL) {
1991 return NT_STATUS_NO_MEMORY;
1993 return NT_STATUS_OK;
1996 /* now work out what sort of session setup we are going to
1997 do. I have split this into separate functions to make the
1998 flow a bit easier to understand (tridge) */
2000 /* if its an older server then we have to use the older request format */
2002 if (cli_state_protocol(cli) < PROTOCOL_NT1) {
2003 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2004 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2005 " or 'client ntlmv2 auth = yes'\n"));
2006 return NT_STATUS_ACCESS_DENIED;
2009 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2010 !lp_client_plaintext_auth() && (*pass)) {
2011 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2012 " or 'client ntlmv2 auth = yes'\n"));
2013 return NT_STATUS_ACCESS_DENIED;
2016 return cli_session_setup_lanman2(cli, user, pass, passlen,
2017 workgroup);
2020 /* if no user is supplied then we have to do an anonymous connection.
2021 passwords are ignored */
2023 if (!user || !*user)
2024 return cli_session_setup_guest(cli);
2026 /* if the server is share level then send a plaintext null
2027 password at this point. The password is sent in the tree
2028 connect */
2030 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2031 return cli_session_setup_plain(cli, user, "", workgroup);
2033 /* if the server doesn't support encryption then we have to use
2034 plaintext. The second password is ignored */
2036 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2037 if (!lp_client_plaintext_auth() && (*pass)) {
2038 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2039 " or 'client ntlmv2 auth = yes'\n"));
2040 return NT_STATUS_ACCESS_DENIED;
2042 return cli_session_setup_plain(cli, user, pass, workgroup);
2045 /* if the server supports extended security then use SPNEGO */
2047 if (cli_state_capabilities(cli) & CAP_EXTENDED_SECURITY) {
2048 const char *remote_realm = cli_state_remote_realm(cli);
2049 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2050 workgroup,
2051 remote_realm);
2052 if (!ADS_ERR_OK(status)) {
2053 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2054 return ads_ntstatus(status);
2056 } else {
2057 NTSTATUS status;
2059 /* otherwise do a NT1 style session setup */
2060 status = cli_session_setup_nt1(cli, user, pass, passlen,
2061 ntpass, ntpasslen, workgroup);
2062 if (!NT_STATUS_IS_OK(status)) {
2063 DEBUG(3,("cli_session_setup: NT1 session setup "
2064 "failed: %s\n", nt_errstr(status)));
2065 return status;
2069 return NT_STATUS_OK;
2072 /****************************************************************************
2073 Send a uloggoff.
2074 *****************************************************************************/
2076 struct cli_ulogoff_state {
2077 struct cli_state *cli;
2078 uint16_t vwv[3];
2081 static void cli_ulogoff_done(struct tevent_req *subreq);
2083 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2084 struct tevent_context *ev,
2085 struct cli_state *cli)
2087 struct tevent_req *req, *subreq;
2088 struct cli_ulogoff_state *state;
2090 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2091 if (req == NULL) {
2092 return NULL;
2094 state->cli = cli;
2096 SCVAL(state->vwv+0, 0, 0xFF);
2097 SCVAL(state->vwv+1, 0, 0);
2098 SSVAL(state->vwv+2, 0, 0);
2100 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2101 0, NULL);
2102 if (tevent_req_nomem(subreq, req)) {
2103 return tevent_req_post(req, ev);
2105 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2106 return req;
2109 static void cli_ulogoff_done(struct tevent_req *subreq)
2111 struct tevent_req *req = tevent_req_callback_data(
2112 subreq, struct tevent_req);
2113 struct cli_ulogoff_state *state = tevent_req_data(
2114 req, struct cli_ulogoff_state);
2115 NTSTATUS status;
2117 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2118 if (!NT_STATUS_IS_OK(status)) {
2119 tevent_req_nterror(req, status);
2120 return;
2122 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2123 tevent_req_done(req);
2126 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2128 return tevent_req_simple_recv_ntstatus(req);
2131 NTSTATUS cli_ulogoff(struct cli_state *cli)
2133 struct tevent_context *ev;
2134 struct tevent_req *req;
2135 NTSTATUS status = NT_STATUS_NO_MEMORY;
2137 if (cli_has_async_calls(cli)) {
2138 return NT_STATUS_INVALID_PARAMETER;
2140 ev = tevent_context_init(talloc_tos());
2141 if (ev == NULL) {
2142 goto fail;
2144 req = cli_ulogoff_send(ev, ev, cli);
2145 if (req == NULL) {
2146 goto fail;
2148 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2149 goto fail;
2151 status = cli_ulogoff_recv(req);
2152 fail:
2153 TALLOC_FREE(ev);
2154 return status;
2157 /****************************************************************************
2158 Send a tconX.
2159 ****************************************************************************/
2161 struct cli_tcon_andx_state {
2162 struct cli_state *cli;
2163 uint16_t vwv[4];
2164 struct iovec bytes;
2167 static void cli_tcon_andx_done(struct tevent_req *subreq);
2169 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2170 struct event_context *ev,
2171 struct cli_state *cli,
2172 const char *share, const char *dev,
2173 const char *pass, int passlen,
2174 struct tevent_req **psmbreq)
2176 struct tevent_req *req, *subreq;
2177 struct cli_tcon_andx_state *state;
2178 uint8_t p24[24];
2179 uint16_t *vwv;
2180 char *tmp = NULL;
2181 uint8_t *bytes;
2182 uint16_t sec_mode = cli_state_security_mode(cli);
2184 *psmbreq = NULL;
2186 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2187 if (req == NULL) {
2188 return NULL;
2190 state->cli = cli;
2191 vwv = state->vwv;
2193 cli->share = talloc_strdup(cli, share);
2194 if (!cli->share) {
2195 return NULL;
2198 /* in user level security don't send a password now */
2199 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2200 passlen = 1;
2201 pass = "";
2202 } else if (pass == NULL) {
2203 DEBUG(1, ("Server not using user level security and no "
2204 "password supplied.\n"));
2205 goto access_denied;
2208 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2209 *pass && passlen != 24) {
2210 if (!lp_client_lanman_auth()) {
2211 DEBUG(1, ("Server requested LANMAN password "
2212 "(share-level security) but "
2213 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2214 goto access_denied;
2218 * Non-encrypted passwords - convert to DOS codepage before
2219 * encryption.
2221 SMBencrypt(pass, cli_state_server_challenge(cli), p24);
2222 passlen = 24;
2223 pass = (const char *)p24;
2224 } else {
2225 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2226 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2227 == 0) {
2228 uint8_t *tmp_pass;
2230 if (!lp_client_plaintext_auth() && (*pass)) {
2231 DEBUG(1, ("Server requested plaintext "
2232 "password but "
2233 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2234 goto access_denied;
2238 * Non-encrypted passwords - convert to DOS codepage
2239 * before using.
2241 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2242 if (tevent_req_nomem(tmp_pass, req)) {
2243 return tevent_req_post(req, ev);
2245 tmp_pass = trans2_bytes_push_str(tmp_pass,
2246 false, /* always DOS */
2247 pass,
2248 passlen,
2249 NULL);
2250 if (tevent_req_nomem(tmp_pass, req)) {
2251 return tevent_req_post(req, ev);
2253 pass = (const char *)tmp_pass;
2254 passlen = talloc_get_size(tmp_pass);
2258 SCVAL(vwv+0, 0, 0xFF);
2259 SCVAL(vwv+0, 1, 0);
2260 SSVAL(vwv+1, 0, 0);
2261 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2262 SSVAL(vwv+3, 0, passlen);
2264 if (passlen && pass) {
2265 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2266 } else {
2267 bytes = talloc_array(state, uint8_t, 0);
2271 * Add the sharename
2273 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2274 cli_state_remote_name(cli), share);
2275 if (tmp == NULL) {
2276 TALLOC_FREE(req);
2277 return NULL;
2279 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2280 NULL);
2281 TALLOC_FREE(tmp);
2284 * Add the devicetype
2286 tmp = talloc_strdup_upper(talloc_tos(), dev);
2287 if (tmp == NULL) {
2288 TALLOC_FREE(req);
2289 return NULL;
2291 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2292 TALLOC_FREE(tmp);
2294 if (bytes == NULL) {
2295 TALLOC_FREE(req);
2296 return NULL;
2299 state->bytes.iov_base = (void *)bytes;
2300 state->bytes.iov_len = talloc_get_size(bytes);
2302 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2303 1, &state->bytes);
2304 if (subreq == NULL) {
2305 TALLOC_FREE(req);
2306 return NULL;
2308 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2309 *psmbreq = subreq;
2310 return req;
2312 access_denied:
2313 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2314 return tevent_req_post(req, ev);
2317 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2318 struct event_context *ev,
2319 struct cli_state *cli,
2320 const char *share, const char *dev,
2321 const char *pass, int passlen)
2323 struct tevent_req *req, *subreq;
2324 NTSTATUS status;
2326 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2327 &subreq);
2328 if (req == NULL) {
2329 return NULL;
2331 if (subreq == NULL) {
2332 return req;
2334 status = cli_smb_req_send(subreq);
2335 if (!NT_STATUS_IS_OK(status)) {
2336 tevent_req_nterror(req, status);
2337 return tevent_req_post(req, ev);
2339 return req;
2342 static void cli_tcon_andx_done(struct tevent_req *subreq)
2344 struct tevent_req *req = tevent_req_callback_data(
2345 subreq, struct tevent_req);
2346 struct cli_tcon_andx_state *state = tevent_req_data(
2347 req, struct cli_tcon_andx_state);
2348 struct cli_state *cli = state->cli;
2349 uint8_t *in;
2350 char *inbuf;
2351 uint8_t wct;
2352 uint16_t *vwv;
2353 uint32_t num_bytes;
2354 uint8_t *bytes;
2355 NTSTATUS status;
2357 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2358 &num_bytes, &bytes);
2359 TALLOC_FREE(subreq);
2360 if (!NT_STATUS_IS_OK(status)) {
2361 tevent_req_nterror(req, status);
2362 return;
2365 inbuf = (char *)in;
2367 if (num_bytes) {
2368 if (clistr_pull_talloc(cli,
2369 inbuf,
2370 SVAL(inbuf, smb_flg2),
2371 &cli->dev,
2372 bytes,
2373 num_bytes,
2374 STR_TERMINATE|STR_ASCII) == -1) {
2375 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2376 return;
2378 } else {
2379 cli->dev = talloc_strdup(cli, "");
2380 if (cli->dev == NULL) {
2381 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2382 return;
2386 if ((cli_state_protocol(cli) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2387 /* almost certainly win95 - enable bug fixes */
2388 cli->win95 = True;
2392 * Make sure that we have the optional support 16-bit field. WCT > 2.
2393 * Avoids issues when connecting to Win9x boxes sharing files
2396 cli->dfsroot = false;
2398 if ((wct > 2) && (cli_state_protocol(cli) >= PROTOCOL_LANMAN2)) {
2399 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2402 cli->smb1.tid = SVAL(inbuf,smb_tid);
2403 tevent_req_done(req);
2406 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2408 return tevent_req_simple_recv_ntstatus(req);
2411 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2412 const char *dev, const char *pass, int passlen)
2414 TALLOC_CTX *frame = talloc_stackframe();
2415 struct event_context *ev;
2416 struct tevent_req *req;
2417 NTSTATUS status = NT_STATUS_OK;
2419 if (cli_has_async_calls(cli)) {
2421 * Can't use sync call while an async call is in flight
2423 status = NT_STATUS_INVALID_PARAMETER;
2424 goto fail;
2427 ev = event_context_init(frame);
2428 if (ev == NULL) {
2429 status = NT_STATUS_NO_MEMORY;
2430 goto fail;
2433 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2434 if (req == NULL) {
2435 status = NT_STATUS_NO_MEMORY;
2436 goto fail;
2439 if (!tevent_req_poll(req, ev)) {
2440 status = map_nt_error_from_unix(errno);
2441 goto fail;
2444 status = cli_tcon_andx_recv(req);
2445 fail:
2446 TALLOC_FREE(frame);
2447 return status;
2450 /****************************************************************************
2451 Send a tree disconnect.
2452 ****************************************************************************/
2454 struct cli_tdis_state {
2455 struct cli_state *cli;
2458 static void cli_tdis_done(struct tevent_req *subreq);
2460 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2461 struct tevent_context *ev,
2462 struct cli_state *cli)
2464 struct tevent_req *req, *subreq;
2465 struct cli_tdis_state *state;
2467 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2468 if (req == NULL) {
2469 return NULL;
2471 state->cli = cli;
2473 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2474 if (tevent_req_nomem(subreq, req)) {
2475 return tevent_req_post(req, ev);
2477 tevent_req_set_callback(subreq, cli_tdis_done, req);
2478 return req;
2481 static void cli_tdis_done(struct tevent_req *subreq)
2483 struct tevent_req *req = tevent_req_callback_data(
2484 subreq, struct tevent_req);
2485 struct cli_tdis_state *state = tevent_req_data(
2486 req, struct cli_tdis_state);
2487 NTSTATUS status;
2489 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2490 TALLOC_FREE(subreq);
2491 if (!NT_STATUS_IS_OK(status)) {
2492 tevent_req_nterror(req, status);
2493 return;
2495 state->cli->smb1.tid = UINT16_MAX;
2496 tevent_req_done(req);
2499 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2501 return tevent_req_simple_recv_ntstatus(req);
2504 NTSTATUS cli_tdis(struct cli_state *cli)
2506 struct tevent_context *ev;
2507 struct tevent_req *req;
2508 NTSTATUS status = NT_STATUS_NO_MEMORY;
2510 if (cli_has_async_calls(cli)) {
2511 return NT_STATUS_INVALID_PARAMETER;
2513 ev = tevent_context_init(talloc_tos());
2514 if (ev == NULL) {
2515 goto fail;
2517 req = cli_tdis_send(ev, ev, cli);
2518 if (req == NULL) {
2519 goto fail;
2521 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2522 goto fail;
2524 status = cli_tdis_recv(req);
2525 fail:
2526 TALLOC_FREE(ev);
2527 return status;
2530 /****************************************************************************
2531 Send a negprot command.
2532 ****************************************************************************/
2534 struct cli_negprot_state {
2535 struct cli_state *cli;
2536 enum protocol_types max_protocol;
2539 static void cli_negprot_done(struct tevent_req *subreq);
2541 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2542 struct event_context *ev,
2543 struct cli_state *cli,
2544 enum protocol_types max_protocol)
2546 struct tevent_req *req, *subreq;
2547 struct cli_negprot_state *state;
2548 uint8_t *bytes = NULL;
2549 int numprots;
2550 enum protocol_types tmp_protocol;
2552 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2553 if (req == NULL) {
2554 return NULL;
2556 state->cli = cli;
2557 state->max_protocol = max_protocol;
2559 /* setup the protocol strings */
2560 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2561 uint8_t c = 2;
2562 if (prots[numprots].prot > state->max_protocol) {
2563 break;
2565 bytes = (uint8_t *)talloc_append_blob(
2566 state, bytes, data_blob_const(&c, sizeof(c)));
2567 if (tevent_req_nomem(bytes, req)) {
2568 return tevent_req_post(req, ev);
2570 bytes = smb_bytes_push_str(bytes, false,
2571 prots[numprots].name,
2572 strlen(prots[numprots].name)+1,
2573 NULL);
2574 if (tevent_req_nomem(bytes, req)) {
2575 return tevent_req_post(req, ev);
2579 tmp_protocol = cli->conn.protocol;
2580 cli->conn.protocol = state->max_protocol;
2581 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2582 talloc_get_size(bytes), bytes);
2583 cli->conn.protocol = tmp_protocol;
2584 if (tevent_req_nomem(subreq, req)) {
2585 return tevent_req_post(req, ev);
2587 tevent_req_set_callback(subreq, cli_negprot_done, req);
2588 return req;
2591 static void cli_negprot_done(struct tevent_req *subreq)
2593 struct tevent_req *req = tevent_req_callback_data(
2594 subreq, struct tevent_req);
2595 struct cli_negprot_state *state = tevent_req_data(
2596 req, struct cli_negprot_state);
2597 struct cli_state *cli = state->cli;
2598 uint8_t flags;
2599 uint8_t wct;
2600 uint16_t *vwv;
2601 uint32_t num_bytes;
2602 uint8_t *bytes;
2603 NTSTATUS status;
2604 uint16_t protnum;
2605 uint8_t *inbuf;
2606 uint32_t client_capabilities = cli->conn.smb1.client.capabilities;
2607 uint32_t both_capabilities;
2608 uint32_t server_capabilities = 0;
2609 uint32_t capabilities;
2610 uint32_t client_max_xmit = cli->conn.smb1.client.max_xmit;
2611 uint32_t server_max_xmit = 0;
2612 uint32_t max_xmit;
2613 uint32_t server_max_mux = 0;
2614 uint16_t server_security_mode = 0;
2615 uint32_t server_session_key = 0;
2616 bool server_readbraw = false;
2617 bool server_writebraw = false;
2618 bool server_lockread = false;
2619 bool server_writeunlock = false;
2620 struct GUID server_guid = GUID_zero();
2621 DATA_BLOB server_gss_blob = data_blob_null;
2622 uint8_t server_challenge[8];
2623 char *server_workgroup = NULL;
2624 int server_time_zone = 0;
2625 time_t server_system_time = 0;
2626 enum protocol_types protocol;
2628 ZERO_STRUCT(server_challenge);
2630 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2631 &num_bytes, &bytes);
2632 TALLOC_FREE(subreq);
2633 if (!NT_STATUS_IS_OK(status)) {
2634 tevent_req_nterror(req, status);
2635 return;
2638 flags = CVAL(inbuf, smb_flg);
2640 protnum = SVAL(vwv, 0);
2642 if ((protnum >= ARRAY_SIZE(prots))
2643 || (prots[protnum].prot > state->max_protocol)) {
2644 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2645 return;
2648 protocol = prots[protnum].prot;
2650 if ((protocol < PROTOCOL_NT1) &&
2651 client_is_signing_mandatory(cli)) {
2652 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2653 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2654 return;
2657 if (flags & FLAG_SUPPORT_LOCKREAD) {
2658 server_lockread = true;
2659 server_writeunlock = true;
2662 if (protocol >= PROTOCOL_NT1) {
2663 struct timespec ts;
2664 const char *client_signing = NULL;
2665 bool server_mandatory;
2666 bool server_allowed;
2667 const char *server_signing = NULL;
2668 bool ok;
2669 uint16_t key_len;
2671 if (wct != 0x11) {
2672 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2673 return;
2676 /* NT protocol */
2677 server_security_mode = CVAL(vwv + 1, 0);
2678 server_max_mux = SVAL(vwv + 1, 1);
2679 server_max_xmit = IVAL(vwv + 3, 1);
2680 server_session_key = IVAL(vwv + 7, 1);
2681 server_time_zone = SVALS(vwv + 15, 1);
2682 server_time_zone *= 60;
2683 /* this time arrives in real GMT */
2684 ts = interpret_long_date(((char *)(vwv+11))+1);
2685 server_system_time = ts.tv_sec;
2686 server_capabilities = IVAL(vwv + 9, 1);
2688 key_len = CVAL(vwv + 16, 1);
2690 if (server_capabilities & CAP_RAW_MODE) {
2691 server_readbraw = true;
2692 server_writebraw = true;
2694 if (server_capabilities & CAP_LOCK_AND_READ) {
2695 server_lockread = true;
2698 if (server_capabilities & CAP_EXTENDED_SECURITY) {
2699 DATA_BLOB blob1, blob2;
2701 if (num_bytes < 16) {
2702 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2703 return;
2706 blob1 = data_blob_const(bytes, 16);
2707 GUID_from_data_blob(&blob1, &server_guid);
2709 blob1 = data_blob_const(bytes+16, num_bytes-16);
2710 blob2 = data_blob_dup_talloc(state, blob1);
2711 if (blob1.length > 0 &&
2712 tevent_req_nomem(blob2.data, req)) {
2713 return;
2715 server_gss_blob = blob2;
2716 } else {
2717 DATA_BLOB blob1;
2718 ssize_t ret;
2720 if (num_bytes < key_len) {
2721 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2722 return;
2725 if (key_len != 0 && key_len != 8) {
2726 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2727 return;
2730 if (key_len == 8) {
2731 memcpy(server_challenge, bytes, 8);
2734 blob1 = data_blob_const(bytes+key_len, num_bytes-key_len);
2735 if (blob1.length > 0) {
2736 ret = pull_string_talloc(state,
2737 (char *)inbuf,
2738 SVAL(inbuf, smb_flg2),
2739 &server_workgroup,
2740 blob1.data, blob1.length,
2741 STR_TERMINATE);
2742 if (ret == -1) {
2743 tevent_req_oom(req);
2744 return;
2749 client_signing = "disabled";
2750 if (client_is_signing_allowed(cli)) {
2751 client_signing = "allowed";
2753 if (client_is_signing_mandatory(cli)) {
2754 client_signing = "required";
2757 server_signing = "not supported";
2759 server_allowed = false;
2760 if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2761 server_signing = "supported";
2762 server_allowed = true;
2765 server_mandatory = false;
2766 if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2767 server_signing = "required";
2768 server_mandatory = true;
2771 ok = cli_set_signing_negotiated(cli,
2772 server_allowed,
2773 server_mandatory);
2774 if (!ok) {
2775 DEBUG(1,("cli_negprot: SMB signing is required, "
2776 "but client[%s] and server[%s] mismatch\n",
2777 client_signing, server_signing));
2778 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2779 return;
2782 } else if (protocol >= PROTOCOL_LANMAN1) {
2783 if (wct != 0x0D) {
2784 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2785 return;
2788 server_security_mode = SVAL(vwv + 1, 0);
2789 server_max_xmit = SVAL(vwv + 2, 0);
2790 server_max_mux = SVAL(vwv + 3, 0);
2791 server_session_key = IVAL(vwv + 6, 0);
2792 server_time_zone = SVALS(vwv + 10, 0);
2793 server_time_zone *= 60;
2794 /* this time is converted to GMT by make_unix_date */
2795 server_system_time = make_unix_date(
2796 (char *)(vwv + 8), server_time_zone);
2797 server_readbraw = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2798 server_writebraw = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2800 if (num_bytes != 0 && num_bytes != 8) {
2801 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2802 return;
2805 if (num_bytes == 8) {
2806 memcpy(server_challenge, bytes, 8);
2808 } else {
2809 /* the old core protocol */
2810 server_time_zone = get_time_zone(time(NULL));
2811 server_system_time = 0;
2812 server_max_xmit = 1024;
2813 server_max_mux = 1;
2814 server_security_mode = 0;
2817 if (server_max_xmit < 1024) {
2818 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2819 return;
2822 if (server_max_mux < 1) {
2823 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2824 return;
2828 * Now calculate the negotiated capabilities
2829 * based on the mask for:
2830 * - client only flags
2831 * - flags used in both directions
2832 * - server only flags
2834 both_capabilities = client_capabilities & server_capabilities;
2835 capabilities = client_capabilities & SMB_CAP_CLIENT_MASK;
2836 capabilities |= both_capabilities & SMB_CAP_BOTH_MASK;
2837 capabilities |= server_capabilities & SMB_CAP_SERVER_MASK;
2839 max_xmit = MIN(client_max_xmit, server_max_xmit);
2841 if (server_workgroup) {
2842 cli->server_domain = talloc_strdup(cli, server_workgroup);
2843 if (tevent_req_nomem(cli->server_domain, req)) {
2844 return;
2848 cli->conn.protocol = protocol;
2850 cli->conn.smb1.server.capabilities = server_capabilities;
2851 cli->conn.smb1.capabilities = capabilities;
2853 cli->conn.smb1.server.max_xmit = server_max_xmit;
2854 cli->conn.smb1.max_xmit = max_xmit;
2856 cli->conn.smb1.server.max_mux = server_max_mux;
2858 cli->conn.smb1.server.security_mode = server_security_mode;
2860 cli->conn.smb1.server.readbraw = server_readbraw;
2861 cli->conn.smb1.server.writebraw = server_writebraw;
2862 cli->conn.smb1.server.lockread = server_lockread;
2863 cli->conn.smb1.server.writeunlock = server_writeunlock;
2865 cli->conn.smb1.server.session_key = server_session_key;
2867 talloc_steal(cli, server_gss_blob.data);
2868 cli->conn.smb1.server.gss_blob = server_gss_blob;
2869 cli->conn.smb1.server.guid = server_guid;
2870 memcpy(cli->conn.smb1.server.challenge, server_challenge, 8);
2871 cli->conn.smb1.server.workgroup = talloc_move(cli, &server_workgroup);
2873 cli->conn.smb1.server.time_zone = server_time_zone;
2874 cli->conn.smb1.server.system_time = server_system_time;
2876 tevent_req_done(req);
2879 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2881 return tevent_req_simple_recv_ntstatus(req);
2884 NTSTATUS cli_negprot(struct cli_state *cli, enum protocol_types max_protocol)
2886 TALLOC_CTX *frame = talloc_stackframe();
2887 struct event_context *ev;
2888 struct tevent_req *req;
2889 NTSTATUS status = NT_STATUS_OK;
2891 if (cli_has_async_calls(cli)) {
2893 * Can't use sync call while an async call is in flight
2895 status = NT_STATUS_INVALID_PARAMETER;
2896 goto fail;
2899 ev = event_context_init(frame);
2900 if (ev == NULL) {
2901 status = NT_STATUS_NO_MEMORY;
2902 goto fail;
2905 req = cli_negprot_send(frame, ev, cli, max_protocol);
2906 if (req == NULL) {
2907 status = NT_STATUS_NO_MEMORY;
2908 goto fail;
2911 if (!tevent_req_poll(req, ev)) {
2912 status = map_nt_error_from_unix(errno);
2913 goto fail;
2916 status = cli_negprot_recv(req);
2917 fail:
2918 TALLOC_FREE(frame);
2919 return status;
2922 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2923 const struct sockaddr_storage *pss,
2924 const char *myname, uint16_t port,
2925 int sec_timeout, int *pfd, uint16_t *pport)
2927 TALLOC_CTX *frame = talloc_stackframe();
2928 const char *prog;
2929 unsigned int i, num_addrs;
2930 const char **called_names;
2931 const char **calling_names;
2932 int *called_types;
2933 NTSTATUS status;
2934 int fd;
2936 prog = getenv("LIBSMB_PROG");
2937 if (prog != NULL) {
2938 fd = sock_exec(prog);
2939 if (fd == -1) {
2940 return map_nt_error_from_unix(errno);
2942 port = 0;
2943 goto done;
2946 if ((pss == NULL) || is_zero_addr(pss)) {
2947 struct sockaddr_storage *addrs;
2948 status = resolve_name_list(talloc_tos(), host, name_type,
2949 &addrs, &num_addrs);
2950 if (!NT_STATUS_IS_OK(status)) {
2951 goto fail;
2953 pss = addrs;
2954 } else {
2955 num_addrs = 1;
2958 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2959 if (called_names == NULL) {
2960 status = NT_STATUS_NO_MEMORY;
2961 goto fail;
2963 called_types = talloc_array(talloc_tos(), int, num_addrs);
2964 if (called_types == NULL) {
2965 status = NT_STATUS_NO_MEMORY;
2966 goto fail;
2968 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2969 if (calling_names == NULL) {
2970 status = NT_STATUS_NO_MEMORY;
2971 goto fail;
2973 for (i=0; i<num_addrs; i++) {
2974 called_names[i] = host;
2975 called_types[i] = name_type;
2976 calling_names[i] = myname;
2978 status = smbsock_any_connect(pss, called_names, called_types,
2979 calling_names, NULL, num_addrs, port,
2980 sec_timeout, &fd, NULL, &port);
2981 if (!NT_STATUS_IS_OK(status)) {
2982 goto fail;
2984 set_socket_options(fd, lp_socket_options());
2985 done:
2986 *pfd = fd;
2987 *pport = port;
2988 status = NT_STATUS_OK;
2989 fail:
2990 TALLOC_FREE(frame);
2991 return status;
2994 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2995 uint16_t port, int name_type, const char *myname,
2996 int signing_state, int flags, struct cli_state **pcli)
2998 TALLOC_CTX *frame = talloc_stackframe();
2999 struct cli_state *cli;
3000 NTSTATUS status = NT_STATUS_NO_MEMORY;
3001 int fd = -1;
3002 char *desthost;
3003 char *p;
3005 desthost = talloc_strdup(talloc_tos(), host);
3006 if (desthost == NULL) {
3007 goto fail;
3010 p = strchr(host, '#');
3011 if (p != NULL) {
3012 name_type = strtol(p+1, NULL, 16);
3013 host = talloc_strndup(talloc_tos(), host, p - host);
3014 if (host == NULL) {
3015 goto fail;
3019 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
3020 20, &fd, &port);
3021 if (!NT_STATUS_IS_OK(status)) {
3022 goto fail;
3025 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
3026 if (cli == NULL) {
3027 goto fail;
3030 *pcli = cli;
3031 status = NT_STATUS_OK;
3032 fail:
3033 TALLOC_FREE(frame);
3034 return status;
3038 establishes a connection to after the negprot.
3039 @param output_cli A fully initialised cli structure, non-null only on success
3040 @param dest_host The netbios name of the remote host
3041 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3042 @param port (optional) The destination port (0 for default)
3044 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3045 const char *my_name,
3046 const char *dest_host,
3047 const struct sockaddr_storage *dest_ss, int port,
3048 int signing_state, int flags)
3050 NTSTATUS nt_status;
3051 struct cli_state *cli;
3053 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
3054 signing_state, flags, &cli);
3055 if (!NT_STATUS_IS_OK(nt_status)) {
3056 DEBUG(10, ("cli_connect_nb failed: %s\n",
3057 nt_errstr(nt_status)));
3058 return nt_status;
3061 nt_status = cli_negprot(cli, PROTOCOL_NT1);
3062 if (!NT_STATUS_IS_OK(nt_status)) {
3063 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3064 cli_shutdown(cli);
3065 return nt_status;
3068 *output_cli = cli;
3069 return NT_STATUS_OK;
3074 establishes a connection right up to doing tconX, password specified.
3075 @param output_cli A fully initialised cli structure, non-null only on success
3076 @param dest_host The netbios name of the remote host
3077 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3078 @param port (optional) The destination port (0 for default)
3079 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3080 @param service_type The 'type' of serivice.
3081 @param user Username, unix string
3082 @param domain User's domain
3083 @param password User's password, unencrypted unix string.
3086 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3087 const char *my_name,
3088 const char *dest_host,
3089 const struct sockaddr_storage *dest_ss, int port,
3090 const char *service, const char *service_type,
3091 const char *user, const char *domain,
3092 const char *password, int flags,
3093 int signing_state)
3095 NTSTATUS nt_status;
3096 struct cli_state *cli = NULL;
3097 int pw_len = password ? strlen(password)+1 : 0;
3099 *output_cli = NULL;
3101 if (password == NULL) {
3102 password = "";
3105 nt_status = cli_start_connection(&cli, my_name, dest_host,
3106 dest_ss, port, signing_state,
3107 flags);
3109 if (!NT_STATUS_IS_OK(nt_status)) {
3110 return nt_status;
3113 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3114 pw_len, domain);
3115 if (!NT_STATUS_IS_OK(nt_status)) {
3117 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3118 DEBUG(1,("failed session setup with %s\n",
3119 nt_errstr(nt_status)));
3120 cli_shutdown(cli);
3121 return nt_status;
3124 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3125 if (!NT_STATUS_IS_OK(nt_status)) {
3126 DEBUG(1,("anonymous failed session setup with %s\n",
3127 nt_errstr(nt_status)));
3128 cli_shutdown(cli);
3129 return nt_status;
3133 if (service) {
3134 nt_status = cli_tcon_andx(cli, service, service_type, password,
3135 pw_len);
3136 if (!NT_STATUS_IS_OK(nt_status)) {
3137 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3138 cli_shutdown(cli);
3139 if (NT_STATUS_IS_OK(nt_status)) {
3140 nt_status = NT_STATUS_UNSUCCESSFUL;
3142 return nt_status;
3146 nt_status = cli_init_creds(cli, user, domain, password);
3147 if (!NT_STATUS_IS_OK(nt_status)) {
3148 cli_shutdown(cli);
3149 return nt_status;
3152 *output_cli = cli;
3153 return NT_STATUS_OK;
3156 /****************************************************************************
3157 Send an old style tcon.
3158 ****************************************************************************/
3159 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3160 const char *service, const char *pass, const char *dev,
3161 uint16 *max_xmit, uint16 *tid)
3163 struct tevent_req *req;
3164 uint16_t *ret_vwv;
3165 uint8_t *bytes;
3166 NTSTATUS status;
3168 if (!lp_client_plaintext_auth() && (*pass)) {
3169 DEBUG(1, ("Server requested plaintext password but 'client "
3170 "plaintext auth' is disabled\n"));
3171 return NT_STATUS_ACCESS_DENIED;
3174 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3175 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3176 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3177 service, strlen(service)+1, NULL);
3178 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3179 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3180 pass, strlen(pass)+1, NULL);
3181 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3182 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3183 dev, strlen(dev)+1, NULL);
3185 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3186 talloc_get_size(bytes), bytes, &req,
3187 2, NULL, &ret_vwv, NULL, NULL);
3188 if (!NT_STATUS_IS_OK(status)) {
3189 return status;
3192 *max_xmit = SVAL(ret_vwv + 0, 0);
3193 *tid = SVAL(ret_vwv + 1, 0);
3195 return NT_STATUS_OK;
3198 /* Return a cli_state pointing at the IPC$ share for the given server */
3200 struct cli_state *get_ipc_connect(char *server,
3201 struct sockaddr_storage *server_ss,
3202 const struct user_auth_info *user_info)
3204 struct cli_state *cli;
3205 NTSTATUS nt_status;
3206 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3208 if (user_info->use_kerberos) {
3209 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3212 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3213 user_info->username ? user_info->username : "",
3214 lp_workgroup(),
3215 user_info->password ? user_info->password : "",
3216 flags,
3217 Undefined);
3219 if (NT_STATUS_IS_OK(nt_status)) {
3220 return cli;
3221 } else if (is_ipaddress(server)) {
3222 /* windows 9* needs a correct NMB name for connections */
3223 fstring remote_name;
3225 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3226 cli = get_ipc_connect(remote_name, server_ss, user_info);
3227 if (cli)
3228 return cli;
3231 return NULL;
3235 * Given the IP address of a master browser on the network, return its
3236 * workgroup and connect to it.
3238 * This function is provided to allow additional processing beyond what
3239 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3240 * browsers and obtain each master browsers' list of domains (in case the
3241 * first master browser is recently on the network and has not yet
3242 * synchronized with other master browsers and therefore does not yet have the
3243 * entire network browse list)
3246 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3247 struct sockaddr_storage *mb_ip,
3248 const struct user_auth_info *user_info,
3249 char **pp_workgroup_out)
3251 char addr[INET6_ADDRSTRLEN];
3252 fstring name;
3253 struct cli_state *cli;
3254 struct sockaddr_storage server_ss;
3256 *pp_workgroup_out = NULL;
3258 print_sockaddr(addr, sizeof(addr), mb_ip);
3259 DEBUG(99, ("Looking up name of master browser %s\n",
3260 addr));
3263 * Do a name status query to find out the name of the master browser.
3264 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3265 * master browser will not respond to a wildcard query (or, at least,
3266 * an NT4 server acting as the domain master browser will not).
3268 * We might be able to use ONLY the query on MSBROWSE, but that's not
3269 * yet been tested with all Windows versions, so until it is, leave
3270 * the original wildcard query as the first choice and fall back to
3271 * MSBROWSE if the wildcard query fails.
3273 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3274 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3276 DEBUG(99, ("Could not retrieve name status for %s\n",
3277 addr));
3278 return NULL;
3281 if (!find_master_ip(name, &server_ss)) {
3282 DEBUG(99, ("Could not find master ip for %s\n", name));
3283 return NULL;
3286 *pp_workgroup_out = talloc_strdup(ctx, name);
3288 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3290 print_sockaddr(addr, sizeof(addr), &server_ss);
3291 cli = get_ipc_connect(addr, &server_ss, user_info);
3293 return cli;
3297 * Return the IP address and workgroup of a master browser on the network, and
3298 * connect to it.
3301 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3302 const struct user_auth_info *user_info,
3303 char **pp_workgroup_out)
3305 struct sockaddr_storage *ip_list;
3306 struct cli_state *cli;
3307 int i, count;
3308 NTSTATUS status;
3310 *pp_workgroup_out = NULL;
3312 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3314 /* Go looking for workgroups by broadcasting on the local network */
3316 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3317 &ip_list, &count);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 DEBUG(99, ("No master browsers responded: %s\n",
3320 nt_errstr(status)));
3321 return False;
3324 for (i = 0; i < count; i++) {
3325 char addr[INET6_ADDRSTRLEN];
3326 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3327 DEBUG(99, ("Found master browser %s\n", addr));
3329 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3330 user_info, pp_workgroup_out);
3331 if (cli)
3332 return(cli);
3335 return NULL;