s3:libsmb: move cli->server{zone,time} to cli->conn.smb1.server.{time_zone,system_time}
[Samba.git] / source3 / libsmb / cliconnect.c
blobfd3c1d40aff94a60624c14eafdbff3612bf8d936
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 if (!NT_STATUS_IS_OK(status)) {
1468 TALLOC_FREE(subreq);
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 TALLOC_FREE(subreq);
1479 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1480 return;
1482 TALLOC_FREE(subreq);
1483 tevent_req_done(req);
1486 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1488 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1489 req, struct cli_session_setup_kerberos_state);
1490 NTSTATUS status;
1492 if (tevent_req_is_nterror(req, &status)) {
1493 return ADS_ERROR_NT(status);
1495 return state->ads_status;
1498 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1499 const char *principal)
1501 struct tevent_context *ev;
1502 struct tevent_req *req;
1503 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1505 if (cli_has_async_calls(cli)) {
1506 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1508 ev = tevent_context_init(talloc_tos());
1509 if (ev == NULL) {
1510 goto fail;
1512 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1513 if (req == NULL) {
1514 goto fail;
1516 if (!tevent_req_poll(req, ev)) {
1517 status = ADS_ERROR_SYSTEM(errno);
1518 goto fail;
1520 status = cli_session_setup_kerberos_recv(req);
1521 fail:
1522 TALLOC_FREE(ev);
1523 return status;
1525 #endif /* HAVE_KRB5 */
1527 /****************************************************************************
1528 Do a spnego/NTLMSSP encrypted session setup.
1529 ****************************************************************************/
1531 struct cli_session_setup_ntlmssp_state {
1532 struct tevent_context *ev;
1533 struct cli_state *cli;
1534 struct ntlmssp_state *ntlmssp_state;
1535 int turn;
1536 DATA_BLOB blob_out;
1539 static int cli_session_setup_ntlmssp_state_destructor(
1540 struct cli_session_setup_ntlmssp_state *state)
1542 if (state->ntlmssp_state != NULL) {
1543 TALLOC_FREE(state->ntlmssp_state);
1545 return 0;
1548 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1550 static struct tevent_req *cli_session_setup_ntlmssp_send(
1551 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1552 const char *user, const char *pass, const char *domain)
1554 struct tevent_req *req, *subreq;
1555 struct cli_session_setup_ntlmssp_state *state;
1556 NTSTATUS status;
1557 DATA_BLOB blob_out;
1558 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1560 req = tevent_req_create(mem_ctx, &state,
1561 struct cli_session_setup_ntlmssp_state);
1562 if (req == NULL) {
1563 return NULL;
1565 state->ev = ev;
1566 state->cli = cli;
1567 state->turn = 1;
1569 state->ntlmssp_state = NULL;
1570 talloc_set_destructor(
1571 state, cli_session_setup_ntlmssp_state_destructor);
1573 status = ntlmssp_client_start(state,
1574 lp_netbios_name(),
1575 lp_workgroup(),
1576 lp_client_ntlmv2_auth(),
1577 &state->ntlmssp_state);
1578 if (!NT_STATUS_IS_OK(status)) {
1579 goto fail;
1581 ntlmssp_want_feature(state->ntlmssp_state,
1582 NTLMSSP_FEATURE_SESSION_KEY);
1583 if (cli->use_ccache) {
1584 ntlmssp_want_feature(state->ntlmssp_state,
1585 NTLMSSP_FEATURE_CCACHE);
1587 status = ntlmssp_set_username(state->ntlmssp_state, user);
1588 if (!NT_STATUS_IS_OK(status)) {
1589 goto fail;
1591 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1592 if (!NT_STATUS_IS_OK(status)) {
1593 goto fail;
1595 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1596 if (!NT_STATUS_IS_OK(status)) {
1597 goto fail;
1599 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1600 &blob_out);
1601 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1602 goto fail;
1605 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1606 data_blob_free(&blob_out);
1608 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1609 if (tevent_req_nomem(subreq, req)) {
1610 return tevent_req_post(req, ev);
1612 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1613 return req;
1614 fail:
1615 tevent_req_nterror(req, status);
1616 return tevent_req_post(req, ev);
1619 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1621 struct tevent_req *req = tevent_req_callback_data(
1622 subreq, struct tevent_req);
1623 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1624 req, struct cli_session_setup_ntlmssp_state);
1625 DATA_BLOB blob_in, msg_in, blob_out;
1626 char *inbuf = NULL;
1627 bool parse_ret;
1628 NTSTATUS status;
1630 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1631 &inbuf);
1632 TALLOC_FREE(subreq);
1633 data_blob_free(&state->blob_out);
1635 if (NT_STATUS_IS_OK(status)) {
1636 if (state->cli->server_domain[0] == '\0') {
1637 TALLOC_FREE(state->cli->server_domain);
1638 state->cli->server_domain = talloc_strdup(state->cli,
1639 state->ntlmssp_state->server.netbios_domain);
1640 if (state->cli->server_domain == NULL) {
1641 TALLOC_FREE(subreq);
1642 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1643 return;
1646 cli_set_session_key(
1647 state->cli, state->ntlmssp_state->session_key);
1649 if (cli_simple_set_signing(
1650 state->cli, state->ntlmssp_state->session_key,
1651 data_blob_null)
1652 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1653 TALLOC_FREE(subreq);
1654 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1655 return;
1657 TALLOC_FREE(subreq);
1658 TALLOC_FREE(state->ntlmssp_state);
1659 tevent_req_done(req);
1660 return;
1662 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1663 tevent_req_nterror(req, status);
1664 return;
1667 if (blob_in.length == 0) {
1668 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1669 return;
1672 if ((state->turn == 1)
1673 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1674 DATA_BLOB tmp_blob = data_blob_null;
1675 /* the server might give us back two challenges */
1676 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1677 &tmp_blob);
1678 data_blob_free(&tmp_blob);
1679 } else {
1680 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1681 OID_NTLMSSP, &msg_in);
1683 state->turn += 1;
1685 if (!parse_ret) {
1686 DEBUG(3,("Failed to parse auth response\n"));
1687 if (NT_STATUS_IS_OK(status)
1688 || NT_STATUS_EQUAL(status,
1689 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1690 tevent_req_nterror(
1691 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1692 return;
1696 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1698 if (!NT_STATUS_IS_OK(status)
1699 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1700 TALLOC_FREE(subreq);
1701 TALLOC_FREE(state->ntlmssp_state);
1702 tevent_req_nterror(req, status);
1703 return;
1706 state->blob_out = spnego_gen_auth(state, blob_out);
1707 TALLOC_FREE(subreq);
1708 if (tevent_req_nomem(state->blob_out.data, req)) {
1709 return;
1712 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1713 state->blob_out);
1714 if (tevent_req_nomem(subreq, req)) {
1715 return;
1717 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1720 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1722 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1723 req, struct cli_session_setup_ntlmssp_state);
1724 NTSTATUS status;
1726 if (tevent_req_is_nterror(req, &status)) {
1727 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1728 return status;
1730 return NT_STATUS_OK;
1733 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1734 const char *user,
1735 const char *pass,
1736 const char *domain)
1738 struct tevent_context *ev;
1739 struct tevent_req *req;
1740 NTSTATUS status = NT_STATUS_NO_MEMORY;
1742 if (cli_has_async_calls(cli)) {
1743 return NT_STATUS_INVALID_PARAMETER;
1745 ev = tevent_context_init(talloc_tos());
1746 if (ev == NULL) {
1747 goto fail;
1749 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1750 if (req == NULL) {
1751 goto fail;
1753 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1754 goto fail;
1756 status = cli_session_setup_ntlmssp_recv(req);
1757 fail:
1758 TALLOC_FREE(ev);
1759 return status;
1762 /****************************************************************************
1763 Do a spnego encrypted session setup.
1765 user_domain: The shortname of the domain the user/machine is a member of.
1766 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1767 ****************************************************************************/
1769 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1770 const char *user,
1771 const char *pass,
1772 const char *user_domain,
1773 const char * dest_realm)
1775 char *principal = NULL;
1776 char *OIDs[ASN1_MAX_OIDS];
1777 int i;
1778 DATA_BLOB *server_blob;
1779 DATA_BLOB blob = data_blob_null;
1780 const char *p = NULL;
1781 char *account = NULL;
1782 NTSTATUS status;
1784 server_blob = cli_state_server_gss_blob(cli);
1785 if (server_blob) {
1786 blob = data_blob(server_blob->data, server_blob->length);
1789 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)blob.length));
1791 /* the server might not even do spnego */
1792 if (blob.length == 0) {
1793 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1794 goto ntlmssp;
1797 #if 0
1798 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1799 #endif
1801 /* The server sent us the first part of the SPNEGO exchange in the
1802 * negprot reply. It is WRONG to depend on the principal sent in the
1803 * negprot reply, but right now we do it. If we don't receive one,
1804 * we try to best guess, then fall back to NTLM. */
1805 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1806 OIDs[0] == NULL) {
1807 data_blob_free(&blob);
1808 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1810 data_blob_free(&blob);
1812 /* make sure the server understands kerberos */
1813 for (i=0;OIDs[i];i++) {
1814 if (i == 0)
1815 DEBUG(3,("got OID=%s\n", OIDs[i]));
1816 else
1817 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1818 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1819 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1820 cli->got_kerberos_mechanism = True;
1822 talloc_free(OIDs[i]);
1825 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1827 status = cli_set_username(cli, user);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 TALLOC_FREE(principal);
1830 return ADS_ERROR_NT(status);
1833 #ifdef HAVE_KRB5
1834 /* If password is set we reauthenticate to kerberos server
1835 * and do not store results */
1837 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1838 ADS_STATUS rc;
1839 const char *remote_name = cli_state_remote_name(cli);
1841 if (pass && *pass) {
1842 int ret;
1844 use_in_memory_ccache();
1845 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1847 if (ret){
1848 TALLOC_FREE(principal);
1849 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1850 if (cli->fallback_after_kerberos)
1851 goto ntlmssp;
1852 return ADS_ERROR_KRB5(ret);
1856 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1858 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1859 TALLOC_FREE(principal);
1862 if (principal == NULL &&
1863 !is_ipaddress(remote_name) &&
1864 !strequal(STAR_SMBSERVER,
1865 remote_name)) {
1866 char *realm = NULL;
1867 char *host = NULL;
1868 DEBUG(3,("cli_session_setup_spnego: using target "
1869 "hostname not SPNEGO principal\n"));
1871 host = strchr_m(remote_name, '.');
1872 if (dest_realm) {
1873 realm = SMB_STRDUP(dest_realm);
1874 if (!realm) {
1875 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1877 strupper_m(realm);
1878 } else {
1879 if (host) {
1880 /* DNS name. */
1881 realm = kerberos_get_realm_from_hostname(remote_name);
1882 } else {
1883 /* NetBIOS name - use our realm. */
1884 realm = kerberos_get_default_realm_from_ccache();
1888 if (realm == NULL || *realm == '\0') {
1889 realm = SMB_STRDUP(lp_realm());
1890 if (!realm) {
1891 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1893 strupper_m(realm);
1894 DEBUG(3,("cli_session_setup_spnego: cannot "
1895 "get realm from dest_realm %s, "
1896 "desthost %s. Using default "
1897 "smb.conf realm %s\n",
1898 dest_realm ? dest_realm : "<null>",
1899 remote_name,
1900 realm));
1903 principal = talloc_asprintf(talloc_tos(),
1904 "cifs/%s@%s",
1905 remote_name,
1906 realm);
1907 if (!principal) {
1908 SAFE_FREE(realm);
1909 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1911 DEBUG(3,("cli_session_setup_spnego: guessed "
1912 "server principal=%s\n",
1913 principal ? principal : "<null>"));
1915 SAFE_FREE(realm);
1918 if (principal) {
1919 rc = cli_session_setup_kerberos(cli, principal);
1920 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1921 TALLOC_FREE(principal);
1922 return rc;
1926 #endif
1928 TALLOC_FREE(principal);
1930 ntlmssp:
1932 account = talloc_strdup(talloc_tos(), user);
1933 if (!account) {
1934 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1937 /* when falling back to ntlmssp while authenticating with a machine
1938 * account strip off the realm - gd */
1940 if ((p = strchr_m(user, '@')) != NULL) {
1941 account[PTR_DIFF(p,user)] = '\0';
1944 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1947 /****************************************************************************
1948 Send a session setup. The username and workgroup is in UNIX character
1949 format and must be converted to DOS codepage format before sending. If the
1950 password is in plaintext, the same should be done.
1951 ****************************************************************************/
1953 NTSTATUS cli_session_setup(struct cli_state *cli,
1954 const char *user,
1955 const char *pass, int passlen,
1956 const char *ntpass, int ntpasslen,
1957 const char *workgroup)
1959 char *p;
1960 char *user2;
1961 uint16_t sec_mode = cli_state_security_mode(cli);
1963 if (user) {
1964 user2 = talloc_strdup(talloc_tos(), user);
1965 } else {
1966 user2 = talloc_strdup(talloc_tos(), "");
1968 if (user2 == NULL) {
1969 return NT_STATUS_NO_MEMORY;
1972 if (!workgroup) {
1973 workgroup = "";
1976 /* allow for workgroups as part of the username */
1977 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1978 (p=strchr_m(user2,*lp_winbind_separator()))) {
1979 *p = 0;
1980 user = p+1;
1981 strupper_m(user2);
1982 workgroup = user2;
1985 if (cli_state_protocol(cli) < PROTOCOL_LANMAN1) {
1987 * Ensure cli->server_domain,
1988 * cli->server_os and cli->server_type
1989 * are valid pointers.
1991 cli->server_domain = talloc_strdup(cli, "");
1992 cli->server_os = talloc_strdup(cli, "");
1993 cli->server_type = talloc_strdup(cli, "");
1994 if (cli->server_domain == NULL ||
1995 cli->server_os == NULL ||
1996 cli->server_type == NULL) {
1997 return NT_STATUS_NO_MEMORY;
1999 return NT_STATUS_OK;
2002 /* now work out what sort of session setup we are going to
2003 do. I have split this into separate functions to make the
2004 flow a bit easier to understand (tridge) */
2006 /* if its an older server then we have to use the older request format */
2008 if (cli_state_protocol(cli) < PROTOCOL_NT1) {
2009 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2010 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2011 " or 'client ntlmv2 auth = yes'\n"));
2012 return NT_STATUS_ACCESS_DENIED;
2015 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2016 !lp_client_plaintext_auth() && (*pass)) {
2017 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2018 " or 'client ntlmv2 auth = yes'\n"));
2019 return NT_STATUS_ACCESS_DENIED;
2022 return cli_session_setup_lanman2(cli, user, pass, passlen,
2023 workgroup);
2026 /* if no user is supplied then we have to do an anonymous connection.
2027 passwords are ignored */
2029 if (!user || !*user)
2030 return cli_session_setup_guest(cli);
2032 /* if the server is share level then send a plaintext null
2033 password at this point. The password is sent in the tree
2034 connect */
2036 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2037 return cli_session_setup_plain(cli, user, "", workgroup);
2039 /* if the server doesn't support encryption then we have to use
2040 plaintext. The second password is ignored */
2042 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2043 if (!lp_client_plaintext_auth() && (*pass)) {
2044 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2045 " or 'client ntlmv2 auth = yes'\n"));
2046 return NT_STATUS_ACCESS_DENIED;
2048 return cli_session_setup_plain(cli, user, pass, workgroup);
2051 /* if the server supports extended security then use SPNEGO */
2053 if (cli_state_capabilities(cli) & CAP_EXTENDED_SECURITY) {
2054 const char *remote_realm = cli_state_remote_realm(cli);
2055 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2056 workgroup,
2057 remote_realm);
2058 if (!ADS_ERR_OK(status)) {
2059 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2060 return ads_ntstatus(status);
2062 } else {
2063 NTSTATUS status;
2065 /* otherwise do a NT1 style session setup */
2066 status = cli_session_setup_nt1(cli, user, pass, passlen,
2067 ntpass, ntpasslen, workgroup);
2068 if (!NT_STATUS_IS_OK(status)) {
2069 DEBUG(3,("cli_session_setup: NT1 session setup "
2070 "failed: %s\n", nt_errstr(status)));
2071 return status;
2075 return NT_STATUS_OK;
2078 /****************************************************************************
2079 Send a uloggoff.
2080 *****************************************************************************/
2082 struct cli_ulogoff_state {
2083 struct cli_state *cli;
2084 uint16_t vwv[3];
2087 static void cli_ulogoff_done(struct tevent_req *subreq);
2089 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2090 struct tevent_context *ev,
2091 struct cli_state *cli)
2093 struct tevent_req *req, *subreq;
2094 struct cli_ulogoff_state *state;
2096 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2097 if (req == NULL) {
2098 return NULL;
2100 state->cli = cli;
2102 SCVAL(state->vwv+0, 0, 0xFF);
2103 SCVAL(state->vwv+1, 0, 0);
2104 SSVAL(state->vwv+2, 0, 0);
2106 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2107 0, NULL);
2108 if (tevent_req_nomem(subreq, req)) {
2109 return tevent_req_post(req, ev);
2111 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2112 return req;
2115 static void cli_ulogoff_done(struct tevent_req *subreq)
2117 struct tevent_req *req = tevent_req_callback_data(
2118 subreq, struct tevent_req);
2119 struct cli_ulogoff_state *state = tevent_req_data(
2120 req, struct cli_ulogoff_state);
2121 NTSTATUS status;
2123 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2124 if (!NT_STATUS_IS_OK(status)) {
2125 tevent_req_nterror(req, status);
2126 return;
2128 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2129 tevent_req_done(req);
2132 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2134 return tevent_req_simple_recv_ntstatus(req);
2137 NTSTATUS cli_ulogoff(struct cli_state *cli)
2139 struct tevent_context *ev;
2140 struct tevent_req *req;
2141 NTSTATUS status = NT_STATUS_NO_MEMORY;
2143 if (cli_has_async_calls(cli)) {
2144 return NT_STATUS_INVALID_PARAMETER;
2146 ev = tevent_context_init(talloc_tos());
2147 if (ev == NULL) {
2148 goto fail;
2150 req = cli_ulogoff_send(ev, ev, cli);
2151 if (req == NULL) {
2152 goto fail;
2154 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2155 goto fail;
2157 status = cli_ulogoff_recv(req);
2158 fail:
2159 TALLOC_FREE(ev);
2160 return status;
2163 /****************************************************************************
2164 Send a tconX.
2165 ****************************************************************************/
2167 struct cli_tcon_andx_state {
2168 struct cli_state *cli;
2169 uint16_t vwv[4];
2170 struct iovec bytes;
2173 static void cli_tcon_andx_done(struct tevent_req *subreq);
2175 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2176 struct event_context *ev,
2177 struct cli_state *cli,
2178 const char *share, const char *dev,
2179 const char *pass, int passlen,
2180 struct tevent_req **psmbreq)
2182 struct tevent_req *req, *subreq;
2183 struct cli_tcon_andx_state *state;
2184 uint8_t p24[24];
2185 uint16_t *vwv;
2186 char *tmp = NULL;
2187 uint8_t *bytes;
2188 uint16_t sec_mode = cli_state_security_mode(cli);
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 (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 ((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_state_server_challenge(cli), p24);
2228 passlen = 24;
2229 pass = (const char *)p24;
2230 } else {
2231 if((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_state_remote_name(cli), 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_state_protocol(cli) >= 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_state_protocol(cli) >= 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;
2542 enum protocol_types max_protocol;
2545 static void cli_negprot_done(struct tevent_req *subreq);
2547 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2548 struct event_context *ev,
2549 struct cli_state *cli,
2550 enum protocol_types max_protocol)
2552 struct tevent_req *req, *subreq;
2553 struct cli_negprot_state *state;
2554 uint8_t *bytes = NULL;
2555 int numprots;
2556 enum protocol_types tmp_protocol;
2558 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2559 if (req == NULL) {
2560 return NULL;
2562 state->cli = cli;
2563 state->max_protocol = max_protocol;
2565 /* setup the protocol strings */
2566 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2567 uint8_t c = 2;
2568 if (prots[numprots].prot > state->max_protocol) {
2569 break;
2571 bytes = (uint8_t *)talloc_append_blob(
2572 state, bytes, data_blob_const(&c, sizeof(c)));
2573 if (tevent_req_nomem(bytes, req)) {
2574 return tevent_req_post(req, ev);
2576 bytes = smb_bytes_push_str(bytes, false,
2577 prots[numprots].name,
2578 strlen(prots[numprots].name)+1,
2579 NULL);
2580 if (tevent_req_nomem(bytes, req)) {
2581 return tevent_req_post(req, ev);
2585 tmp_protocol = cli->conn.protocol;
2586 cli->conn.protocol = state->max_protocol;
2587 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2588 talloc_get_size(bytes), bytes);
2589 cli->conn.protocol = tmp_protocol;
2590 if (tevent_req_nomem(subreq, req)) {
2591 return tevent_req_post(req, ev);
2593 tevent_req_set_callback(subreq, cli_negprot_done, req);
2594 return req;
2597 static void cli_negprot_done(struct tevent_req *subreq)
2599 struct tevent_req *req = tevent_req_callback_data(
2600 subreq, struct tevent_req);
2601 struct cli_negprot_state *state = tevent_req_data(
2602 req, struct cli_negprot_state);
2603 struct cli_state *cli = state->cli;
2604 uint8_t flags;
2605 uint8_t wct;
2606 uint16_t *vwv;
2607 uint32_t num_bytes;
2608 uint8_t *bytes;
2609 NTSTATUS status;
2610 uint16_t protnum;
2611 uint8_t *inbuf;
2612 uint32_t client_capabilities = cli->conn.smb1.client.capabilities;
2613 uint32_t both_capabilities;
2614 uint32_t server_capabilities = 0;
2615 uint32_t capabilities;
2616 uint32_t client_max_xmit = cli->conn.smb1.client.max_xmit;
2617 uint32_t server_max_xmit = 0;
2618 uint32_t max_xmit;
2619 uint32_t server_max_mux = 0;
2620 uint16_t server_security_mode = 0;
2621 uint32_t server_session_key = 0;
2622 bool server_readbraw = false;
2623 bool server_writebraw = false;
2624 bool server_lockread = false;
2625 bool server_writeunlock = false;
2626 struct GUID server_guid = GUID_zero();
2627 DATA_BLOB server_gss_blob = data_blob_null;
2628 uint8_t server_challenge[8];
2629 char *server_workgroup = NULL;
2630 int server_time_zone = 0;
2631 time_t server_system_time = 0;
2632 enum protocol_types protocol;
2634 ZERO_STRUCT(server_challenge);
2636 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2637 &num_bytes, &bytes);
2638 TALLOC_FREE(subreq);
2639 if (!NT_STATUS_IS_OK(status)) {
2640 tevent_req_nterror(req, status);
2641 return;
2644 flags = CVAL(inbuf, smb_flg);
2646 protnum = SVAL(vwv, 0);
2648 if ((protnum >= ARRAY_SIZE(prots))
2649 || (prots[protnum].prot > state->max_protocol)) {
2650 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2651 return;
2654 protocol = prots[protnum].prot;
2656 if ((protocol < PROTOCOL_NT1) &&
2657 client_is_signing_mandatory(cli)) {
2658 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2659 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2660 return;
2663 if (flags & FLAG_SUPPORT_LOCKREAD) {
2664 server_lockread = true;
2665 server_writeunlock = true;
2668 if (protocol >= PROTOCOL_NT1) {
2669 struct timespec ts;
2670 const char *client_signing = NULL;
2671 bool server_mandatory;
2672 bool server_allowed;
2673 const char *server_signing = NULL;
2674 bool ok;
2675 uint16_t key_len;
2677 if (wct != 0x11) {
2678 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2679 return;
2682 /* NT protocol */
2683 server_security_mode = CVAL(vwv + 1, 0);
2684 server_max_mux = SVAL(vwv + 1, 1);
2685 server_max_xmit = IVAL(vwv + 3, 1);
2686 server_session_key = IVAL(vwv + 7, 1);
2687 server_time_zone = SVALS(vwv + 15, 1);
2688 server_time_zone *= 60;
2689 /* this time arrives in real GMT */
2690 ts = interpret_long_date(((char *)(vwv+11))+1);
2691 server_system_time = ts.tv_sec;
2692 server_capabilities = IVAL(vwv + 9, 1);
2694 key_len = CVAL(vwv + 16, 1);
2696 if (server_capabilities & CAP_RAW_MODE) {
2697 server_readbraw = true;
2698 server_writebraw = true;
2700 if (server_capabilities & CAP_LOCK_AND_READ) {
2701 server_lockread = true;
2704 if (server_capabilities & CAP_EXTENDED_SECURITY) {
2705 DATA_BLOB blob1, blob2;
2707 if (num_bytes < 16) {
2708 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2709 return;
2712 blob1 = data_blob_const(bytes, 16);
2713 GUID_from_data_blob(&blob1, &server_guid);
2715 blob1 = data_blob_const(bytes+16, num_bytes-16);
2716 blob2 = data_blob_dup_talloc(state, &blob1);
2717 if (blob1.length > 0 &&
2718 tevent_req_nomem(blob2.data, req)) {
2719 return;
2721 server_gss_blob = blob2;
2722 } else {
2723 DATA_BLOB blob1;
2724 ssize_t ret;
2726 if (num_bytes < key_len) {
2727 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2728 return;
2731 if (key_len != 0 && key_len != 8) {
2732 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2733 return;
2736 if (key_len == 8) {
2737 memcpy(server_challenge, bytes, 8);
2740 blob1 = data_blob_const(bytes+key_len, num_bytes-key_len);
2741 if (blob1.length > 0) {
2742 ret = pull_string_talloc(state,
2743 (char *)inbuf,
2744 SVAL(inbuf, smb_flg2),
2745 &server_workgroup,
2746 blob1.data, blob1.length,
2747 STR_TERMINATE);
2748 if (ret == -1) {
2749 tevent_req_oom(req);
2750 return;
2755 client_signing = "disabled";
2756 if (client_is_signing_allowed(cli)) {
2757 client_signing = "allowed";
2759 if (client_is_signing_mandatory(cli)) {
2760 client_signing = "required";
2763 server_signing = "not supported";
2764 if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2765 server_signing = "supported";
2766 server_allowed = true;
2768 if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2769 server_signing = "required";
2770 server_mandatory = true;
2773 ok = cli_set_signing_negotiated(cli,
2774 server_allowed,
2775 server_mandatory);
2776 if (!ok) {
2777 DEBUG(1,("cli_negprot: SMB signing is required, "
2778 "but client[%s] and server[%s] mismatch\n",
2779 client_signing, server_signing));
2780 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2781 return;
2784 } else if (protocol >= PROTOCOL_LANMAN1) {
2785 if (wct != 0x0D) {
2786 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2787 return;
2790 server_security_mode = SVAL(vwv + 1, 0);
2791 server_max_xmit = SVAL(vwv + 2, 0);
2792 server_max_mux = SVAL(vwv + 3, 0);
2793 server_session_key = IVAL(vwv + 6, 0);
2794 server_time_zone = SVALS(vwv + 10, 0);
2795 server_time_zone *= 60;
2796 /* this time is converted to GMT by make_unix_date */
2797 server_system_time = make_unix_date(
2798 (char *)(vwv + 8), server_time_zone);
2799 server_readbraw = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2800 server_writebraw = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2802 if (num_bytes != 0 && num_bytes != 8) {
2803 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2804 return;
2807 if (num_bytes == 8) {
2808 memcpy(server_challenge, bytes, 8);
2810 } else {
2811 /* the old core protocol */
2812 server_time_zone = get_time_zone(time(NULL));
2813 server_system_time = 0;
2814 server_max_xmit = 1024;
2815 server_max_mux = 1;
2816 server_security_mode = 0;
2819 if (server_max_xmit < 1024) {
2820 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2821 return;
2824 if (server_max_mux < 1) {
2825 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2826 return;
2830 * Now calculate the negotiated capabilities
2831 * based on the mask for:
2832 * - client only flags
2833 * - flags used in both directions
2834 * - server only flags
2836 both_capabilities = client_capabilities & server_capabilities;
2837 capabilities = client_capabilities & SMB_CAP_CLIENT_MASK;
2838 capabilities |= both_capabilities & SMB_CAP_BOTH_MASK;
2839 capabilities |= server_capabilities & SMB_CAP_SERVER_MASK;
2841 max_xmit = MIN(client_max_xmit, server_max_xmit);
2843 if (server_workgroup) {
2844 cli->server_domain = talloc_strdup(cli, server_workgroup);
2845 if (tevent_req_nomem(cli->server_domain, req)) {
2846 return;
2850 cli->conn.protocol = protocol;
2852 cli->conn.smb1.server.capabilities = server_capabilities;
2853 cli->conn.smb1.capabilities = capabilities;
2855 cli->conn.smb1.server.max_xmit = server_max_xmit;
2856 cli->conn.smb1.max_xmit = max_xmit;
2858 cli->conn.smb1.server.max_mux = server_max_mux;
2860 cli->conn.smb1.server.security_mode = server_security_mode;
2862 cli->conn.smb1.server.readbraw = server_readbraw;
2863 cli->conn.smb1.server.writebraw = server_writebraw;
2864 cli->conn.smb1.server.lockread = server_lockread;
2865 cli->conn.smb1.server.writeunlock = server_writeunlock;
2867 cli->conn.smb1.server.session_key = server_session_key;
2869 talloc_steal(cli, server_gss_blob.data);
2870 cli->conn.smb1.server.gss_blob = server_gss_blob;
2871 cli->conn.smb1.server.guid = server_guid;
2872 memcpy(cli->conn.smb1.server.challenge, server_challenge, 8);
2873 cli->conn.smb1.server.workgroup = talloc_move(cli, &server_workgroup);
2875 cli->conn.smb1.server.time_zone = server_time_zone;
2876 cli->conn.smb1.server.system_time = server_system_time;
2878 tevent_req_done(req);
2881 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2883 return tevent_req_simple_recv_ntstatus(req);
2886 NTSTATUS cli_negprot(struct cli_state *cli, enum protocol_types max_protocol)
2888 TALLOC_CTX *frame = talloc_stackframe();
2889 struct event_context *ev;
2890 struct tevent_req *req;
2891 NTSTATUS status = NT_STATUS_OK;
2893 if (cli_has_async_calls(cli)) {
2895 * Can't use sync call while an async call is in flight
2897 status = NT_STATUS_INVALID_PARAMETER;
2898 goto fail;
2901 ev = event_context_init(frame);
2902 if (ev == NULL) {
2903 status = NT_STATUS_NO_MEMORY;
2904 goto fail;
2907 req = cli_negprot_send(frame, ev, cli, max_protocol);
2908 if (req == NULL) {
2909 status = NT_STATUS_NO_MEMORY;
2910 goto fail;
2913 if (!tevent_req_poll(req, ev)) {
2914 status = map_nt_error_from_unix(errno);
2915 goto fail;
2918 status = cli_negprot_recv(req);
2919 fail:
2920 TALLOC_FREE(frame);
2921 return status;
2924 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2925 const struct sockaddr_storage *pss,
2926 const char *myname, uint16_t port,
2927 int sec_timeout, int *pfd, uint16_t *pport)
2929 TALLOC_CTX *frame = talloc_stackframe();
2930 const char *prog;
2931 unsigned int i, num_addrs;
2932 const char **called_names;
2933 const char **calling_names;
2934 int *called_types;
2935 NTSTATUS status;
2936 int fd;
2938 prog = getenv("LIBSMB_PROG");
2939 if (prog != NULL) {
2940 fd = sock_exec(prog);
2941 if (fd == -1) {
2942 return map_nt_error_from_unix(errno);
2944 port = 0;
2945 goto done;
2948 if ((pss == NULL) || is_zero_addr(pss)) {
2949 struct sockaddr_storage *addrs;
2950 status = resolve_name_list(talloc_tos(), host, name_type,
2951 &addrs, &num_addrs);
2952 if (!NT_STATUS_IS_OK(status)) {
2953 goto fail;
2955 pss = addrs;
2956 } else {
2957 num_addrs = 1;
2960 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2961 if (called_names == NULL) {
2962 status = NT_STATUS_NO_MEMORY;
2963 goto fail;
2965 called_types = talloc_array(talloc_tos(), int, num_addrs);
2966 if (called_types == NULL) {
2967 status = NT_STATUS_NO_MEMORY;
2968 goto fail;
2970 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2971 if (calling_names == NULL) {
2972 status = NT_STATUS_NO_MEMORY;
2973 goto fail;
2975 for (i=0; i<num_addrs; i++) {
2976 called_names[i] = host;
2977 called_types[i] = name_type;
2978 calling_names[i] = myname;
2980 status = smbsock_any_connect(pss, called_names, called_types,
2981 calling_names, NULL, num_addrs, port,
2982 sec_timeout, &fd, NULL, &port);
2983 if (!NT_STATUS_IS_OK(status)) {
2984 goto fail;
2986 set_socket_options(fd, lp_socket_options());
2987 done:
2988 *pfd = fd;
2989 *pport = port;
2990 status = NT_STATUS_OK;
2991 fail:
2992 TALLOC_FREE(frame);
2993 return status;
2996 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2997 uint16_t port, int name_type, const char *myname,
2998 int signing_state, int flags, struct cli_state **pcli)
3000 TALLOC_CTX *frame = talloc_stackframe();
3001 struct cli_state *cli;
3002 NTSTATUS status = NT_STATUS_NO_MEMORY;
3003 int fd = -1;
3004 char *desthost;
3005 char *p;
3007 desthost = talloc_strdup(talloc_tos(), host);
3008 if (desthost == NULL) {
3009 goto fail;
3012 p = strchr(host, '#');
3013 if (p != NULL) {
3014 name_type = strtol(p+1, NULL, 16);
3015 host = talloc_strndup(talloc_tos(), host, p - host);
3016 if (host == NULL) {
3017 goto fail;
3021 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
3022 20, &fd, &port);
3023 if (!NT_STATUS_IS_OK(status)) {
3024 goto fail;
3027 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
3028 if (cli == NULL) {
3029 goto fail;
3032 *pcli = cli;
3033 status = NT_STATUS_OK;
3034 fail:
3035 TALLOC_FREE(frame);
3036 return status;
3040 establishes a connection to after the negprot.
3041 @param output_cli A fully initialised cli structure, non-null only on success
3042 @param dest_host The netbios name of the remote host
3043 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3044 @param port (optional) The destination port (0 for default)
3046 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3047 const char *my_name,
3048 const char *dest_host,
3049 const struct sockaddr_storage *dest_ss, int port,
3050 int signing_state, int flags)
3052 NTSTATUS nt_status;
3053 struct cli_state *cli;
3055 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
3056 signing_state, flags, &cli);
3057 if (!NT_STATUS_IS_OK(nt_status)) {
3058 DEBUG(10, ("cli_connect_nb failed: %s\n",
3059 nt_errstr(nt_status)));
3060 return nt_status;
3063 nt_status = cli_negprot(cli, PROTOCOL_NT1);
3064 if (!NT_STATUS_IS_OK(nt_status)) {
3065 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3066 cli_shutdown(cli);
3067 return nt_status;
3070 *output_cli = cli;
3071 return NT_STATUS_OK;
3076 establishes a connection right up to doing tconX, password specified.
3077 @param output_cli A fully initialised cli structure, non-null only on success
3078 @param dest_host The netbios name of the remote host
3079 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3080 @param port (optional) The destination port (0 for default)
3081 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3082 @param service_type The 'type' of serivice.
3083 @param user Username, unix string
3084 @param domain User's domain
3085 @param password User's password, unencrypted unix string.
3088 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3089 const char *my_name,
3090 const char *dest_host,
3091 const struct sockaddr_storage *dest_ss, int port,
3092 const char *service, const char *service_type,
3093 const char *user, const char *domain,
3094 const char *password, int flags,
3095 int signing_state)
3097 NTSTATUS nt_status;
3098 struct cli_state *cli = NULL;
3099 int pw_len = password ? strlen(password)+1 : 0;
3101 *output_cli = NULL;
3103 if (password == NULL) {
3104 password = "";
3107 nt_status = cli_start_connection(&cli, my_name, dest_host,
3108 dest_ss, port, signing_state,
3109 flags);
3111 if (!NT_STATUS_IS_OK(nt_status)) {
3112 return nt_status;
3115 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3116 pw_len, domain);
3117 if (!NT_STATUS_IS_OK(nt_status)) {
3119 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3120 DEBUG(1,("failed session setup with %s\n",
3121 nt_errstr(nt_status)));
3122 cli_shutdown(cli);
3123 return nt_status;
3126 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3127 if (!NT_STATUS_IS_OK(nt_status)) {
3128 DEBUG(1,("anonymous failed session setup with %s\n",
3129 nt_errstr(nt_status)));
3130 cli_shutdown(cli);
3131 return nt_status;
3135 if (service) {
3136 nt_status = cli_tcon_andx(cli, service, service_type, password,
3137 pw_len);
3138 if (!NT_STATUS_IS_OK(nt_status)) {
3139 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3140 cli_shutdown(cli);
3141 if (NT_STATUS_IS_OK(nt_status)) {
3142 nt_status = NT_STATUS_UNSUCCESSFUL;
3144 return nt_status;
3148 nt_status = cli_init_creds(cli, user, domain, password);
3149 if (!NT_STATUS_IS_OK(nt_status)) {
3150 cli_shutdown(cli);
3151 return nt_status;
3154 *output_cli = cli;
3155 return NT_STATUS_OK;
3158 /****************************************************************************
3159 Send an old style tcon.
3160 ****************************************************************************/
3161 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3162 const char *service, const char *pass, const char *dev,
3163 uint16 *max_xmit, uint16 *tid)
3165 struct tevent_req *req;
3166 uint16_t *ret_vwv;
3167 uint8_t *bytes;
3168 NTSTATUS status;
3170 if (!lp_client_plaintext_auth() && (*pass)) {
3171 DEBUG(1, ("Server requested plaintext password but 'client "
3172 "plaintext auth' is disabled\n"));
3173 return NT_STATUS_ACCESS_DENIED;
3176 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3177 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3178 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3179 service, strlen(service)+1, NULL);
3180 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3181 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3182 pass, strlen(pass)+1, NULL);
3183 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3184 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3185 dev, strlen(dev)+1, NULL);
3187 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3188 talloc_get_size(bytes), bytes, &req,
3189 2, NULL, &ret_vwv, NULL, NULL);
3190 if (!NT_STATUS_IS_OK(status)) {
3191 return status;
3194 *max_xmit = SVAL(ret_vwv + 0, 0);
3195 *tid = SVAL(ret_vwv + 1, 0);
3197 return NT_STATUS_OK;
3200 /* Return a cli_state pointing at the IPC$ share for the given server */
3202 struct cli_state *get_ipc_connect(char *server,
3203 struct sockaddr_storage *server_ss,
3204 const struct user_auth_info *user_info)
3206 struct cli_state *cli;
3207 NTSTATUS nt_status;
3208 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3210 if (user_info->use_kerberos) {
3211 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3214 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3215 user_info->username ? user_info->username : "",
3216 lp_workgroup(),
3217 user_info->password ? user_info->password : "",
3218 flags,
3219 Undefined);
3221 if (NT_STATUS_IS_OK(nt_status)) {
3222 return cli;
3223 } else if (is_ipaddress(server)) {
3224 /* windows 9* needs a correct NMB name for connections */
3225 fstring remote_name;
3227 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3228 cli = get_ipc_connect(remote_name, server_ss, user_info);
3229 if (cli)
3230 return cli;
3233 return NULL;
3237 * Given the IP address of a master browser on the network, return its
3238 * workgroup and connect to it.
3240 * This function is provided to allow additional processing beyond what
3241 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3242 * browsers and obtain each master browsers' list of domains (in case the
3243 * first master browser is recently on the network and has not yet
3244 * synchronized with other master browsers and therefore does not yet have the
3245 * entire network browse list)
3248 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3249 struct sockaddr_storage *mb_ip,
3250 const struct user_auth_info *user_info,
3251 char **pp_workgroup_out)
3253 char addr[INET6_ADDRSTRLEN];
3254 fstring name;
3255 struct cli_state *cli;
3256 struct sockaddr_storage server_ss;
3258 *pp_workgroup_out = NULL;
3260 print_sockaddr(addr, sizeof(addr), mb_ip);
3261 DEBUG(99, ("Looking up name of master browser %s\n",
3262 addr));
3265 * Do a name status query to find out the name of the master browser.
3266 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3267 * master browser will not respond to a wildcard query (or, at least,
3268 * an NT4 server acting as the domain master browser will not).
3270 * We might be able to use ONLY the query on MSBROWSE, but that's not
3271 * yet been tested with all Windows versions, so until it is, leave
3272 * the original wildcard query as the first choice and fall back to
3273 * MSBROWSE if the wildcard query fails.
3275 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3276 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3278 DEBUG(99, ("Could not retrieve name status for %s\n",
3279 addr));
3280 return NULL;
3283 if (!find_master_ip(name, &server_ss)) {
3284 DEBUG(99, ("Could not find master ip for %s\n", name));
3285 return NULL;
3288 *pp_workgroup_out = talloc_strdup(ctx, name);
3290 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3292 print_sockaddr(addr, sizeof(addr), &server_ss);
3293 cli = get_ipc_connect(addr, &server_ss, user_info);
3295 return cli;
3299 * Return the IP address and workgroup of a master browser on the network, and
3300 * connect to it.
3303 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3304 const struct user_auth_info *user_info,
3305 char **pp_workgroup_out)
3307 struct sockaddr_storage *ip_list;
3308 struct cli_state *cli;
3309 int i, count;
3310 NTSTATUS status;
3312 *pp_workgroup_out = NULL;
3314 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3316 /* Go looking for workgroups by broadcasting on the local network */
3318 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3319 &ip_list, &count);
3320 if (!NT_STATUS_IS_OK(status)) {
3321 DEBUG(99, ("No master browsers responded: %s\n",
3322 nt_errstr(status)));
3323 return False;
3326 for (i = 0; i < count; i++) {
3327 char addr[INET6_ADDRSTRLEN];
3328 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3329 DEBUG(99, ("Found master browser %s\n", addr));
3331 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3332 user_info, pp_workgroup_out);
3333 if (cli)
3334 return(cli);
3337 return NULL;