s3:libsmb: remove unused cli->is_samba
[Samba.git] / source3 / libsmb / cliconnect.c
blobd4391553e9ac41357ab045a829899aefd34ef8fa
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "popt_common.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "../libcli/auth/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
31 #include "krb5_env.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
35 #include "read_smb.h"
37 static const struct {
38 int prot;
39 const char name[24];
40 } prots[10] = {
41 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
42 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
43 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
44 {PROTOCOL_LANMAN1, "LANMAN1.0"},
45 {PROTOCOL_LANMAN2, "LM1.2X002"},
46 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
47 {PROTOCOL_LANMAN2, "LANMAN2.1"},
48 {PROTOCOL_LANMAN2, "Samba"},
49 {PROTOCOL_NT1, "NT LANMAN 1.0"},
50 {PROTOCOL_NT1, "NT LM 0.12"},
53 #define STAR_SMBSERVER "*SMBSERVER"
55 /********************************************************
56 Utility function to ensure we always return at least
57 a valid char * pointer to an empty string for the
58 cli->server_os, cli->server_type and cli->server_domain
59 strings.
60 *******************************************************/
62 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
63 char *inbuf,
64 char **dest,
65 uint8_t *src,
66 size_t srclen,
67 ssize_t *destlen)
69 *destlen = clistr_pull_talloc(mem_ctx,
70 inbuf,
71 SVAL(inbuf, smb_flg2),
72 dest,
73 (char *)src,
74 srclen,
75 STR_TERMINATE);
76 if (*destlen == -1) {
77 return NT_STATUS_NO_MEMORY;
80 if (*dest == NULL) {
81 *dest = talloc_strdup(mem_ctx, "");
82 if (*dest == NULL) {
83 return NT_STATUS_NO_MEMORY;
86 return NT_STATUS_OK;
89 /**
90 * Set the user session key for a connection
91 * @param cli The cli structure to add it too
92 * @param session_key The session key used. (A copy of this is taken for the cli struct)
96 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
98 cli->user_session_key = data_blob(session_key.data, session_key.length);
101 /****************************************************************************
102 Do an old lanman2 style session setup.
103 ****************************************************************************/
105 struct cli_session_setup_lanman2_state {
106 struct cli_state *cli;
107 uint16_t vwv[10];
108 const char *user;
111 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
113 static struct tevent_req *cli_session_setup_lanman2_send(
114 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
115 struct cli_state *cli, const char *user,
116 const char *pass, size_t passlen,
117 const char *workgroup)
119 struct tevent_req *req, *subreq;
120 struct cli_session_setup_lanman2_state *state;
121 DATA_BLOB lm_response = data_blob_null;
122 uint16_t *vwv;
123 uint8_t *bytes;
124 char *tmp;
125 uint16_t sec_mode = cli_state_security_mode(cli);
127 req = tevent_req_create(mem_ctx, &state,
128 struct cli_session_setup_lanman2_state);
129 if (req == NULL) {
130 return NULL;
132 state->cli = cli;
133 state->user = user;
134 vwv = state->vwv;
137 * LANMAN servers predate NT status codes and Unicode and
138 * ignore those smb flags so we must disable the corresponding
139 * default capabilities that would otherwise cause the Unicode
140 * and NT Status flags to be set (and even returned by the
141 * server)
144 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
147 * if in share level security then don't send a password now
149 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
150 passlen = 0;
153 if (passlen > 0
154 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
155 && passlen != 24) {
157 * Encrypted mode needed, and non encrypted password
158 * supplied.
160 lm_response = data_blob(NULL, 24);
161 if (tevent_req_nomem(lm_response.data, req)) {
162 return tevent_req_post(req, ev);
165 if (!SMBencrypt(pass, cli->secblob.data,
166 (uint8_t *)lm_response.data)) {
167 DEBUG(1, ("Password is > 14 chars in length, and is "
168 "therefore incompatible with Lanman "
169 "authentication\n"));
170 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
171 return tevent_req_post(req, ev);
173 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
174 && passlen == 24) {
176 * Encrypted mode needed, and encrypted password
177 * supplied.
179 lm_response = data_blob(pass, passlen);
180 if (tevent_req_nomem(lm_response.data, req)) {
181 return tevent_req_post(req, ev);
183 } else if (passlen > 0) {
184 uint8_t *buf;
185 size_t converted_size;
187 * Plaintext mode needed, assume plaintext supplied.
189 buf = talloc_array(talloc_tos(), uint8_t, 0);
190 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
191 &converted_size);
192 if (tevent_req_nomem(buf, req)) {
193 return tevent_req_post(req, ev);
195 lm_response = data_blob(pass, passlen);
196 TALLOC_FREE(buf);
197 if (tevent_req_nomem(lm_response.data, req)) {
198 return tevent_req_post(req, ev);
202 SCVAL(vwv+0, 0, 0xff);
203 SCVAL(vwv+0, 1, 0);
204 SSVAL(vwv+1, 0, 0);
205 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
206 SSVAL(vwv+3, 0, 2);
207 SSVAL(vwv+4, 0, 1);
208 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
209 SSVAL(vwv+7, 0, lm_response.length);
211 bytes = talloc_array(state, uint8_t, lm_response.length);
212 if (tevent_req_nomem(bytes, req)) {
213 return tevent_req_post(req, ev);
215 if (lm_response.length != 0) {
216 memcpy(bytes, lm_response.data, lm_response.length);
218 data_blob_free(&lm_response);
220 tmp = talloc_strdup_upper(talloc_tos(), user);
221 if (tevent_req_nomem(tmp, req)) {
222 return tevent_req_post(req, ev);
224 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
225 NULL);
226 TALLOC_FREE(tmp);
228 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
229 if (tevent_req_nomem(tmp, req)) {
230 return tevent_req_post(req, ev);
232 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
233 NULL);
234 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
235 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
237 if (tevent_req_nomem(bytes, req)) {
238 return tevent_req_post(req, ev);
241 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
242 talloc_get_size(bytes), bytes);
243 if (tevent_req_nomem(subreq, req)) {
244 return tevent_req_post(req, ev);
246 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
247 return req;
250 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
252 struct tevent_req *req = tevent_req_callback_data(
253 subreq, struct tevent_req);
254 struct cli_session_setup_lanman2_state *state = tevent_req_data(
255 req, struct cli_session_setup_lanman2_state);
256 struct cli_state *cli = state->cli;
257 uint32_t num_bytes;
258 uint8_t *in;
259 char *inbuf;
260 uint8_t *bytes;
261 uint8_t *p;
262 NTSTATUS status;
263 ssize_t ret;
264 uint8_t wct;
265 uint16_t *vwv;
267 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
268 &num_bytes, &bytes);
269 TALLOC_FREE(subreq);
270 if (!NT_STATUS_IS_OK(status)) {
271 tevent_req_nterror(req, status);
272 return;
275 inbuf = (char *)in;
276 p = bytes;
278 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
279 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
281 status = smb_bytes_talloc_string(cli,
282 inbuf,
283 &cli->server_os,
285 bytes+num_bytes-p,
286 &ret);
288 if (!NT_STATUS_IS_OK(status)) {
289 tevent_req_nterror(req, status);
290 return;
292 p += ret;
294 status = smb_bytes_talloc_string(cli,
295 inbuf,
296 &cli->server_type,
298 bytes+num_bytes-p,
299 &ret);
301 if (!NT_STATUS_IS_OK(status)) {
302 tevent_req_nterror(req, status);
303 return;
305 p += ret;
307 status = smb_bytes_talloc_string(cli,
308 inbuf,
309 &cli->server_domain,
311 bytes+num_bytes-p,
312 &ret);
314 if (!NT_STATUS_IS_OK(status)) {
315 tevent_req_nterror(req, status);
316 return;
318 p += ret;
320 status = cli_set_username(cli, state->user);
321 if (tevent_req_nterror(req, status)) {
322 return;
324 tevent_req_done(req);
327 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
329 return tevent_req_simple_recv_ntstatus(req);
332 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
333 const char *pass, size_t passlen,
334 const char *workgroup)
336 TALLOC_CTX *frame = talloc_stackframe();
337 struct event_context *ev;
338 struct tevent_req *req;
339 NTSTATUS status = NT_STATUS_NO_MEMORY;
341 if (cli_has_async_calls(cli)) {
343 * Can't use sync call while an async call is in flight
345 status = NT_STATUS_INVALID_PARAMETER;
346 goto fail;
348 ev = event_context_init(frame);
349 if (ev == NULL) {
350 goto fail;
352 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
353 workgroup);
354 if (req == NULL) {
355 goto fail;
357 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
358 goto fail;
360 status = cli_session_setup_lanman2_recv(req);
361 fail:
362 TALLOC_FREE(frame);
363 return status;
366 /****************************************************************************
367 Work out suitable capabilities to offer the server.
368 ****************************************************************************/
370 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
372 uint32 capabilities = CAP_NT_SMBS;
374 if (!cli->force_dos_errors)
375 capabilities |= CAP_STATUS32;
377 if (cli->use_level_II_oplocks)
378 capabilities |= CAP_LEVEL_II_OPLOCKS;
380 capabilities |= (cli_state_capabilities(cli) & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
381 return capabilities;
384 /****************************************************************************
385 Do a NT1 guest session setup.
386 ****************************************************************************/
388 struct cli_session_setup_guest_state {
389 struct cli_state *cli;
390 uint16_t vwv[13];
391 struct iovec bytes;
394 static void cli_session_setup_guest_done(struct tevent_req *subreq);
396 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
397 struct event_context *ev,
398 struct cli_state *cli,
399 struct tevent_req **psmbreq)
401 struct tevent_req *req, *subreq;
402 struct cli_session_setup_guest_state *state;
403 uint16_t *vwv;
404 uint8_t *bytes;
406 req = tevent_req_create(mem_ctx, &state,
407 struct cli_session_setup_guest_state);
408 if (req == NULL) {
409 return NULL;
411 state->cli = cli;
412 vwv = state->vwv;
414 SCVAL(vwv+0, 0, 0xFF);
415 SCVAL(vwv+0, 1, 0);
416 SSVAL(vwv+1, 0, 0);
417 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
418 SSVAL(vwv+3, 0, 2);
419 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
420 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
421 SSVAL(vwv+7, 0, 0);
422 SSVAL(vwv+8, 0, 0);
423 SSVAL(vwv+9, 0, 0);
424 SSVAL(vwv+10, 0, 0);
425 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
427 bytes = talloc_array(state, uint8_t, 0);
429 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
430 NULL);
431 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
432 NULL);
433 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
434 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
436 if (bytes == NULL) {
437 TALLOC_FREE(req);
438 return NULL;
441 state->bytes.iov_base = (void *)bytes;
442 state->bytes.iov_len = talloc_get_size(bytes);
444 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
445 1, &state->bytes);
446 if (subreq == NULL) {
447 TALLOC_FREE(req);
448 return NULL;
450 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
451 *psmbreq = subreq;
452 return req;
455 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
456 struct event_context *ev,
457 struct cli_state *cli)
459 struct tevent_req *req, *subreq;
460 NTSTATUS status;
462 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
463 if (req == NULL) {
464 return NULL;
467 status = cli_smb_req_send(subreq);
468 if (NT_STATUS_IS_OK(status)) {
469 tevent_req_nterror(req, status);
470 return tevent_req_post(req, ev);
472 return req;
475 static void cli_session_setup_guest_done(struct tevent_req *subreq)
477 struct tevent_req *req = tevent_req_callback_data(
478 subreq, struct tevent_req);
479 struct cli_session_setup_guest_state *state = tevent_req_data(
480 req, struct cli_session_setup_guest_state);
481 struct cli_state *cli = state->cli;
482 uint32_t num_bytes;
483 uint8_t *in;
484 char *inbuf;
485 uint8_t *bytes;
486 uint8_t *p;
487 NTSTATUS status;
488 ssize_t ret;
489 uint8_t wct;
490 uint16_t *vwv;
492 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
493 &num_bytes, &bytes);
494 TALLOC_FREE(subreq);
495 if (!NT_STATUS_IS_OK(status)) {
496 tevent_req_nterror(req, status);
497 return;
500 inbuf = (char *)in;
501 p = bytes;
503 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
504 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
506 status = smb_bytes_talloc_string(cli,
507 inbuf,
508 &cli->server_os,
510 bytes+num_bytes-p,
511 &ret);
513 if (!NT_STATUS_IS_OK(status)) {
514 tevent_req_nterror(req, status);
515 return;
517 p += ret;
519 status = smb_bytes_talloc_string(cli,
520 inbuf,
521 &cli->server_type,
523 bytes+num_bytes-p,
524 &ret);
526 if (!NT_STATUS_IS_OK(status)) {
527 tevent_req_nterror(req, status);
528 return;
530 p += ret;
532 status = smb_bytes_talloc_string(cli,
533 inbuf,
534 &cli->server_domain,
536 bytes+num_bytes-p,
537 &ret);
539 if (!NT_STATUS_IS_OK(status)) {
540 tevent_req_nterror(req, status);
541 return;
543 p += ret;
545 status = cli_set_username(cli, "");
546 if (!NT_STATUS_IS_OK(status)) {
547 tevent_req_nterror(req, status);
548 return;
550 tevent_req_done(req);
553 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
555 return tevent_req_simple_recv_ntstatus(req);
558 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
560 TALLOC_CTX *frame = talloc_stackframe();
561 struct event_context *ev;
562 struct tevent_req *req;
563 NTSTATUS status = NT_STATUS_OK;
565 if (cli_has_async_calls(cli)) {
567 * Can't use sync call while an async call is in flight
569 status = NT_STATUS_INVALID_PARAMETER;
570 goto fail;
573 ev = event_context_init(frame);
574 if (ev == NULL) {
575 status = NT_STATUS_NO_MEMORY;
576 goto fail;
579 req = cli_session_setup_guest_send(frame, ev, cli);
580 if (req == NULL) {
581 status = NT_STATUS_NO_MEMORY;
582 goto fail;
585 if (!tevent_req_poll(req, ev)) {
586 status = map_nt_error_from_unix(errno);
587 goto fail;
590 status = cli_session_setup_guest_recv(req);
591 fail:
592 TALLOC_FREE(frame);
593 return status;
596 /****************************************************************************
597 Do a NT1 plaintext session setup.
598 ****************************************************************************/
600 struct cli_session_setup_plain_state {
601 struct cli_state *cli;
602 uint16_t vwv[13];
603 const char *user;
606 static void cli_session_setup_plain_done(struct tevent_req *subreq);
608 static struct tevent_req *cli_session_setup_plain_send(
609 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
610 struct cli_state *cli,
611 const char *user, const char *pass, const char *workgroup)
613 struct tevent_req *req, *subreq;
614 struct cli_session_setup_plain_state *state;
615 uint16_t *vwv;
616 uint8_t *bytes;
617 size_t passlen;
618 char *version;
620 req = tevent_req_create(mem_ctx, &state,
621 struct cli_session_setup_plain_state);
622 if (req == NULL) {
623 return NULL;
625 state->cli = cli;
626 state->user = user;
627 vwv = state->vwv;
629 SCVAL(vwv+0, 0, 0xff);
630 SCVAL(vwv+0, 1, 0);
631 SSVAL(vwv+1, 0, 0);
632 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
633 SSVAL(vwv+3, 0, 2);
634 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
635 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
636 SSVAL(vwv+7, 0, 0);
637 SSVAL(vwv+8, 0, 0);
638 SSVAL(vwv+9, 0, 0);
639 SSVAL(vwv+10, 0, 0);
640 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
642 bytes = talloc_array(state, uint8_t, 0);
643 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
644 &passlen);
645 if (tevent_req_nomem(bytes, req)) {
646 return tevent_req_post(req, ev);
648 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
650 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
651 user, strlen(user)+1, NULL);
652 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
653 workgroup, strlen(workgroup)+1, NULL);
654 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
655 "Unix", 5, NULL);
657 version = talloc_asprintf(talloc_tos(), "Samba %s",
658 samba_version_string());
659 if (tevent_req_nomem(version, req)){
660 return tevent_req_post(req, ev);
662 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
663 version, strlen(version)+1, NULL);
664 TALLOC_FREE(version);
666 if (tevent_req_nomem(bytes, req)) {
667 return tevent_req_post(req, ev);
670 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
671 talloc_get_size(bytes), bytes);
672 if (tevent_req_nomem(subreq, req)) {
673 return tevent_req_post(req, ev);
675 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
676 return req;
679 static void cli_session_setup_plain_done(struct tevent_req *subreq)
681 struct tevent_req *req = tevent_req_callback_data(
682 subreq, struct tevent_req);
683 struct cli_session_setup_plain_state *state = tevent_req_data(
684 req, struct cli_session_setup_plain_state);
685 struct cli_state *cli = state->cli;
686 uint32_t num_bytes;
687 uint8_t *in;
688 char *inbuf;
689 uint8_t *bytes;
690 uint8_t *p;
691 NTSTATUS status;
692 ssize_t ret;
693 uint8_t wct;
694 uint16_t *vwv;
696 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
697 &num_bytes, &bytes);
698 TALLOC_FREE(subreq);
699 if (tevent_req_nterror(req, status)) {
700 return;
703 inbuf = (char *)in;
704 p = bytes;
706 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
707 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
709 status = smb_bytes_talloc_string(cli,
710 inbuf,
711 &cli->server_os,
713 bytes+num_bytes-p,
714 &ret);
716 if (!NT_STATUS_IS_OK(status)) {
717 tevent_req_nterror(req, status);
718 return;
720 p += ret;
722 status = smb_bytes_talloc_string(cli,
723 inbuf,
724 &cli->server_type,
726 bytes+num_bytes-p,
727 &ret);
729 if (!NT_STATUS_IS_OK(status)) {
730 tevent_req_nterror(req, status);
731 return;
733 p += ret;
735 status = smb_bytes_talloc_string(cli,
736 inbuf,
737 &cli->server_domain,
739 bytes+num_bytes-p,
740 &ret);
742 if (!NT_STATUS_IS_OK(status)) {
743 tevent_req_nterror(req, status);
744 return;
746 p += ret;
748 status = cli_set_username(cli, state->user);
749 if (tevent_req_nterror(req, status)) {
750 return;
753 tevent_req_done(req);
756 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
758 return tevent_req_simple_recv_ntstatus(req);
761 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
762 const char *user, const char *pass,
763 const char *workgroup)
765 TALLOC_CTX *frame = talloc_stackframe();
766 struct event_context *ev;
767 struct tevent_req *req;
768 NTSTATUS status = NT_STATUS_NO_MEMORY;
770 if (cli_has_async_calls(cli)) {
772 * Can't use sync call while an async call is in flight
774 status = NT_STATUS_INVALID_PARAMETER;
775 goto fail;
777 ev = event_context_init(frame);
778 if (ev == NULL) {
779 goto fail;
781 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
782 workgroup);
783 if (req == NULL) {
784 goto fail;
786 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
787 goto fail;
789 status = cli_session_setup_plain_recv(req);
790 fail:
791 TALLOC_FREE(frame);
792 return status;
795 /****************************************************************************
796 do a NT1 NTLM/LM encrypted session setup - for when extended security
797 is not negotiated.
798 @param cli client state to create do session setup on
799 @param user username
800 @param pass *either* cleartext password (passlen !=24) or LM response.
801 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
802 @param workgroup The user's domain.
803 ****************************************************************************/
805 struct cli_session_setup_nt1_state {
806 struct cli_state *cli;
807 uint16_t vwv[13];
808 DATA_BLOB response;
809 DATA_BLOB session_key;
810 const char *user;
813 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
815 static struct tevent_req *cli_session_setup_nt1_send(
816 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
817 struct cli_state *cli, const char *user,
818 const char *pass, size_t passlen,
819 const char *ntpass, size_t ntpasslen,
820 const char *workgroup)
822 struct tevent_req *req, *subreq;
823 struct cli_session_setup_nt1_state *state;
824 DATA_BLOB lm_response = data_blob_null;
825 DATA_BLOB nt_response = data_blob_null;
826 DATA_BLOB session_key = data_blob_null;
827 uint16_t *vwv;
828 uint8_t *bytes;
829 char *workgroup_upper;
831 req = tevent_req_create(mem_ctx, &state,
832 struct cli_session_setup_nt1_state);
833 if (req == NULL) {
834 return NULL;
836 state->cli = cli;
837 state->user = user;
838 vwv = state->vwv;
840 if (passlen == 0) {
841 /* do nothing - guest login */
842 } else if (passlen != 24) {
843 if (lp_client_ntlmv2_auth()) {
844 DATA_BLOB server_chal;
845 DATA_BLOB names_blob;
847 server_chal = data_blob(cli->secblob.data,
848 MIN(cli->secblob.length, 8));
849 if (tevent_req_nomem(server_chal.data, req)) {
850 return tevent_req_post(req, ev);
854 * note that the 'workgroup' here is a best
855 * guess - we don't know the server's domain
856 * at this point. Windows clients also don't
857 * use hostname...
859 names_blob = NTLMv2_generate_names_blob(
860 NULL, NULL, workgroup);
862 if (tevent_req_nomem(names_blob.data, req)) {
863 return tevent_req_post(req, ev);
866 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
867 &server_chal, &names_blob,
868 &lm_response, &nt_response,
869 NULL, &session_key)) {
870 data_blob_free(&names_blob);
871 data_blob_free(&server_chal);
872 tevent_req_nterror(
873 req, NT_STATUS_ACCESS_DENIED);
874 return tevent_req_post(req, ev);
876 data_blob_free(&names_blob);
877 data_blob_free(&server_chal);
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->secblob.data,
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,cli->secblob.data,
903 lm_response.data)) {
905 * Oops, the LM response is
906 * invalid, just put the NT
907 * response there instead
909 data_blob_free(&lm_response);
910 lm_response = data_blob(
911 nt_response.data,
912 nt_response.length);
914 } else {
916 * LM disabled, place NT# in LM field
917 * instead
919 lm_response = data_blob(
920 nt_response.data, nt_response.length);
923 if (tevent_req_nomem(lm_response.data, req)) {
924 return tevent_req_post(req, ev);
927 session_key = data_blob(NULL, 16);
928 if (tevent_req_nomem(session_key.data, req)) {
929 return tevent_req_post(req, ev);
931 #ifdef LANMAN_ONLY
932 E_deshash(pass, session_key.data);
933 memset(&session_key.data[8], '\0', 8);
934 #else
935 SMBsesskeygen_ntv1(nt_hash, session_key.data);
936 #endif
938 } else {
939 /* pre-encrypted password supplied. Only used for
940 security=server, can't do
941 signing because we don't have original key */
943 lm_response = data_blob(pass, passlen);
944 if (tevent_req_nomem(lm_response.data, req)) {
945 return tevent_req_post(req, ev);
948 nt_response = data_blob(ntpass, ntpasslen);
949 if (tevent_req_nomem(nt_response.data, req)) {
950 return tevent_req_post(req, ev);
954 #ifdef LANMAN_ONLY
955 state->response = data_blob_talloc(
956 state, lm_response.data, lm_response.length);
957 #else
958 state->response = data_blob_talloc(
959 state, nt_response.data, nt_response.length);
960 #endif
961 if (tevent_req_nomem(state->response.data, req)) {
962 return tevent_req_post(req, ev);
965 if (session_key.data) {
966 state->session_key = data_blob_talloc(
967 state, session_key.data, session_key.length);
968 if (tevent_req_nomem(state->session_key.data, req)) {
969 return tevent_req_post(req, ev);
972 data_blob_free(&session_key);
974 SCVAL(vwv+0, 0, 0xff);
975 SCVAL(vwv+0, 1, 0);
976 SSVAL(vwv+1, 0, 0);
977 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
978 SSVAL(vwv+3, 0, 2);
979 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
980 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
981 SSVAL(vwv+7, 0, lm_response.length);
982 SSVAL(vwv+8, 0, nt_response.length);
983 SSVAL(vwv+9, 0, 0);
984 SSVAL(vwv+10, 0, 0);
985 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
987 bytes = talloc_array(state, uint8_t,
988 lm_response.length + nt_response.length);
989 if (tevent_req_nomem(bytes, req)) {
990 return tevent_req_post(req, ev);
992 if (lm_response.length != 0) {
993 memcpy(bytes, lm_response.data, lm_response.length);
995 if (nt_response.length != 0) {
996 memcpy(bytes + lm_response.length,
997 nt_response.data, nt_response.length);
999 data_blob_free(&lm_response);
1000 data_blob_free(&nt_response);
1002 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1003 user, strlen(user)+1, NULL);
1006 * Upper case here might help some NTLMv2 implementations
1008 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1009 if (tevent_req_nomem(workgroup_upper, req)) {
1010 return tevent_req_post(req, ev);
1012 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1013 workgroup_upper, strlen(workgroup_upper)+1,
1014 NULL);
1015 TALLOC_FREE(workgroup_upper);
1017 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1018 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1019 if (tevent_req_nomem(bytes, req)) {
1020 return tevent_req_post(req, ev);
1023 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1024 talloc_get_size(bytes), bytes);
1025 if (tevent_req_nomem(subreq, req)) {
1026 return tevent_req_post(req, ev);
1028 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1029 return req;
1032 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1034 struct tevent_req *req = tevent_req_callback_data(
1035 subreq, struct tevent_req);
1036 struct cli_session_setup_nt1_state *state = tevent_req_data(
1037 req, struct cli_session_setup_nt1_state);
1038 struct cli_state *cli = state->cli;
1039 uint32_t num_bytes;
1040 uint8_t *in;
1041 char *inbuf;
1042 uint8_t *bytes;
1043 uint8_t *p;
1044 NTSTATUS status;
1045 ssize_t ret;
1046 uint8_t wct;
1047 uint16_t *vwv;
1049 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1050 &num_bytes, &bytes);
1051 TALLOC_FREE(subreq);
1052 if (!NT_STATUS_IS_OK(status)) {
1053 tevent_req_nterror(req, status);
1054 return;
1057 inbuf = (char *)in;
1058 p = bytes;
1060 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
1061 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1063 status = smb_bytes_talloc_string(cli,
1064 inbuf,
1065 &cli->server_os,
1067 bytes+num_bytes-p,
1068 &ret);
1069 if (!NT_STATUS_IS_OK(status)) {
1070 tevent_req_nterror(req, status);
1071 return;
1073 p += ret;
1075 status = smb_bytes_talloc_string(cli,
1076 inbuf,
1077 &cli->server_type,
1079 bytes+num_bytes-p,
1080 &ret);
1081 if (!NT_STATUS_IS_OK(status)) {
1082 tevent_req_nterror(req, status);
1083 return;
1085 p += ret;
1087 status = smb_bytes_talloc_string(cli,
1088 inbuf,
1089 &cli->server_domain,
1091 bytes+num_bytes-p,
1092 &ret);
1093 if (!NT_STATUS_IS_OK(status)) {
1094 tevent_req_nterror(req, status);
1095 return;
1097 p += ret;
1099 status = cli_set_username(cli, state->user);
1100 if (tevent_req_nterror(req, status)) {
1101 return;
1103 if (cli_simple_set_signing(cli, state->session_key, state->response)
1104 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1105 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1106 return;
1108 if (state->session_key.data) {
1109 /* Have plaintext orginal */
1110 cli_set_session_key(cli, state->session_key);
1112 tevent_req_done(req);
1115 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1117 return tevent_req_simple_recv_ntstatus(req);
1120 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1121 const char *pass, size_t passlen,
1122 const char *ntpass, size_t ntpasslen,
1123 const char *workgroup)
1125 TALLOC_CTX *frame = talloc_stackframe();
1126 struct event_context *ev;
1127 struct tevent_req *req;
1128 NTSTATUS status = NT_STATUS_NO_MEMORY;
1130 if (cli_has_async_calls(cli)) {
1132 * Can't use sync call while an async call is in flight
1134 status = NT_STATUS_INVALID_PARAMETER;
1135 goto fail;
1137 ev = event_context_init(frame);
1138 if (ev == NULL) {
1139 goto fail;
1141 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1142 ntpass, ntpasslen, workgroup);
1143 if (req == NULL) {
1144 goto fail;
1146 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1147 goto fail;
1149 status = cli_session_setup_nt1_recv(req);
1150 fail:
1151 TALLOC_FREE(frame);
1152 return status;
1155 /* The following is calculated from :
1156 * (smb_size-4) = 35
1157 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1158 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1159 * end of packet.
1162 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1164 struct cli_sesssetup_blob_state {
1165 struct tevent_context *ev;
1166 struct cli_state *cli;
1167 DATA_BLOB blob;
1168 uint16_t max_blob_size;
1169 uint16_t vwv[12];
1170 uint8_t *buf;
1172 NTSTATUS status;
1173 char *inbuf;
1174 DATA_BLOB ret_blob;
1177 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1178 struct tevent_req **psubreq);
1179 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1181 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1182 struct tevent_context *ev,
1183 struct cli_state *cli,
1184 DATA_BLOB blob)
1186 struct tevent_req *req, *subreq;
1187 struct cli_sesssetup_blob_state *state;
1188 uint32_t usable_space;
1190 req = tevent_req_create(mem_ctx, &state,
1191 struct cli_sesssetup_blob_state);
1192 if (req == NULL) {
1193 return NULL;
1195 state->ev = ev;
1196 state->blob = blob;
1197 state->cli = cli;
1199 usable_space = cli_state_available_size(cli,
1200 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1202 if (usable_space == 0) {
1203 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1204 "(not possible to send %u bytes)\n",
1205 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1206 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1207 return tevent_req_post(req, ev);
1209 state->max_blob_size = MIN(usable_space, 0xFFFF);
1211 if (!cli_sesssetup_blob_next(state, &subreq)) {
1212 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1213 return tevent_req_post(req, ev);
1215 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1216 return req;
1219 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1220 struct tevent_req **psubreq)
1222 struct tevent_req *subreq;
1223 uint16_t thistime;
1225 SCVAL(state->vwv+0, 0, 0xFF);
1226 SCVAL(state->vwv+0, 1, 0);
1227 SSVAL(state->vwv+1, 0, 0);
1228 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1229 SSVAL(state->vwv+3, 0, 2);
1230 SSVAL(state->vwv+4, 0, 1);
1231 SIVAL(state->vwv+5, 0, 0);
1233 thistime = MIN(state->blob.length, state->max_blob_size);
1234 SSVAL(state->vwv+7, 0, thistime);
1236 SSVAL(state->vwv+8, 0, 0);
1237 SSVAL(state->vwv+9, 0, 0);
1238 SIVAL(state->vwv+10, 0,
1239 cli_session_setup_capabilities(state->cli)
1240 | 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 blob;
1779 const char *p = NULL;
1780 char *account = NULL;
1781 NTSTATUS status;
1783 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1785 /* the server might not even do spnego */
1786 if (cli->secblob.length <= 16) {
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 /* there is 16 bytes of GUID before the real spnego packet starts */
1796 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1798 /* The server sent us the first part of the SPNEGO exchange in the
1799 * negprot reply. It is WRONG to depend on the principal sent in the
1800 * negprot reply, but right now we do it. If we don't receive one,
1801 * we try to best guess, then fall back to NTLM. */
1802 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1803 OIDs[0] == NULL) {
1804 data_blob_free(&blob);
1805 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1807 data_blob_free(&blob);
1809 /* make sure the server understands kerberos */
1810 for (i=0;OIDs[i];i++) {
1811 if (i == 0)
1812 DEBUG(3,("got OID=%s\n", OIDs[i]));
1813 else
1814 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1815 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1816 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1817 cli->got_kerberos_mechanism = True;
1819 talloc_free(OIDs[i]);
1822 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1824 status = cli_set_username(cli, user);
1825 if (!NT_STATUS_IS_OK(status)) {
1826 TALLOC_FREE(principal);
1827 return ADS_ERROR_NT(status);
1830 #ifdef HAVE_KRB5
1831 /* If password is set we reauthenticate to kerberos server
1832 * and do not store results */
1834 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1835 ADS_STATUS rc;
1836 const char *remote_name = cli_state_remote_name(cli);
1838 if (pass && *pass) {
1839 int ret;
1841 use_in_memory_ccache();
1842 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1844 if (ret){
1845 TALLOC_FREE(principal);
1846 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1847 if (cli->fallback_after_kerberos)
1848 goto ntlmssp;
1849 return ADS_ERROR_KRB5(ret);
1853 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1855 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1856 TALLOC_FREE(principal);
1859 if (principal == NULL &&
1860 !is_ipaddress(remote_name) &&
1861 !strequal(STAR_SMBSERVER,
1862 remote_name)) {
1863 char *realm = NULL;
1864 char *host = NULL;
1865 DEBUG(3,("cli_session_setup_spnego: using target "
1866 "hostname not SPNEGO principal\n"));
1868 host = strchr_m(remote_name, '.');
1869 if (dest_realm) {
1870 realm = SMB_STRDUP(dest_realm);
1871 if (!realm) {
1872 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1874 strupper_m(realm);
1875 } else {
1876 if (host) {
1877 /* DNS name. */
1878 realm = kerberos_get_realm_from_hostname(remote_name);
1879 } else {
1880 /* NetBIOS name - use our realm. */
1881 realm = kerberos_get_default_realm_from_ccache();
1885 if (realm == NULL || *realm == '\0') {
1886 realm = SMB_STRDUP(lp_realm());
1887 if (!realm) {
1888 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1890 strupper_m(realm);
1891 DEBUG(3,("cli_session_setup_spnego: cannot "
1892 "get realm from dest_realm %s, "
1893 "desthost %s. Using default "
1894 "smb.conf realm %s\n",
1895 dest_realm ? dest_realm : "<null>",
1896 remote_name,
1897 realm));
1900 principal = talloc_asprintf(talloc_tos(),
1901 "cifs/%s@%s",
1902 remote_name,
1903 realm);
1904 if (!principal) {
1905 SAFE_FREE(realm);
1906 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1908 DEBUG(3,("cli_session_setup_spnego: guessed "
1909 "server principal=%s\n",
1910 principal ? principal : "<null>"));
1912 SAFE_FREE(realm);
1915 if (principal) {
1916 rc = cli_session_setup_kerberos(cli, principal);
1917 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1918 TALLOC_FREE(principal);
1919 return rc;
1923 #endif
1925 TALLOC_FREE(principal);
1927 ntlmssp:
1929 account = talloc_strdup(talloc_tos(), user);
1930 if (!account) {
1931 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1934 /* when falling back to ntlmssp while authenticating with a machine
1935 * account strip off the realm - gd */
1937 if ((p = strchr_m(user, '@')) != NULL) {
1938 account[PTR_DIFF(p,user)] = '\0';
1941 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1944 /****************************************************************************
1945 Send a session setup. The username and workgroup is in UNIX character
1946 format and must be converted to DOS codepage format before sending. If the
1947 password is in plaintext, the same should be done.
1948 ****************************************************************************/
1950 NTSTATUS cli_session_setup(struct cli_state *cli,
1951 const char *user,
1952 const char *pass, int passlen,
1953 const char *ntpass, int ntpasslen,
1954 const char *workgroup)
1956 char *p;
1957 char *user2;
1958 uint16_t sec_mode = cli_state_security_mode(cli);
1960 if (user) {
1961 user2 = talloc_strdup(talloc_tos(), user);
1962 } else {
1963 user2 = talloc_strdup(talloc_tos(), "");
1965 if (user2 == NULL) {
1966 return NT_STATUS_NO_MEMORY;
1969 if (!workgroup) {
1970 workgroup = "";
1973 /* allow for workgroups as part of the username */
1974 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1975 (p=strchr_m(user2,*lp_winbind_separator()))) {
1976 *p = 0;
1977 user = p+1;
1978 strupper_m(user2);
1979 workgroup = user2;
1982 if (cli_state_protocol(cli) < PROTOCOL_LANMAN1) {
1984 * Ensure cli->server_domain,
1985 * cli->server_os and cli->server_type
1986 * are valid pointers.
1988 cli->server_domain = talloc_strdup(cli, "");
1989 cli->server_os = talloc_strdup(cli, "");
1990 cli->server_type = talloc_strdup(cli, "");
1991 if (cli->server_domain == NULL ||
1992 cli->server_os == NULL ||
1993 cli->server_type == NULL) {
1994 return NT_STATUS_NO_MEMORY;
1996 return NT_STATUS_OK;
1999 /* now work out what sort of session setup we are going to
2000 do. I have split this into separate functions to make the
2001 flow a bit easier to understand (tridge) */
2003 /* if its an older server then we have to use the older request format */
2005 if (cli_state_protocol(cli) < PROTOCOL_NT1) {
2006 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2007 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2008 " or 'client ntlmv2 auth = yes'\n"));
2009 return NT_STATUS_ACCESS_DENIED;
2012 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2013 !lp_client_plaintext_auth() && (*pass)) {
2014 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2015 " or 'client ntlmv2 auth = yes'\n"));
2016 return NT_STATUS_ACCESS_DENIED;
2019 return cli_session_setup_lanman2(cli, user, pass, passlen,
2020 workgroup);
2023 /* if no user is supplied then we have to do an anonymous connection.
2024 passwords are ignored */
2026 if (!user || !*user)
2027 return cli_session_setup_guest(cli);
2029 /* if the server is share level then send a plaintext null
2030 password at this point. The password is sent in the tree
2031 connect */
2033 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2034 return cli_session_setup_plain(cli, user, "", workgroup);
2036 /* if the server doesn't support encryption then we have to use
2037 plaintext. The second password is ignored */
2039 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2040 if (!lp_client_plaintext_auth() && (*pass)) {
2041 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2042 " or 'client ntlmv2 auth = yes'\n"));
2043 return NT_STATUS_ACCESS_DENIED;
2045 return cli_session_setup_plain(cli, user, pass, workgroup);
2048 /* if the server supports extended security then use SPNEGO */
2050 if (cli_state_capabilities(cli) & CAP_EXTENDED_SECURITY) {
2051 const char *remote_realm = cli_state_remote_realm(cli);
2052 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2053 workgroup,
2054 remote_realm);
2055 if (!ADS_ERR_OK(status)) {
2056 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2057 return ads_ntstatus(status);
2059 } else {
2060 NTSTATUS status;
2062 /* otherwise do a NT1 style session setup */
2063 status = cli_session_setup_nt1(cli, user, pass, passlen,
2064 ntpass, ntpasslen, workgroup);
2065 if (!NT_STATUS_IS_OK(status)) {
2066 DEBUG(3,("cli_session_setup: NT1 session setup "
2067 "failed: %s\n", nt_errstr(status)));
2068 return status;
2072 return NT_STATUS_OK;
2075 /****************************************************************************
2076 Send a uloggoff.
2077 *****************************************************************************/
2079 struct cli_ulogoff_state {
2080 struct cli_state *cli;
2081 uint16_t vwv[3];
2084 static void cli_ulogoff_done(struct tevent_req *subreq);
2086 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2087 struct tevent_context *ev,
2088 struct cli_state *cli)
2090 struct tevent_req *req, *subreq;
2091 struct cli_ulogoff_state *state;
2093 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2094 if (req == NULL) {
2095 return NULL;
2097 state->cli = cli;
2099 SCVAL(state->vwv+0, 0, 0xFF);
2100 SCVAL(state->vwv+1, 0, 0);
2101 SSVAL(state->vwv+2, 0, 0);
2103 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2104 0, NULL);
2105 if (tevent_req_nomem(subreq, req)) {
2106 return tevent_req_post(req, ev);
2108 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2109 return req;
2112 static void cli_ulogoff_done(struct tevent_req *subreq)
2114 struct tevent_req *req = tevent_req_callback_data(
2115 subreq, struct tevent_req);
2116 struct cli_ulogoff_state *state = tevent_req_data(
2117 req, struct cli_ulogoff_state);
2118 NTSTATUS status;
2120 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2121 if (!NT_STATUS_IS_OK(status)) {
2122 tevent_req_nterror(req, status);
2123 return;
2125 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2126 tevent_req_done(req);
2129 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2131 return tevent_req_simple_recv_ntstatus(req);
2134 NTSTATUS cli_ulogoff(struct cli_state *cli)
2136 struct tevent_context *ev;
2137 struct tevent_req *req;
2138 NTSTATUS status = NT_STATUS_NO_MEMORY;
2140 if (cli_has_async_calls(cli)) {
2141 return NT_STATUS_INVALID_PARAMETER;
2143 ev = tevent_context_init(talloc_tos());
2144 if (ev == NULL) {
2145 goto fail;
2147 req = cli_ulogoff_send(ev, ev, cli);
2148 if (req == NULL) {
2149 goto fail;
2151 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2152 goto fail;
2154 status = cli_ulogoff_recv(req);
2155 fail:
2156 TALLOC_FREE(ev);
2157 return status;
2160 /****************************************************************************
2161 Send a tconX.
2162 ****************************************************************************/
2164 struct cli_tcon_andx_state {
2165 struct cli_state *cli;
2166 uint16_t vwv[4];
2167 struct iovec bytes;
2170 static void cli_tcon_andx_done(struct tevent_req *subreq);
2172 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2173 struct event_context *ev,
2174 struct cli_state *cli,
2175 const char *share, const char *dev,
2176 const char *pass, int passlen,
2177 struct tevent_req **psmbreq)
2179 struct tevent_req *req, *subreq;
2180 struct cli_tcon_andx_state *state;
2181 uint8_t p24[24];
2182 uint16_t *vwv;
2183 char *tmp = NULL;
2184 uint8_t *bytes;
2185 uint16_t sec_mode = cli_state_security_mode(cli);
2187 *psmbreq = NULL;
2189 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2190 if (req == NULL) {
2191 return NULL;
2193 state->cli = cli;
2194 vwv = state->vwv;
2196 cli->share = talloc_strdup(cli, share);
2197 if (!cli->share) {
2198 return NULL;
2201 /* in user level security don't send a password now */
2202 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2203 passlen = 1;
2204 pass = "";
2205 } else if (pass == NULL) {
2206 DEBUG(1, ("Server not using user level security and no "
2207 "password supplied.\n"));
2208 goto access_denied;
2211 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2212 *pass && passlen != 24) {
2213 if (!lp_client_lanman_auth()) {
2214 DEBUG(1, ("Server requested LANMAN password "
2215 "(share-level security) but "
2216 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2217 goto access_denied;
2221 * Non-encrypted passwords - convert to DOS codepage before
2222 * encryption.
2224 SMBencrypt(pass, cli->secblob.data, p24);
2225 passlen = 24;
2226 pass = (const char *)p24;
2227 } else {
2228 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2229 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2230 == 0) {
2231 uint8_t *tmp_pass;
2233 if (!lp_client_plaintext_auth() && (*pass)) {
2234 DEBUG(1, ("Server requested plaintext "
2235 "password but "
2236 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2237 goto access_denied;
2241 * Non-encrypted passwords - convert to DOS codepage
2242 * before using.
2244 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2245 if (tevent_req_nomem(tmp_pass, req)) {
2246 return tevent_req_post(req, ev);
2248 tmp_pass = trans2_bytes_push_str(tmp_pass,
2249 false, /* always DOS */
2250 pass,
2251 passlen,
2252 NULL);
2253 if (tevent_req_nomem(tmp_pass, req)) {
2254 return tevent_req_post(req, ev);
2256 pass = (const char *)tmp_pass;
2257 passlen = talloc_get_size(tmp_pass);
2261 SCVAL(vwv+0, 0, 0xFF);
2262 SCVAL(vwv+0, 1, 0);
2263 SSVAL(vwv+1, 0, 0);
2264 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2265 SSVAL(vwv+3, 0, passlen);
2267 if (passlen && pass) {
2268 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2269 } else {
2270 bytes = talloc_array(state, uint8_t, 0);
2274 * Add the sharename
2276 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2277 cli_state_remote_name(cli), share);
2278 if (tmp == NULL) {
2279 TALLOC_FREE(req);
2280 return NULL;
2282 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2283 NULL);
2284 TALLOC_FREE(tmp);
2287 * Add the devicetype
2289 tmp = talloc_strdup_upper(talloc_tos(), dev);
2290 if (tmp == NULL) {
2291 TALLOC_FREE(req);
2292 return NULL;
2294 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2295 TALLOC_FREE(tmp);
2297 if (bytes == NULL) {
2298 TALLOC_FREE(req);
2299 return NULL;
2302 state->bytes.iov_base = (void *)bytes;
2303 state->bytes.iov_len = talloc_get_size(bytes);
2305 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2306 1, &state->bytes);
2307 if (subreq == NULL) {
2308 TALLOC_FREE(req);
2309 return NULL;
2311 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2312 *psmbreq = subreq;
2313 return req;
2315 access_denied:
2316 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2317 return tevent_req_post(req, ev);
2320 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2321 struct event_context *ev,
2322 struct cli_state *cli,
2323 const char *share, const char *dev,
2324 const char *pass, int passlen)
2326 struct tevent_req *req, *subreq;
2327 NTSTATUS status;
2329 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2330 &subreq);
2331 if (req == NULL) {
2332 return NULL;
2334 if (subreq == NULL) {
2335 return req;
2337 status = cli_smb_req_send(subreq);
2338 if (!NT_STATUS_IS_OK(status)) {
2339 tevent_req_nterror(req, status);
2340 return tevent_req_post(req, ev);
2342 return req;
2345 static void cli_tcon_andx_done(struct tevent_req *subreq)
2347 struct tevent_req *req = tevent_req_callback_data(
2348 subreq, struct tevent_req);
2349 struct cli_tcon_andx_state *state = tevent_req_data(
2350 req, struct cli_tcon_andx_state);
2351 struct cli_state *cli = state->cli;
2352 uint8_t *in;
2353 char *inbuf;
2354 uint8_t wct;
2355 uint16_t *vwv;
2356 uint32_t num_bytes;
2357 uint8_t *bytes;
2358 NTSTATUS status;
2360 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2361 &num_bytes, &bytes);
2362 TALLOC_FREE(subreq);
2363 if (!NT_STATUS_IS_OK(status)) {
2364 tevent_req_nterror(req, status);
2365 return;
2368 inbuf = (char *)in;
2370 if (num_bytes) {
2371 if (clistr_pull_talloc(cli,
2372 inbuf,
2373 SVAL(inbuf, smb_flg2),
2374 &cli->dev,
2375 bytes,
2376 num_bytes,
2377 STR_TERMINATE|STR_ASCII) == -1) {
2378 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2379 return;
2381 } else {
2382 cli->dev = talloc_strdup(cli, "");
2383 if (cli->dev == NULL) {
2384 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2385 return;
2389 if ((cli_state_protocol(cli) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2390 /* almost certainly win95 - enable bug fixes */
2391 cli->win95 = True;
2395 * Make sure that we have the optional support 16-bit field. WCT > 2.
2396 * Avoids issues when connecting to Win9x boxes sharing files
2399 cli->dfsroot = false;
2401 if ((wct > 2) && (cli_state_protocol(cli) >= PROTOCOL_LANMAN2)) {
2402 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2405 cli->smb1.tid = SVAL(inbuf,smb_tid);
2406 tevent_req_done(req);
2409 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2411 return tevent_req_simple_recv_ntstatus(req);
2414 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2415 const char *dev, const char *pass, int passlen)
2417 TALLOC_CTX *frame = talloc_stackframe();
2418 struct event_context *ev;
2419 struct tevent_req *req;
2420 NTSTATUS status = NT_STATUS_OK;
2422 if (cli_has_async_calls(cli)) {
2424 * Can't use sync call while an async call is in flight
2426 status = NT_STATUS_INVALID_PARAMETER;
2427 goto fail;
2430 ev = event_context_init(frame);
2431 if (ev == NULL) {
2432 status = NT_STATUS_NO_MEMORY;
2433 goto fail;
2436 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2437 if (req == NULL) {
2438 status = NT_STATUS_NO_MEMORY;
2439 goto fail;
2442 if (!tevent_req_poll(req, ev)) {
2443 status = map_nt_error_from_unix(errno);
2444 goto fail;
2447 status = cli_tcon_andx_recv(req);
2448 fail:
2449 TALLOC_FREE(frame);
2450 return status;
2453 /****************************************************************************
2454 Send a tree disconnect.
2455 ****************************************************************************/
2457 struct cli_tdis_state {
2458 struct cli_state *cli;
2461 static void cli_tdis_done(struct tevent_req *subreq);
2463 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2464 struct tevent_context *ev,
2465 struct cli_state *cli)
2467 struct tevent_req *req, *subreq;
2468 struct cli_tdis_state *state;
2470 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2471 if (req == NULL) {
2472 return NULL;
2474 state->cli = cli;
2476 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2477 if (tevent_req_nomem(subreq, req)) {
2478 return tevent_req_post(req, ev);
2480 tevent_req_set_callback(subreq, cli_tdis_done, req);
2481 return req;
2484 static void cli_tdis_done(struct tevent_req *subreq)
2486 struct tevent_req *req = tevent_req_callback_data(
2487 subreq, struct tevent_req);
2488 struct cli_tdis_state *state = tevent_req_data(
2489 req, struct cli_tdis_state);
2490 NTSTATUS status;
2492 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2493 TALLOC_FREE(subreq);
2494 if (!NT_STATUS_IS_OK(status)) {
2495 tevent_req_nterror(req, status);
2496 return;
2498 state->cli->smb1.tid = UINT16_MAX;
2499 tevent_req_done(req);
2502 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2504 return tevent_req_simple_recv_ntstatus(req);
2507 NTSTATUS cli_tdis(struct cli_state *cli)
2509 struct tevent_context *ev;
2510 struct tevent_req *req;
2511 NTSTATUS status = NT_STATUS_NO_MEMORY;
2513 if (cli_has_async_calls(cli)) {
2514 return NT_STATUS_INVALID_PARAMETER;
2516 ev = tevent_context_init(talloc_tos());
2517 if (ev == NULL) {
2518 goto fail;
2520 req = cli_tdis_send(ev, ev, cli);
2521 if (req == NULL) {
2522 goto fail;
2524 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2525 goto fail;
2527 status = cli_tdis_recv(req);
2528 fail:
2529 TALLOC_FREE(ev);
2530 return status;
2533 /****************************************************************************
2534 Send a negprot command.
2535 ****************************************************************************/
2537 struct cli_negprot_state {
2538 struct cli_state *cli;
2541 static void cli_negprot_done(struct tevent_req *subreq);
2543 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2544 struct event_context *ev,
2545 struct cli_state *cli)
2547 struct tevent_req *req, *subreq;
2548 struct cli_negprot_state *state;
2549 uint8_t *bytes = NULL;
2550 int numprots;
2552 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2553 if (req == NULL) {
2554 return NULL;
2556 state->cli = cli;
2558 if (cli_state_protocol(cli) < PROTOCOL_NT1)
2559 cli->use_spnego = False;
2561 /* setup the protocol strings */
2562 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2563 uint8_t c = 2;
2564 if (prots[numprots].prot > cli_state_protocol(cli)) {
2565 break;
2567 bytes = (uint8_t *)talloc_append_blob(
2568 state, bytes, data_blob_const(&c, sizeof(c)));
2569 if (tevent_req_nomem(bytes, req)) {
2570 return tevent_req_post(req, ev);
2572 bytes = smb_bytes_push_str(bytes, false,
2573 prots[numprots].name,
2574 strlen(prots[numprots].name)+1,
2575 NULL);
2576 if (tevent_req_nomem(bytes, req)) {
2577 return tevent_req_post(req, ev);
2581 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2582 talloc_get_size(bytes), bytes);
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 wct;
2599 uint16_t *vwv;
2600 uint32_t num_bytes;
2601 uint8_t *bytes;
2602 NTSTATUS status;
2603 uint16_t protnum;
2604 uint8_t *inbuf;
2606 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2607 &num_bytes, &bytes);
2608 TALLOC_FREE(subreq);
2609 if (!NT_STATUS_IS_OK(status)) {
2610 tevent_req_nterror(req, status);
2611 return;
2614 protnum = SVAL(vwv, 0);
2616 if ((protnum >= ARRAY_SIZE(prots))
2617 || (prots[protnum].prot > cli_state_protocol(cli))) {
2618 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2619 return;
2622 cli->protocol = prots[protnum].prot;
2624 if ((cli_state_protocol(cli) < PROTOCOL_NT1) &&
2625 client_is_signing_mandatory(cli)) {
2626 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2627 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2628 return;
2631 if (cli_state_protocol(cli) >= PROTOCOL_NT1) {
2632 struct timespec ts;
2633 const char *client_signing = NULL;
2634 bool server_mandatory;
2635 bool server_allowed;
2636 const char *server_signing = NULL;
2637 bool ok;
2639 if (wct != 0x11) {
2640 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2641 return;
2644 /* NT protocol */
2645 cli->sec_mode = CVAL(vwv + 1, 0);
2646 cli->max_mux = SVAL(vwv + 1, 1);
2647 cli->max_xmit = IVAL(vwv + 3, 1);
2648 cli->sesskey = IVAL(vwv + 7, 1);
2649 cli->serverzone = SVALS(vwv + 15, 1);
2650 cli->serverzone *= 60;
2651 /* this time arrives in real GMT */
2652 ts = interpret_long_date(((char *)(vwv+11))+1);
2653 cli->servertime = ts.tv_sec;
2654 cli->secblob = data_blob(bytes, num_bytes);
2655 cli->capabilities = IVAL(vwv + 9, 1);
2656 if (cli_state_capabilities(cli) & CAP_RAW_MODE) {
2657 cli->readbraw_supported = True;
2658 cli->writebraw_supported = True;
2660 /* work out if they sent us a workgroup */
2661 if (!(cli_state_capabilities(cli) & CAP_EXTENDED_SECURITY) &&
2662 smb_buflen(inbuf) > 8) {
2663 ssize_t ret;
2664 status = smb_bytes_talloc_string(
2665 cli, (char *)inbuf, &cli->server_domain,
2666 bytes + 8, num_bytes - 8, &ret);
2667 if (tevent_req_nterror(req, status)) {
2668 return;
2672 client_signing = "disabled";
2673 if (client_is_signing_allowed(cli)) {
2674 client_signing = "allowed";
2676 if (client_is_signing_mandatory(cli)) {
2677 client_signing = "required";
2680 server_signing = "not supported";
2681 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2682 server_signing = "supported";
2683 server_allowed = true;
2685 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2686 server_signing = "required";
2687 server_mandatory = true;
2690 ok = cli_set_signing_negotiated(cli,
2691 server_allowed,
2692 server_mandatory);
2693 if (!ok) {
2694 DEBUG(1,("cli_negprot: SMB signing is required, "
2695 "but client[%s] and server[%s] mismatch\n",
2696 client_signing, server_signing));
2697 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2698 return;
2701 } else if (cli_state_protocol(cli) >= PROTOCOL_LANMAN1) {
2702 if (wct != 0x0D) {
2703 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2704 return;
2707 cli->use_spnego = False;
2708 cli->sec_mode = SVAL(vwv + 1, 0);
2709 cli->max_xmit = SVAL(vwv + 2, 0);
2710 cli->max_mux = SVAL(vwv + 3, 0);
2711 cli->sesskey = IVAL(vwv + 6, 0);
2712 cli->serverzone = SVALS(vwv + 10, 0);
2713 cli->serverzone *= 60;
2714 /* this time is converted to GMT by make_unix_date */
2715 cli->servertime = make_unix_date(
2716 (char *)(vwv + 8), cli->serverzone);
2717 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2718 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2719 cli->secblob = data_blob(bytes, num_bytes);
2720 } else {
2721 /* the old core protocol */
2722 cli->use_spnego = False;
2723 cli->sec_mode = 0;
2724 cli->serverzone = get_time_zone(time(NULL));
2725 cli->max_xmit = 1024;
2726 cli->max_mux = 1;
2729 if (cli->max_xmit < 1024) {
2730 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2731 return;
2734 if (cli->max_mux < 1) {
2735 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2736 return;
2739 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2741 /* a way to force ascii SMB */
2742 if (cli->force_ascii) {
2743 cli->capabilities &= ~CAP_UNICODE;
2746 tevent_req_done(req);
2749 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2751 return tevent_req_simple_recv_ntstatus(req);
2754 NTSTATUS cli_negprot(struct cli_state *cli)
2756 TALLOC_CTX *frame = talloc_stackframe();
2757 struct event_context *ev;
2758 struct tevent_req *req;
2759 NTSTATUS status = NT_STATUS_OK;
2761 if (cli_has_async_calls(cli)) {
2763 * Can't use sync call while an async call is in flight
2765 status = NT_STATUS_INVALID_PARAMETER;
2766 goto fail;
2769 ev = event_context_init(frame);
2770 if (ev == NULL) {
2771 status = NT_STATUS_NO_MEMORY;
2772 goto fail;
2775 req = cli_negprot_send(frame, ev, cli);
2776 if (req == NULL) {
2777 status = NT_STATUS_NO_MEMORY;
2778 goto fail;
2781 if (!tevent_req_poll(req, ev)) {
2782 status = map_nt_error_from_unix(errno);
2783 goto fail;
2786 status = cli_negprot_recv(req);
2787 fail:
2788 TALLOC_FREE(frame);
2789 return status;
2792 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2793 const struct sockaddr_storage *pss,
2794 const char *myname, uint16_t port,
2795 int sec_timeout, int *pfd, uint16_t *pport)
2797 TALLOC_CTX *frame = talloc_stackframe();
2798 const char *prog;
2799 unsigned int i, num_addrs;
2800 const char **called_names;
2801 const char **calling_names;
2802 int *called_types;
2803 NTSTATUS status;
2804 int fd;
2806 prog = getenv("LIBSMB_PROG");
2807 if (prog != NULL) {
2808 fd = sock_exec(prog);
2809 if (fd == -1) {
2810 return map_nt_error_from_unix(errno);
2812 port = 0;
2813 goto done;
2816 if ((pss == NULL) || is_zero_addr(pss)) {
2817 struct sockaddr_storage *addrs;
2818 status = resolve_name_list(talloc_tos(), host, name_type,
2819 &addrs, &num_addrs);
2820 if (!NT_STATUS_IS_OK(status)) {
2821 goto fail;
2823 pss = addrs;
2824 } else {
2825 num_addrs = 1;
2828 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2829 if (called_names == NULL) {
2830 status = NT_STATUS_NO_MEMORY;
2831 goto fail;
2833 called_types = talloc_array(talloc_tos(), int, num_addrs);
2834 if (called_types == NULL) {
2835 status = NT_STATUS_NO_MEMORY;
2836 goto fail;
2838 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2839 if (calling_names == NULL) {
2840 status = NT_STATUS_NO_MEMORY;
2841 goto fail;
2843 for (i=0; i<num_addrs; i++) {
2844 called_names[i] = host;
2845 called_types[i] = name_type;
2846 calling_names[i] = myname;
2848 status = smbsock_any_connect(pss, called_names, called_types,
2849 calling_names, NULL, num_addrs, port,
2850 sec_timeout, &fd, NULL, &port);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 goto fail;
2854 set_socket_options(fd, lp_socket_options());
2855 done:
2856 *pfd = fd;
2857 *pport = port;
2858 status = NT_STATUS_OK;
2859 fail:
2860 TALLOC_FREE(frame);
2861 return status;
2864 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2865 uint16_t port, int name_type, const char *myname,
2866 int signing_state, int flags, struct cli_state **pcli)
2868 TALLOC_CTX *frame = talloc_stackframe();
2869 struct cli_state *cli;
2870 NTSTATUS status = NT_STATUS_NO_MEMORY;
2871 int fd = -1;
2872 char *desthost;
2873 char *p;
2875 desthost = talloc_strdup(talloc_tos(), host);
2876 if (desthost == NULL) {
2877 goto fail;
2880 p = strchr(host, '#');
2881 if (p != NULL) {
2882 name_type = strtol(p+1, NULL, 16);
2883 host = talloc_strndup(talloc_tos(), host, p - host);
2884 if (host == NULL) {
2885 goto fail;
2889 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
2890 20, &fd, &port);
2891 if (!NT_STATUS_IS_OK(status)) {
2892 goto fail;
2895 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
2896 if (cli == NULL) {
2897 goto fail;
2900 *pcli = cli;
2901 status = NT_STATUS_OK;
2902 fail:
2903 TALLOC_FREE(frame);
2904 return status;
2908 establishes a connection to after the negprot.
2909 @param output_cli A fully initialised cli structure, non-null only on success
2910 @param dest_host The netbios name of the remote host
2911 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2912 @param port (optional) The destination port (0 for default)
2914 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2915 const char *my_name,
2916 const char *dest_host,
2917 const struct sockaddr_storage *dest_ss, int port,
2918 int signing_state, int flags)
2920 NTSTATUS nt_status;
2921 struct cli_state *cli;
2923 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2924 signing_state, flags, &cli);
2925 if (!NT_STATUS_IS_OK(nt_status)) {
2926 DEBUG(10, ("cli_connect_nb failed: %s\n",
2927 nt_errstr(nt_status)));
2928 return nt_status;
2931 nt_status = cli_negprot(cli);
2932 if (!NT_STATUS_IS_OK(nt_status)) {
2933 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2934 cli_shutdown(cli);
2935 return nt_status;
2938 *output_cli = cli;
2939 return NT_STATUS_OK;
2944 establishes a connection right up to doing tconX, password specified.
2945 @param output_cli A fully initialised cli structure, non-null only on success
2946 @param dest_host The netbios name of the remote host
2947 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2948 @param port (optional) The destination port (0 for default)
2949 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2950 @param service_type The 'type' of serivice.
2951 @param user Username, unix string
2952 @param domain User's domain
2953 @param password User's password, unencrypted unix string.
2956 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2957 const char *my_name,
2958 const char *dest_host,
2959 const struct sockaddr_storage *dest_ss, int port,
2960 const char *service, const char *service_type,
2961 const char *user, const char *domain,
2962 const char *password, int flags,
2963 int signing_state)
2965 NTSTATUS nt_status;
2966 struct cli_state *cli = NULL;
2967 int pw_len = password ? strlen(password)+1 : 0;
2969 *output_cli = NULL;
2971 if (password == NULL) {
2972 password = "";
2975 nt_status = cli_start_connection(&cli, my_name, dest_host,
2976 dest_ss, port, signing_state,
2977 flags);
2979 if (!NT_STATUS_IS_OK(nt_status)) {
2980 return nt_status;
2983 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2984 pw_len, domain);
2985 if (!NT_STATUS_IS_OK(nt_status)) {
2987 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2988 DEBUG(1,("failed session setup with %s\n",
2989 nt_errstr(nt_status)));
2990 cli_shutdown(cli);
2991 return nt_status;
2994 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2995 if (!NT_STATUS_IS_OK(nt_status)) {
2996 DEBUG(1,("anonymous failed session setup with %s\n",
2997 nt_errstr(nt_status)));
2998 cli_shutdown(cli);
2999 return nt_status;
3003 if (service) {
3004 nt_status = cli_tcon_andx(cli, service, service_type, password,
3005 pw_len);
3006 if (!NT_STATUS_IS_OK(nt_status)) {
3007 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3008 cli_shutdown(cli);
3009 if (NT_STATUS_IS_OK(nt_status)) {
3010 nt_status = NT_STATUS_UNSUCCESSFUL;
3012 return nt_status;
3016 nt_status = cli_init_creds(cli, user, domain, password);
3017 if (!NT_STATUS_IS_OK(nt_status)) {
3018 cli_shutdown(cli);
3019 return nt_status;
3022 *output_cli = cli;
3023 return NT_STATUS_OK;
3026 /****************************************************************************
3027 Send an old style tcon.
3028 ****************************************************************************/
3029 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3030 const char *service, const char *pass, const char *dev,
3031 uint16 *max_xmit, uint16 *tid)
3033 struct tevent_req *req;
3034 uint16_t *ret_vwv;
3035 uint8_t *bytes;
3036 NTSTATUS status;
3038 if (!lp_client_plaintext_auth() && (*pass)) {
3039 DEBUG(1, ("Server requested plaintext password but 'client "
3040 "plaintext auth' is disabled\n"));
3041 return NT_STATUS_ACCESS_DENIED;
3044 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3045 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3046 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3047 service, strlen(service)+1, NULL);
3048 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3049 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3050 pass, strlen(pass)+1, NULL);
3051 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3052 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3053 dev, strlen(dev)+1, NULL);
3055 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3056 talloc_get_size(bytes), bytes, &req,
3057 2, NULL, &ret_vwv, NULL, NULL);
3058 if (!NT_STATUS_IS_OK(status)) {
3059 return status;
3062 *max_xmit = SVAL(ret_vwv + 0, 0);
3063 *tid = SVAL(ret_vwv + 1, 0);
3065 return NT_STATUS_OK;
3068 /* Return a cli_state pointing at the IPC$ share for the given server */
3070 struct cli_state *get_ipc_connect(char *server,
3071 struct sockaddr_storage *server_ss,
3072 const struct user_auth_info *user_info)
3074 struct cli_state *cli;
3075 NTSTATUS nt_status;
3076 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3078 if (user_info->use_kerberos) {
3079 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3082 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3083 user_info->username ? user_info->username : "",
3084 lp_workgroup(),
3085 user_info->password ? user_info->password : "",
3086 flags,
3087 Undefined);
3089 if (NT_STATUS_IS_OK(nt_status)) {
3090 return cli;
3091 } else if (is_ipaddress(server)) {
3092 /* windows 9* needs a correct NMB name for connections */
3093 fstring remote_name;
3095 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3096 cli = get_ipc_connect(remote_name, server_ss, user_info);
3097 if (cli)
3098 return cli;
3101 return NULL;
3105 * Given the IP address of a master browser on the network, return its
3106 * workgroup and connect to it.
3108 * This function is provided to allow additional processing beyond what
3109 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3110 * browsers and obtain each master browsers' list of domains (in case the
3111 * first master browser is recently on the network and has not yet
3112 * synchronized with other master browsers and therefore does not yet have the
3113 * entire network browse list)
3116 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3117 struct sockaddr_storage *mb_ip,
3118 const struct user_auth_info *user_info,
3119 char **pp_workgroup_out)
3121 char addr[INET6_ADDRSTRLEN];
3122 fstring name;
3123 struct cli_state *cli;
3124 struct sockaddr_storage server_ss;
3126 *pp_workgroup_out = NULL;
3128 print_sockaddr(addr, sizeof(addr), mb_ip);
3129 DEBUG(99, ("Looking up name of master browser %s\n",
3130 addr));
3133 * Do a name status query to find out the name of the master browser.
3134 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3135 * master browser will not respond to a wildcard query (or, at least,
3136 * an NT4 server acting as the domain master browser will not).
3138 * We might be able to use ONLY the query on MSBROWSE, but that's not
3139 * yet been tested with all Windows versions, so until it is, leave
3140 * the original wildcard query as the first choice and fall back to
3141 * MSBROWSE if the wildcard query fails.
3143 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3144 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3146 DEBUG(99, ("Could not retrieve name status for %s\n",
3147 addr));
3148 return NULL;
3151 if (!find_master_ip(name, &server_ss)) {
3152 DEBUG(99, ("Could not find master ip for %s\n", name));
3153 return NULL;
3156 *pp_workgroup_out = talloc_strdup(ctx, name);
3158 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3160 print_sockaddr(addr, sizeof(addr), &server_ss);
3161 cli = get_ipc_connect(addr, &server_ss, user_info);
3163 return cli;
3167 * Return the IP address and workgroup of a master browser on the network, and
3168 * connect to it.
3171 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3172 const struct user_auth_info *user_info,
3173 char **pp_workgroup_out)
3175 struct sockaddr_storage *ip_list;
3176 struct cli_state *cli;
3177 int i, count;
3178 NTSTATUS status;
3180 *pp_workgroup_out = NULL;
3182 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3184 /* Go looking for workgroups by broadcasting on the local network */
3186 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3187 &ip_list, &count);
3188 if (!NT_STATUS_IS_OK(status)) {
3189 DEBUG(99, ("No master browsers responded: %s\n",
3190 nt_errstr(status)));
3191 return False;
3194 for (i = 0; i < count; i++) {
3195 char addr[INET6_ADDRSTRLEN];
3196 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3197 DEBUG(99, ("Found master browser %s\n", addr));
3199 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3200 user_info, pp_workgroup_out);
3201 if (cli)
3202 return(cli);
3205 return NULL;