s3:net_time: make use of cli_state_server_time_zone() and cli_state_server_time()
[Samba.git] / source3 / libsmb / cliconnect.c
blob4ebabceaa7d533f8abc2a9b45a136fea8dbe382c
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 if (strstr(cli->server_type, "Samba")) {
321 cli->is_samba = True;
323 status = cli_set_username(cli, state->user);
324 if (tevent_req_nterror(req, status)) {
325 return;
327 tevent_req_done(req);
330 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
332 return tevent_req_simple_recv_ntstatus(req);
335 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
336 const char *pass, size_t passlen,
337 const char *workgroup)
339 TALLOC_CTX *frame = talloc_stackframe();
340 struct event_context *ev;
341 struct tevent_req *req;
342 NTSTATUS status = NT_STATUS_NO_MEMORY;
344 if (cli_has_async_calls(cli)) {
346 * Can't use sync call while an async call is in flight
348 status = NT_STATUS_INVALID_PARAMETER;
349 goto fail;
351 ev = event_context_init(frame);
352 if (ev == NULL) {
353 goto fail;
355 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
356 workgroup);
357 if (req == NULL) {
358 goto fail;
360 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
361 goto fail;
363 status = cli_session_setup_lanman2_recv(req);
364 fail:
365 TALLOC_FREE(frame);
366 return status;
369 /****************************************************************************
370 Work out suitable capabilities to offer the server.
371 ****************************************************************************/
373 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
375 uint32 capabilities = CAP_NT_SMBS;
377 if (!cli->force_dos_errors)
378 capabilities |= CAP_STATUS32;
380 if (cli->use_level_II_oplocks)
381 capabilities |= CAP_LEVEL_II_OPLOCKS;
383 capabilities |= (cli_state_capabilities(cli) & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
384 return capabilities;
387 /****************************************************************************
388 Do a NT1 guest session setup.
389 ****************************************************************************/
391 struct cli_session_setup_guest_state {
392 struct cli_state *cli;
393 uint16_t vwv[13];
394 struct iovec bytes;
397 static void cli_session_setup_guest_done(struct tevent_req *subreq);
399 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
400 struct event_context *ev,
401 struct cli_state *cli,
402 struct tevent_req **psmbreq)
404 struct tevent_req *req, *subreq;
405 struct cli_session_setup_guest_state *state;
406 uint16_t *vwv;
407 uint8_t *bytes;
409 req = tevent_req_create(mem_ctx, &state,
410 struct cli_session_setup_guest_state);
411 if (req == NULL) {
412 return NULL;
414 state->cli = cli;
415 vwv = state->vwv;
417 SCVAL(vwv+0, 0, 0xFF);
418 SCVAL(vwv+0, 1, 0);
419 SSVAL(vwv+1, 0, 0);
420 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
421 SSVAL(vwv+3, 0, 2);
422 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
423 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
424 SSVAL(vwv+7, 0, 0);
425 SSVAL(vwv+8, 0, 0);
426 SSVAL(vwv+9, 0, 0);
427 SSVAL(vwv+10, 0, 0);
428 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
430 bytes = talloc_array(state, uint8_t, 0);
432 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
433 NULL);
434 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
435 NULL);
436 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
437 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
439 if (bytes == NULL) {
440 TALLOC_FREE(req);
441 return NULL;
444 state->bytes.iov_base = (void *)bytes;
445 state->bytes.iov_len = talloc_get_size(bytes);
447 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
448 1, &state->bytes);
449 if (subreq == NULL) {
450 TALLOC_FREE(req);
451 return NULL;
453 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
454 *psmbreq = subreq;
455 return req;
458 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
459 struct event_context *ev,
460 struct cli_state *cli)
462 struct tevent_req *req, *subreq;
463 NTSTATUS status;
465 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
466 if (req == NULL) {
467 return NULL;
470 status = cli_smb_req_send(subreq);
471 if (NT_STATUS_IS_OK(status)) {
472 tevent_req_nterror(req, status);
473 return tevent_req_post(req, ev);
475 return req;
478 static void cli_session_setup_guest_done(struct tevent_req *subreq)
480 struct tevent_req *req = tevent_req_callback_data(
481 subreq, struct tevent_req);
482 struct cli_session_setup_guest_state *state = tevent_req_data(
483 req, struct cli_session_setup_guest_state);
484 struct cli_state *cli = state->cli;
485 uint32_t num_bytes;
486 uint8_t *in;
487 char *inbuf;
488 uint8_t *bytes;
489 uint8_t *p;
490 NTSTATUS status;
491 ssize_t ret;
492 uint8_t wct;
493 uint16_t *vwv;
495 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
496 &num_bytes, &bytes);
497 TALLOC_FREE(subreq);
498 if (!NT_STATUS_IS_OK(status)) {
499 tevent_req_nterror(req, status);
500 return;
503 inbuf = (char *)in;
504 p = bytes;
506 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
507 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
509 status = smb_bytes_talloc_string(cli,
510 inbuf,
511 &cli->server_os,
513 bytes+num_bytes-p,
514 &ret);
516 if (!NT_STATUS_IS_OK(status)) {
517 tevent_req_nterror(req, status);
518 return;
520 p += ret;
522 status = smb_bytes_talloc_string(cli,
523 inbuf,
524 &cli->server_type,
526 bytes+num_bytes-p,
527 &ret);
529 if (!NT_STATUS_IS_OK(status)) {
530 tevent_req_nterror(req, status);
531 return;
533 p += ret;
535 status = smb_bytes_talloc_string(cli,
536 inbuf,
537 &cli->server_domain,
539 bytes+num_bytes-p,
540 &ret);
542 if (!NT_STATUS_IS_OK(status)) {
543 tevent_req_nterror(req, status);
544 return;
546 p += ret;
548 if (strstr(cli->server_type, "Samba")) {
549 cli->is_samba = True;
552 status = cli_set_username(cli, "");
553 if (!NT_STATUS_IS_OK(status)) {
554 tevent_req_nterror(req, status);
555 return;
557 tevent_req_done(req);
560 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
562 return tevent_req_simple_recv_ntstatus(req);
565 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
567 TALLOC_CTX *frame = talloc_stackframe();
568 struct event_context *ev;
569 struct tevent_req *req;
570 NTSTATUS status = NT_STATUS_OK;
572 if (cli_has_async_calls(cli)) {
574 * Can't use sync call while an async call is in flight
576 status = NT_STATUS_INVALID_PARAMETER;
577 goto fail;
580 ev = event_context_init(frame);
581 if (ev == NULL) {
582 status = NT_STATUS_NO_MEMORY;
583 goto fail;
586 req = cli_session_setup_guest_send(frame, ev, cli);
587 if (req == NULL) {
588 status = NT_STATUS_NO_MEMORY;
589 goto fail;
592 if (!tevent_req_poll(req, ev)) {
593 status = map_nt_error_from_unix(errno);
594 goto fail;
597 status = cli_session_setup_guest_recv(req);
598 fail:
599 TALLOC_FREE(frame);
600 return status;
603 /****************************************************************************
604 Do a NT1 plaintext session setup.
605 ****************************************************************************/
607 struct cli_session_setup_plain_state {
608 struct cli_state *cli;
609 uint16_t vwv[13];
610 const char *user;
613 static void cli_session_setup_plain_done(struct tevent_req *subreq);
615 static struct tevent_req *cli_session_setup_plain_send(
616 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
617 struct cli_state *cli,
618 const char *user, const char *pass, const char *workgroup)
620 struct tevent_req *req, *subreq;
621 struct cli_session_setup_plain_state *state;
622 uint16_t *vwv;
623 uint8_t *bytes;
624 size_t passlen;
625 char *version;
627 req = tevent_req_create(mem_ctx, &state,
628 struct cli_session_setup_plain_state);
629 if (req == NULL) {
630 return NULL;
632 state->cli = cli;
633 state->user = user;
634 vwv = state->vwv;
636 SCVAL(vwv+0, 0, 0xff);
637 SCVAL(vwv+0, 1, 0);
638 SSVAL(vwv+1, 0, 0);
639 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
640 SSVAL(vwv+3, 0, 2);
641 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
642 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
643 SSVAL(vwv+7, 0, 0);
644 SSVAL(vwv+8, 0, 0);
645 SSVAL(vwv+9, 0, 0);
646 SSVAL(vwv+10, 0, 0);
647 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
649 bytes = talloc_array(state, uint8_t, 0);
650 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
651 &passlen);
652 if (tevent_req_nomem(bytes, req)) {
653 return tevent_req_post(req, ev);
655 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
657 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
658 user, strlen(user)+1, NULL);
659 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
660 workgroup, strlen(workgroup)+1, NULL);
661 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
662 "Unix", 5, NULL);
664 version = talloc_asprintf(talloc_tos(), "Samba %s",
665 samba_version_string());
666 if (tevent_req_nomem(version, req)){
667 return tevent_req_post(req, ev);
669 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
670 version, strlen(version)+1, NULL);
671 TALLOC_FREE(version);
673 if (tevent_req_nomem(bytes, req)) {
674 return tevent_req_post(req, ev);
677 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
678 talloc_get_size(bytes), bytes);
679 if (tevent_req_nomem(subreq, req)) {
680 return tevent_req_post(req, ev);
682 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
683 return req;
686 static void cli_session_setup_plain_done(struct tevent_req *subreq)
688 struct tevent_req *req = tevent_req_callback_data(
689 subreq, struct tevent_req);
690 struct cli_session_setup_plain_state *state = tevent_req_data(
691 req, struct cli_session_setup_plain_state);
692 struct cli_state *cli = state->cli;
693 uint32_t num_bytes;
694 uint8_t *in;
695 char *inbuf;
696 uint8_t *bytes;
697 uint8_t *p;
698 NTSTATUS status;
699 ssize_t ret;
700 uint8_t wct;
701 uint16_t *vwv;
703 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
704 &num_bytes, &bytes);
705 TALLOC_FREE(subreq);
706 if (tevent_req_nterror(req, status)) {
707 return;
710 inbuf = (char *)in;
711 p = bytes;
713 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
714 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
716 status = smb_bytes_talloc_string(cli,
717 inbuf,
718 &cli->server_os,
720 bytes+num_bytes-p,
721 &ret);
723 if (!NT_STATUS_IS_OK(status)) {
724 tevent_req_nterror(req, status);
725 return;
727 p += ret;
729 status = smb_bytes_talloc_string(cli,
730 inbuf,
731 &cli->server_type,
733 bytes+num_bytes-p,
734 &ret);
736 if (!NT_STATUS_IS_OK(status)) {
737 tevent_req_nterror(req, status);
738 return;
740 p += ret;
742 status = smb_bytes_talloc_string(cli,
743 inbuf,
744 &cli->server_domain,
746 bytes+num_bytes-p,
747 &ret);
749 if (!NT_STATUS_IS_OK(status)) {
750 tevent_req_nterror(req, status);
751 return;
753 p += ret;
755 status = cli_set_username(cli, state->user);
756 if (tevent_req_nterror(req, status)) {
757 return;
759 if (strstr(cli->server_type, "Samba")) {
760 cli->is_samba = True;
762 tevent_req_done(req);
765 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
767 return tevent_req_simple_recv_ntstatus(req);
770 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
771 const char *user, const char *pass,
772 const char *workgroup)
774 TALLOC_CTX *frame = talloc_stackframe();
775 struct event_context *ev;
776 struct tevent_req *req;
777 NTSTATUS status = NT_STATUS_NO_MEMORY;
779 if (cli_has_async_calls(cli)) {
781 * Can't use sync call while an async call is in flight
783 status = NT_STATUS_INVALID_PARAMETER;
784 goto fail;
786 ev = event_context_init(frame);
787 if (ev == NULL) {
788 goto fail;
790 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
791 workgroup);
792 if (req == NULL) {
793 goto fail;
795 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
796 goto fail;
798 status = cli_session_setup_plain_recv(req);
799 fail:
800 TALLOC_FREE(frame);
801 return status;
804 /****************************************************************************
805 do a NT1 NTLM/LM encrypted session setup - for when extended security
806 is not negotiated.
807 @param cli client state to create do session setup on
808 @param user username
809 @param pass *either* cleartext password (passlen !=24) or LM response.
810 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
811 @param workgroup The user's domain.
812 ****************************************************************************/
814 struct cli_session_setup_nt1_state {
815 struct cli_state *cli;
816 uint16_t vwv[13];
817 DATA_BLOB response;
818 DATA_BLOB session_key;
819 const char *user;
822 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
824 static struct tevent_req *cli_session_setup_nt1_send(
825 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
826 struct cli_state *cli, const char *user,
827 const char *pass, size_t passlen,
828 const char *ntpass, size_t ntpasslen,
829 const char *workgroup)
831 struct tevent_req *req, *subreq;
832 struct cli_session_setup_nt1_state *state;
833 DATA_BLOB lm_response = data_blob_null;
834 DATA_BLOB nt_response = data_blob_null;
835 DATA_BLOB session_key = data_blob_null;
836 uint16_t *vwv;
837 uint8_t *bytes;
838 char *workgroup_upper;
840 req = tevent_req_create(mem_ctx, &state,
841 struct cli_session_setup_nt1_state);
842 if (req == NULL) {
843 return NULL;
845 state->cli = cli;
846 state->user = user;
847 vwv = state->vwv;
849 if (passlen == 0) {
850 /* do nothing - guest login */
851 } else if (passlen != 24) {
852 if (lp_client_ntlmv2_auth()) {
853 DATA_BLOB server_chal;
854 DATA_BLOB names_blob;
856 server_chal = data_blob(cli->secblob.data,
857 MIN(cli->secblob.length, 8));
858 if (tevent_req_nomem(server_chal.data, req)) {
859 return tevent_req_post(req, ev);
863 * note that the 'workgroup' here is a best
864 * guess - we don't know the server's domain
865 * at this point. Windows clients also don't
866 * use hostname...
868 names_blob = NTLMv2_generate_names_blob(
869 NULL, NULL, workgroup);
871 if (tevent_req_nomem(names_blob.data, req)) {
872 return tevent_req_post(req, ev);
875 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
876 &server_chal, &names_blob,
877 &lm_response, &nt_response,
878 NULL, &session_key)) {
879 data_blob_free(&names_blob);
880 data_blob_free(&server_chal);
881 tevent_req_nterror(
882 req, NT_STATUS_ACCESS_DENIED);
883 return tevent_req_post(req, ev);
885 data_blob_free(&names_blob);
886 data_blob_free(&server_chal);
888 } else {
889 uchar nt_hash[16];
890 E_md4hash(pass, nt_hash);
892 #ifdef LANMAN_ONLY
893 nt_response = data_blob_null;
894 #else
895 nt_response = data_blob(NULL, 24);
896 if (tevent_req_nomem(nt_response.data, req)) {
897 return tevent_req_post(req, ev);
900 SMBNTencrypt(pass, cli->secblob.data,
901 nt_response.data);
902 #endif
903 /* non encrypted password supplied. Ignore ntpass. */
904 if (lp_client_lanman_auth()) {
906 lm_response = data_blob(NULL, 24);
907 if (tevent_req_nomem(lm_response.data, req)) {
908 return tevent_req_post(req, ev);
911 if (!SMBencrypt(pass,cli->secblob.data,
912 lm_response.data)) {
914 * Oops, the LM response is
915 * invalid, just put the NT
916 * response there instead
918 data_blob_free(&lm_response);
919 lm_response = data_blob(
920 nt_response.data,
921 nt_response.length);
923 } else {
925 * LM disabled, place NT# in LM field
926 * instead
928 lm_response = data_blob(
929 nt_response.data, nt_response.length);
932 if (tevent_req_nomem(lm_response.data, req)) {
933 return tevent_req_post(req, ev);
936 session_key = data_blob(NULL, 16);
937 if (tevent_req_nomem(session_key.data, req)) {
938 return tevent_req_post(req, ev);
940 #ifdef LANMAN_ONLY
941 E_deshash(pass, session_key.data);
942 memset(&session_key.data[8], '\0', 8);
943 #else
944 SMBsesskeygen_ntv1(nt_hash, session_key.data);
945 #endif
947 cli_temp_set_signing(cli);
948 } else {
949 /* pre-encrypted password supplied. Only used for
950 security=server, can't do
951 signing because we don't have original key */
953 lm_response = data_blob(pass, passlen);
954 if (tevent_req_nomem(lm_response.data, req)) {
955 return tevent_req_post(req, ev);
958 nt_response = data_blob(ntpass, ntpasslen);
959 if (tevent_req_nomem(nt_response.data, req)) {
960 return tevent_req_post(req, ev);
964 #ifdef LANMAN_ONLY
965 state->response = data_blob_talloc(
966 state, lm_response.data, lm_response.length);
967 #else
968 state->response = data_blob_talloc(
969 state, nt_response.data, nt_response.length);
970 #endif
971 if (tevent_req_nomem(state->response.data, req)) {
972 return tevent_req_post(req, ev);
975 if (session_key.data) {
976 state->session_key = data_blob_talloc(
977 state, session_key.data, session_key.length);
978 if (tevent_req_nomem(state->session_key.data, req)) {
979 return tevent_req_post(req, ev);
982 data_blob_free(&session_key);
984 SCVAL(vwv+0, 0, 0xff);
985 SCVAL(vwv+0, 1, 0);
986 SSVAL(vwv+1, 0, 0);
987 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
988 SSVAL(vwv+3, 0, 2);
989 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
990 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
991 SSVAL(vwv+7, 0, lm_response.length);
992 SSVAL(vwv+8, 0, nt_response.length);
993 SSVAL(vwv+9, 0, 0);
994 SSVAL(vwv+10, 0, 0);
995 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
997 bytes = talloc_array(state, uint8_t,
998 lm_response.length + nt_response.length);
999 if (tevent_req_nomem(bytes, req)) {
1000 return tevent_req_post(req, ev);
1002 if (lm_response.length != 0) {
1003 memcpy(bytes, lm_response.data, lm_response.length);
1005 if (nt_response.length != 0) {
1006 memcpy(bytes + lm_response.length,
1007 nt_response.data, nt_response.length);
1009 data_blob_free(&lm_response);
1010 data_blob_free(&nt_response);
1012 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1013 user, strlen(user)+1, NULL);
1016 * Upper case here might help some NTLMv2 implementations
1018 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1019 if (tevent_req_nomem(workgroup_upper, req)) {
1020 return tevent_req_post(req, ev);
1022 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1023 workgroup_upper, strlen(workgroup_upper)+1,
1024 NULL);
1025 TALLOC_FREE(workgroup_upper);
1027 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1028 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1029 if (tevent_req_nomem(bytes, req)) {
1030 return tevent_req_post(req, ev);
1033 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1034 talloc_get_size(bytes), bytes);
1035 if (tevent_req_nomem(subreq, req)) {
1036 return tevent_req_post(req, ev);
1038 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1039 return req;
1042 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1044 struct tevent_req *req = tevent_req_callback_data(
1045 subreq, struct tevent_req);
1046 struct cli_session_setup_nt1_state *state = tevent_req_data(
1047 req, struct cli_session_setup_nt1_state);
1048 struct cli_state *cli = state->cli;
1049 uint32_t num_bytes;
1050 uint8_t *in;
1051 char *inbuf;
1052 uint8_t *bytes;
1053 uint8_t *p;
1054 NTSTATUS status;
1055 ssize_t ret;
1056 uint8_t wct;
1057 uint16_t *vwv;
1059 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1060 &num_bytes, &bytes);
1061 TALLOC_FREE(subreq);
1062 if (!NT_STATUS_IS_OK(status)) {
1063 tevent_req_nterror(req, status);
1064 return;
1067 inbuf = (char *)in;
1068 p = bytes;
1070 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
1071 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1073 status = smb_bytes_talloc_string(cli,
1074 inbuf,
1075 &cli->server_os,
1077 bytes+num_bytes-p,
1078 &ret);
1079 if (!NT_STATUS_IS_OK(status)) {
1080 tevent_req_nterror(req, status);
1081 return;
1083 p += ret;
1085 status = smb_bytes_talloc_string(cli,
1086 inbuf,
1087 &cli->server_type,
1089 bytes+num_bytes-p,
1090 &ret);
1091 if (!NT_STATUS_IS_OK(status)) {
1092 tevent_req_nterror(req, status);
1093 return;
1095 p += ret;
1097 status = smb_bytes_talloc_string(cli,
1098 inbuf,
1099 &cli->server_domain,
1101 bytes+num_bytes-p,
1102 &ret);
1103 if (!NT_STATUS_IS_OK(status)) {
1104 tevent_req_nterror(req, status);
1105 return;
1107 p += ret;
1109 if (strstr(cli->server_type, "Samba")) {
1110 cli->is_samba = True;
1113 status = cli_set_username(cli, state->user);
1114 if (tevent_req_nterror(req, status)) {
1115 return;
1117 if (cli_simple_set_signing(cli, state->session_key, state->response)
1118 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1119 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1120 return;
1122 if (state->session_key.data) {
1123 /* Have plaintext orginal */
1124 cli_set_session_key(cli, state->session_key);
1126 tevent_req_done(req);
1129 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1131 return tevent_req_simple_recv_ntstatus(req);
1134 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1135 const char *pass, size_t passlen,
1136 const char *ntpass, size_t ntpasslen,
1137 const char *workgroup)
1139 TALLOC_CTX *frame = talloc_stackframe();
1140 struct event_context *ev;
1141 struct tevent_req *req;
1142 NTSTATUS status = NT_STATUS_NO_MEMORY;
1144 if (cli_has_async_calls(cli)) {
1146 * Can't use sync call while an async call is in flight
1148 status = NT_STATUS_INVALID_PARAMETER;
1149 goto fail;
1151 ev = event_context_init(frame);
1152 if (ev == NULL) {
1153 goto fail;
1155 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1156 ntpass, ntpasslen, workgroup);
1157 if (req == NULL) {
1158 goto fail;
1160 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1161 goto fail;
1163 status = cli_session_setup_nt1_recv(req);
1164 fail:
1165 TALLOC_FREE(frame);
1166 return status;
1169 /* The following is calculated from :
1170 * (smb_size-4) = 35
1171 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1172 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1173 * end of packet.
1176 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1178 struct cli_sesssetup_blob_state {
1179 struct tevent_context *ev;
1180 struct cli_state *cli;
1181 DATA_BLOB blob;
1182 uint16_t max_blob_size;
1183 uint16_t vwv[12];
1184 uint8_t *buf;
1186 NTSTATUS status;
1187 char *inbuf;
1188 DATA_BLOB ret_blob;
1191 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1192 struct tevent_req **psubreq);
1193 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1195 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1196 struct tevent_context *ev,
1197 struct cli_state *cli,
1198 DATA_BLOB blob)
1200 struct tevent_req *req, *subreq;
1201 struct cli_sesssetup_blob_state *state;
1202 uint32_t usable_space;
1204 req = tevent_req_create(mem_ctx, &state,
1205 struct cli_sesssetup_blob_state);
1206 if (req == NULL) {
1207 return NULL;
1209 state->ev = ev;
1210 state->blob = blob;
1211 state->cli = cli;
1213 usable_space = cli_state_available_size(cli,
1214 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1216 if (usable_space == 0) {
1217 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1218 "(not possible to send %u bytes)\n",
1219 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1220 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1221 return tevent_req_post(req, ev);
1223 state->max_blob_size = MIN(usable_space, 0xFFFF);
1225 if (!cli_sesssetup_blob_next(state, &subreq)) {
1226 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1227 return tevent_req_post(req, ev);
1229 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1230 return req;
1233 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1234 struct tevent_req **psubreq)
1236 struct tevent_req *subreq;
1237 uint16_t thistime;
1239 SCVAL(state->vwv+0, 0, 0xFF);
1240 SCVAL(state->vwv+0, 1, 0);
1241 SSVAL(state->vwv+1, 0, 0);
1242 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1243 SSVAL(state->vwv+3, 0, 2);
1244 SSVAL(state->vwv+4, 0, 1);
1245 SIVAL(state->vwv+5, 0, 0);
1247 thistime = MIN(state->blob.length, state->max_blob_size);
1248 SSVAL(state->vwv+7, 0, thistime);
1250 SSVAL(state->vwv+8, 0, 0);
1251 SSVAL(state->vwv+9, 0, 0);
1252 SIVAL(state->vwv+10, 0,
1253 cli_session_setup_capabilities(state->cli)
1254 | CAP_EXTENDED_SECURITY);
1256 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1257 thistime);
1258 if (state->buf == NULL) {
1259 return false;
1261 state->blob.data += thistime;
1262 state->blob.length -= thistime;
1264 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1265 "Unix", 5, NULL);
1266 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1267 "Samba", 6, NULL);
1268 if (state->buf == NULL) {
1269 return false;
1271 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1272 12, state->vwv,
1273 talloc_get_size(state->buf), state->buf);
1274 if (subreq == NULL) {
1275 return false;
1277 *psubreq = subreq;
1278 return true;
1281 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1283 struct tevent_req *req = tevent_req_callback_data(
1284 subreq, struct tevent_req);
1285 struct cli_sesssetup_blob_state *state = tevent_req_data(
1286 req, struct cli_sesssetup_blob_state);
1287 struct cli_state *cli = state->cli;
1288 uint8_t wct;
1289 uint16_t *vwv;
1290 uint32_t num_bytes;
1291 uint8_t *bytes;
1292 NTSTATUS status;
1293 uint8_t *p;
1294 uint16_t blob_length;
1295 uint8_t *inbuf;
1296 ssize_t ret;
1298 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
1299 &num_bytes, &bytes);
1300 TALLOC_FREE(subreq);
1301 if (!NT_STATUS_IS_OK(status)
1302 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1303 tevent_req_nterror(req, status);
1304 return;
1307 state->status = status;
1308 TALLOC_FREE(state->buf);
1310 state->inbuf = (char *)inbuf;
1311 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
1312 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1314 blob_length = SVAL(vwv+3, 0);
1315 if (blob_length > num_bytes) {
1316 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1317 return;
1319 state->ret_blob = data_blob_const(bytes, blob_length);
1321 p = bytes + blob_length;
1323 status = smb_bytes_talloc_string(cli,
1324 (char *)inbuf,
1325 &cli->server_os,
1327 bytes+num_bytes-p,
1328 &ret);
1330 if (!NT_STATUS_IS_OK(status)) {
1331 tevent_req_nterror(req, status);
1332 return;
1334 p += ret;
1336 status = smb_bytes_talloc_string(cli,
1337 (char *)inbuf,
1338 &cli->server_type,
1340 bytes+num_bytes-p,
1341 &ret);
1343 if (!NT_STATUS_IS_OK(status)) {
1344 tevent_req_nterror(req, status);
1345 return;
1347 p += ret;
1349 status = smb_bytes_talloc_string(cli,
1350 (char *)inbuf,
1351 &cli->server_domain,
1353 bytes+num_bytes-p,
1354 &ret);
1356 if (!NT_STATUS_IS_OK(status)) {
1357 tevent_req_nterror(req, status);
1358 return;
1360 p += ret;
1362 if (strstr(cli->server_type, "Samba")) {
1363 cli->is_samba = True;
1366 if (state->blob.length != 0) {
1368 * More to send
1370 if (!cli_sesssetup_blob_next(state, &subreq)) {
1371 tevent_req_oom(req);
1372 return;
1374 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1375 return;
1377 tevent_req_done(req);
1380 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1381 TALLOC_CTX *mem_ctx,
1382 DATA_BLOB *pblob,
1383 char **pinbuf)
1385 struct cli_sesssetup_blob_state *state = tevent_req_data(
1386 req, struct cli_sesssetup_blob_state);
1387 NTSTATUS status;
1388 char *inbuf;
1390 if (tevent_req_is_nterror(req, &status)) {
1391 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1392 return status;
1395 inbuf = talloc_move(mem_ctx, &state->inbuf);
1396 if (pblob != NULL) {
1397 *pblob = state->ret_blob;
1399 if (pinbuf != NULL) {
1400 *pinbuf = inbuf;
1402 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1403 return state->status;
1406 #ifdef HAVE_KRB5
1408 /****************************************************************************
1409 Use in-memory credentials cache
1410 ****************************************************************************/
1412 static void use_in_memory_ccache(void) {
1413 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1416 /****************************************************************************
1417 Do a spnego/kerberos encrypted session setup.
1418 ****************************************************************************/
1420 struct cli_session_setup_kerberos_state {
1421 struct cli_state *cli;
1422 DATA_BLOB negTokenTarg;
1423 DATA_BLOB session_key_krb5;
1424 ADS_STATUS ads_status;
1427 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1429 static struct tevent_req *cli_session_setup_kerberos_send(
1430 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1431 const char *principal)
1433 struct tevent_req *req, *subreq;
1434 struct cli_session_setup_kerberos_state *state;
1435 int rc;
1437 DEBUG(2,("Doing kerberos session setup\n"));
1439 req = tevent_req_create(mem_ctx, &state,
1440 struct cli_session_setup_kerberos_state);
1441 if (req == NULL) {
1442 return NULL;
1444 state->cli = cli;
1445 state->ads_status = ADS_SUCCESS;
1447 cli_temp_set_signing(cli);
1450 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1451 * we have to acquire a ticket. To be fixed later :-)
1453 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1454 &state->session_key_krb5, 0, NULL);
1455 if (rc) {
1456 DEBUG(1, ("cli_session_setup_kerberos: "
1457 "spnego_gen_krb5_negTokenInit failed: %s\n",
1458 error_message(rc)));
1459 state->ads_status = ADS_ERROR_KRB5(rc);
1460 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1461 return tevent_req_post(req, ev);
1464 #if 0
1465 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1466 state->negTokenTarg.length);
1467 #endif
1469 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1470 if (tevent_req_nomem(subreq, req)) {
1471 return tevent_req_post(req, ev);
1473 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1474 return req;
1477 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1479 struct tevent_req *req = tevent_req_callback_data(
1480 subreq, struct tevent_req);
1481 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1482 req, struct cli_session_setup_kerberos_state);
1483 char *inbuf = NULL;
1484 NTSTATUS status;
1486 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1487 if (!NT_STATUS_IS_OK(status)) {
1488 TALLOC_FREE(subreq);
1489 tevent_req_nterror(req, status);
1490 return;
1493 cli_set_session_key(state->cli, state->session_key_krb5);
1495 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1496 data_blob_null)
1497 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1498 TALLOC_FREE(subreq);
1499 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1500 return;
1502 TALLOC_FREE(subreq);
1503 tevent_req_done(req);
1506 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1508 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1509 req, struct cli_session_setup_kerberos_state);
1510 NTSTATUS status;
1512 if (tevent_req_is_nterror(req, &status)) {
1513 return ADS_ERROR_NT(status);
1515 return state->ads_status;
1518 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1519 const char *principal)
1521 struct tevent_context *ev;
1522 struct tevent_req *req;
1523 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1525 if (cli_has_async_calls(cli)) {
1526 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1528 ev = tevent_context_init(talloc_tos());
1529 if (ev == NULL) {
1530 goto fail;
1532 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1533 if (req == NULL) {
1534 goto fail;
1536 if (!tevent_req_poll(req, ev)) {
1537 status = ADS_ERROR_SYSTEM(errno);
1538 goto fail;
1540 status = cli_session_setup_kerberos_recv(req);
1541 fail:
1542 TALLOC_FREE(ev);
1543 return status;
1545 #endif /* HAVE_KRB5 */
1547 /****************************************************************************
1548 Do a spnego/NTLMSSP encrypted session setup.
1549 ****************************************************************************/
1551 struct cli_session_setup_ntlmssp_state {
1552 struct tevent_context *ev;
1553 struct cli_state *cli;
1554 struct ntlmssp_state *ntlmssp_state;
1555 int turn;
1556 DATA_BLOB blob_out;
1559 static int cli_session_setup_ntlmssp_state_destructor(
1560 struct cli_session_setup_ntlmssp_state *state)
1562 if (state->ntlmssp_state != NULL) {
1563 TALLOC_FREE(state->ntlmssp_state);
1565 return 0;
1568 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1570 static struct tevent_req *cli_session_setup_ntlmssp_send(
1571 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1572 const char *user, const char *pass, const char *domain)
1574 struct tevent_req *req, *subreq;
1575 struct cli_session_setup_ntlmssp_state *state;
1576 NTSTATUS status;
1577 DATA_BLOB blob_out;
1578 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1580 req = tevent_req_create(mem_ctx, &state,
1581 struct cli_session_setup_ntlmssp_state);
1582 if (req == NULL) {
1583 return NULL;
1585 state->ev = ev;
1586 state->cli = cli;
1587 state->turn = 1;
1589 state->ntlmssp_state = NULL;
1590 talloc_set_destructor(
1591 state, cli_session_setup_ntlmssp_state_destructor);
1593 cli_temp_set_signing(cli);
1595 status = ntlmssp_client_start(state,
1596 lp_netbios_name(),
1597 lp_workgroup(),
1598 lp_client_ntlmv2_auth(),
1599 &state->ntlmssp_state);
1600 if (!NT_STATUS_IS_OK(status)) {
1601 goto fail;
1603 ntlmssp_want_feature(state->ntlmssp_state,
1604 NTLMSSP_FEATURE_SESSION_KEY);
1605 if (cli->use_ccache) {
1606 ntlmssp_want_feature(state->ntlmssp_state,
1607 NTLMSSP_FEATURE_CCACHE);
1609 status = ntlmssp_set_username(state->ntlmssp_state, user);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 goto fail;
1613 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 goto fail;
1617 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1618 if (!NT_STATUS_IS_OK(status)) {
1619 goto fail;
1621 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1622 &blob_out);
1623 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1624 goto fail;
1627 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1628 data_blob_free(&blob_out);
1630 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1631 if (tevent_req_nomem(subreq, req)) {
1632 return tevent_req_post(req, ev);
1634 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1635 return req;
1636 fail:
1637 tevent_req_nterror(req, status);
1638 return tevent_req_post(req, ev);
1641 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1643 struct tevent_req *req = tevent_req_callback_data(
1644 subreq, struct tevent_req);
1645 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1646 req, struct cli_session_setup_ntlmssp_state);
1647 DATA_BLOB blob_in, msg_in, blob_out;
1648 char *inbuf = NULL;
1649 bool parse_ret;
1650 NTSTATUS status;
1652 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1653 &inbuf);
1654 TALLOC_FREE(subreq);
1655 data_blob_free(&state->blob_out);
1657 if (NT_STATUS_IS_OK(status)) {
1658 if (state->cli->server_domain[0] == '\0') {
1659 TALLOC_FREE(state->cli->server_domain);
1660 state->cli->server_domain = talloc_strdup(state->cli,
1661 state->ntlmssp_state->server.netbios_domain);
1662 if (state->cli->server_domain == NULL) {
1663 TALLOC_FREE(subreq);
1664 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1665 return;
1668 cli_set_session_key(
1669 state->cli, state->ntlmssp_state->session_key);
1671 if (cli_simple_set_signing(
1672 state->cli, state->ntlmssp_state->session_key,
1673 data_blob_null)
1674 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1675 TALLOC_FREE(subreq);
1676 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1677 return;
1679 TALLOC_FREE(subreq);
1680 TALLOC_FREE(state->ntlmssp_state);
1681 tevent_req_done(req);
1682 return;
1684 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1685 tevent_req_nterror(req, status);
1686 return;
1689 if (blob_in.length == 0) {
1690 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1691 return;
1694 if ((state->turn == 1)
1695 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1696 DATA_BLOB tmp_blob = data_blob_null;
1697 /* the server might give us back two challenges */
1698 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1699 &tmp_blob);
1700 data_blob_free(&tmp_blob);
1701 } else {
1702 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1703 OID_NTLMSSP, &msg_in);
1705 state->turn += 1;
1707 if (!parse_ret) {
1708 DEBUG(3,("Failed to parse auth response\n"));
1709 if (NT_STATUS_IS_OK(status)
1710 || NT_STATUS_EQUAL(status,
1711 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1712 tevent_req_nterror(
1713 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1714 return;
1718 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1720 if (!NT_STATUS_IS_OK(status)
1721 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1722 TALLOC_FREE(subreq);
1723 TALLOC_FREE(state->ntlmssp_state);
1724 tevent_req_nterror(req, status);
1725 return;
1728 state->blob_out = spnego_gen_auth(state, blob_out);
1729 TALLOC_FREE(subreq);
1730 if (tevent_req_nomem(state->blob_out.data, req)) {
1731 return;
1734 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1735 state->blob_out);
1736 if (tevent_req_nomem(subreq, req)) {
1737 return;
1739 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1742 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1744 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1745 req, struct cli_session_setup_ntlmssp_state);
1746 NTSTATUS status;
1748 if (tevent_req_is_nterror(req, &status)) {
1749 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1750 return status;
1752 return NT_STATUS_OK;
1755 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1756 const char *user,
1757 const char *pass,
1758 const char *domain)
1760 struct tevent_context *ev;
1761 struct tevent_req *req;
1762 NTSTATUS status = NT_STATUS_NO_MEMORY;
1764 if (cli_has_async_calls(cli)) {
1765 return NT_STATUS_INVALID_PARAMETER;
1767 ev = tevent_context_init(talloc_tos());
1768 if (ev == NULL) {
1769 goto fail;
1771 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1772 if (req == NULL) {
1773 goto fail;
1775 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1776 goto fail;
1778 status = cli_session_setup_ntlmssp_recv(req);
1779 fail:
1780 TALLOC_FREE(ev);
1781 return status;
1784 /****************************************************************************
1785 Do a spnego encrypted session setup.
1787 user_domain: The shortname of the domain the user/machine is a member of.
1788 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1789 ****************************************************************************/
1791 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1792 const char *user,
1793 const char *pass,
1794 const char *user_domain,
1795 const char * dest_realm)
1797 char *principal = NULL;
1798 char *OIDs[ASN1_MAX_OIDS];
1799 int i;
1800 DATA_BLOB blob;
1801 const char *p = NULL;
1802 char *account = NULL;
1803 NTSTATUS status;
1805 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1807 /* the server might not even do spnego */
1808 if (cli->secblob.length <= 16) {
1809 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1810 goto ntlmssp;
1813 #if 0
1814 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1815 #endif
1817 /* there is 16 bytes of GUID before the real spnego packet starts */
1818 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1820 /* The server sent us the first part of the SPNEGO exchange in the
1821 * negprot reply. It is WRONG to depend on the principal sent in the
1822 * negprot reply, but right now we do it. If we don't receive one,
1823 * we try to best guess, then fall back to NTLM. */
1824 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1825 OIDs[0] == NULL) {
1826 data_blob_free(&blob);
1827 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1829 data_blob_free(&blob);
1831 /* make sure the server understands kerberos */
1832 for (i=0;OIDs[i];i++) {
1833 if (i == 0)
1834 DEBUG(3,("got OID=%s\n", OIDs[i]));
1835 else
1836 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1837 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1838 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1839 cli->got_kerberos_mechanism = True;
1841 talloc_free(OIDs[i]);
1844 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1846 status = cli_set_username(cli, user);
1847 if (!NT_STATUS_IS_OK(status)) {
1848 TALLOC_FREE(principal);
1849 return ADS_ERROR_NT(status);
1852 #ifdef HAVE_KRB5
1853 /* If password is set we reauthenticate to kerberos server
1854 * and do not store results */
1856 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1857 ADS_STATUS rc;
1858 const char *remote_name = cli_state_remote_name(cli);
1860 if (pass && *pass) {
1861 int ret;
1863 use_in_memory_ccache();
1864 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1866 if (ret){
1867 TALLOC_FREE(principal);
1868 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1869 if (cli->fallback_after_kerberos)
1870 goto ntlmssp;
1871 return ADS_ERROR_KRB5(ret);
1875 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1877 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1878 TALLOC_FREE(principal);
1881 if (principal == NULL &&
1882 !is_ipaddress(remote_name) &&
1883 !strequal(STAR_SMBSERVER,
1884 remote_name)) {
1885 char *realm = NULL;
1886 char *host = NULL;
1887 DEBUG(3,("cli_session_setup_spnego: using target "
1888 "hostname not SPNEGO principal\n"));
1890 host = strchr_m(remote_name, '.');
1891 if (dest_realm) {
1892 realm = SMB_STRDUP(dest_realm);
1893 if (!realm) {
1894 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1896 strupper_m(realm);
1897 } else {
1898 if (host) {
1899 /* DNS name. */
1900 realm = kerberos_get_realm_from_hostname(remote_name);
1901 } else {
1902 /* NetBIOS name - use our realm. */
1903 realm = kerberos_get_default_realm_from_ccache();
1907 if (realm == NULL || *realm == '\0') {
1908 realm = SMB_STRDUP(lp_realm());
1909 if (!realm) {
1910 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1912 strupper_m(realm);
1913 DEBUG(3,("cli_session_setup_spnego: cannot "
1914 "get realm from dest_realm %s, "
1915 "desthost %s. Using default "
1916 "smb.conf realm %s\n",
1917 dest_realm ? dest_realm : "<null>",
1918 remote_name,
1919 realm));
1922 principal = talloc_asprintf(talloc_tos(),
1923 "cifs/%s@%s",
1924 remote_name,
1925 realm);
1926 if (!principal) {
1927 SAFE_FREE(realm);
1928 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1930 DEBUG(3,("cli_session_setup_spnego: guessed "
1931 "server principal=%s\n",
1932 principal ? principal : "<null>"));
1934 SAFE_FREE(realm);
1937 if (principal) {
1938 rc = cli_session_setup_kerberos(cli, principal);
1939 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1940 TALLOC_FREE(principal);
1941 return rc;
1945 #endif
1947 TALLOC_FREE(principal);
1949 ntlmssp:
1951 account = talloc_strdup(talloc_tos(), user);
1952 if (!account) {
1953 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1956 /* when falling back to ntlmssp while authenticating with a machine
1957 * account strip off the realm - gd */
1959 if ((p = strchr_m(user, '@')) != NULL) {
1960 account[PTR_DIFF(p,user)] = '\0';
1963 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1966 /****************************************************************************
1967 Send a session setup. The username and workgroup is in UNIX character
1968 format and must be converted to DOS codepage format before sending. If the
1969 password is in plaintext, the same should be done.
1970 ****************************************************************************/
1972 NTSTATUS cli_session_setup(struct cli_state *cli,
1973 const char *user,
1974 const char *pass, int passlen,
1975 const char *ntpass, int ntpasslen,
1976 const char *workgroup)
1978 char *p;
1979 char *user2;
1980 uint16_t sec_mode = cli_state_security_mode(cli);
1982 if (user) {
1983 user2 = talloc_strdup(talloc_tos(), user);
1984 } else {
1985 user2 = talloc_strdup(talloc_tos(), "");
1987 if (user2 == NULL) {
1988 return NT_STATUS_NO_MEMORY;
1991 if (!workgroup) {
1992 workgroup = "";
1995 /* allow for workgroups as part of the username */
1996 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1997 (p=strchr_m(user2,*lp_winbind_separator()))) {
1998 *p = 0;
1999 user = p+1;
2000 strupper_m(user2);
2001 workgroup = user2;
2004 if (cli_state_protocol(cli) < PROTOCOL_LANMAN1) {
2005 return NT_STATUS_OK;
2008 /* now work out what sort of session setup we are going to
2009 do. I have split this into separate functions to make the
2010 flow a bit easier to understand (tridge) */
2012 /* if its an older server then we have to use the older request format */
2014 if (cli_state_protocol(cli) < PROTOCOL_NT1) {
2015 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2016 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2017 " or 'client ntlmv2 auth = yes'\n"));
2018 return NT_STATUS_ACCESS_DENIED;
2021 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2022 !lp_client_plaintext_auth() && (*pass)) {
2023 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2024 " or 'client ntlmv2 auth = yes'\n"));
2025 return NT_STATUS_ACCESS_DENIED;
2028 return cli_session_setup_lanman2(cli, user, pass, passlen,
2029 workgroup);
2032 /* if no user is supplied then we have to do an anonymous connection.
2033 passwords are ignored */
2035 if (!user || !*user)
2036 return cli_session_setup_guest(cli);
2038 /* if the server is share level then send a plaintext null
2039 password at this point. The password is sent in the tree
2040 connect */
2042 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2043 return cli_session_setup_plain(cli, user, "", workgroup);
2045 /* if the server doesn't support encryption then we have to use
2046 plaintext. The second password is ignored */
2048 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2049 if (!lp_client_plaintext_auth() && (*pass)) {
2050 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2051 " or 'client ntlmv2 auth = yes'\n"));
2052 return NT_STATUS_ACCESS_DENIED;
2054 return cli_session_setup_plain(cli, user, pass, workgroup);
2057 /* if the server supports extended security then use SPNEGO */
2059 if (cli_state_capabilities(cli) & CAP_EXTENDED_SECURITY) {
2060 const char *remote_realm = cli_state_remote_realm(cli);
2061 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2062 workgroup,
2063 remote_realm);
2064 if (!ADS_ERR_OK(status)) {
2065 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2066 return ads_ntstatus(status);
2068 } else {
2069 NTSTATUS status;
2071 /* otherwise do a NT1 style session setup */
2072 status = cli_session_setup_nt1(cli, user, pass, passlen,
2073 ntpass, ntpasslen, workgroup);
2074 if (!NT_STATUS_IS_OK(status)) {
2075 DEBUG(3,("cli_session_setup: NT1 session setup "
2076 "failed: %s\n", nt_errstr(status)));
2077 return status;
2081 if (strstr(cli->server_type, "Samba")) {
2082 cli->is_samba = True;
2085 return NT_STATUS_OK;
2088 /****************************************************************************
2089 Send a uloggoff.
2090 *****************************************************************************/
2092 struct cli_ulogoff_state {
2093 struct cli_state *cli;
2094 uint16_t vwv[3];
2097 static void cli_ulogoff_done(struct tevent_req *subreq);
2099 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2100 struct tevent_context *ev,
2101 struct cli_state *cli)
2103 struct tevent_req *req, *subreq;
2104 struct cli_ulogoff_state *state;
2106 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2107 if (req == NULL) {
2108 return NULL;
2110 state->cli = cli;
2112 SCVAL(state->vwv+0, 0, 0xFF);
2113 SCVAL(state->vwv+1, 0, 0);
2114 SSVAL(state->vwv+2, 0, 0);
2116 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2117 0, NULL);
2118 if (tevent_req_nomem(subreq, req)) {
2119 return tevent_req_post(req, ev);
2121 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2122 return req;
2125 static void cli_ulogoff_done(struct tevent_req *subreq)
2127 struct tevent_req *req = tevent_req_callback_data(
2128 subreq, struct tevent_req);
2129 struct cli_ulogoff_state *state = tevent_req_data(
2130 req, struct cli_ulogoff_state);
2131 NTSTATUS status;
2133 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2134 if (!NT_STATUS_IS_OK(status)) {
2135 tevent_req_nterror(req, status);
2136 return;
2138 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2139 tevent_req_done(req);
2142 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2144 return tevent_req_simple_recv_ntstatus(req);
2147 NTSTATUS cli_ulogoff(struct cli_state *cli)
2149 struct tevent_context *ev;
2150 struct tevent_req *req;
2151 NTSTATUS status = NT_STATUS_NO_MEMORY;
2153 if (cli_has_async_calls(cli)) {
2154 return NT_STATUS_INVALID_PARAMETER;
2156 ev = tevent_context_init(talloc_tos());
2157 if (ev == NULL) {
2158 goto fail;
2160 req = cli_ulogoff_send(ev, ev, cli);
2161 if (req == NULL) {
2162 goto fail;
2164 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2165 goto fail;
2167 status = cli_ulogoff_recv(req);
2168 fail:
2169 TALLOC_FREE(ev);
2170 return status;
2173 /****************************************************************************
2174 Send a tconX.
2175 ****************************************************************************/
2177 struct cli_tcon_andx_state {
2178 struct cli_state *cli;
2179 uint16_t vwv[4];
2180 struct iovec bytes;
2183 static void cli_tcon_andx_done(struct tevent_req *subreq);
2185 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2186 struct event_context *ev,
2187 struct cli_state *cli,
2188 const char *share, const char *dev,
2189 const char *pass, int passlen,
2190 struct tevent_req **psmbreq)
2192 struct tevent_req *req, *subreq;
2193 struct cli_tcon_andx_state *state;
2194 uint8_t p24[24];
2195 uint16_t *vwv;
2196 char *tmp = NULL;
2197 uint8_t *bytes;
2198 uint16_t sec_mode = cli_state_security_mode(cli);
2200 *psmbreq = NULL;
2202 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2203 if (req == NULL) {
2204 return NULL;
2206 state->cli = cli;
2207 vwv = state->vwv;
2209 cli->share = talloc_strdup(cli, share);
2210 if (!cli->share) {
2211 return NULL;
2214 /* in user level security don't send a password now */
2215 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2216 passlen = 1;
2217 pass = "";
2218 } else if (pass == NULL) {
2219 DEBUG(1, ("Server not using user level security and no "
2220 "password supplied.\n"));
2221 goto access_denied;
2224 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2225 *pass && passlen != 24) {
2226 if (!lp_client_lanman_auth()) {
2227 DEBUG(1, ("Server requested LANMAN password "
2228 "(share-level security) but "
2229 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2230 goto access_denied;
2234 * Non-encrypted passwords - convert to DOS codepage before
2235 * encryption.
2237 SMBencrypt(pass, cli->secblob.data, p24);
2238 passlen = 24;
2239 pass = (const char *)p24;
2240 } else {
2241 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2242 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2243 == 0) {
2244 uint8_t *tmp_pass;
2246 if (!lp_client_plaintext_auth() && (*pass)) {
2247 DEBUG(1, ("Server requested plaintext "
2248 "password but "
2249 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2250 goto access_denied;
2254 * Non-encrypted passwords - convert to DOS codepage
2255 * before using.
2257 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2258 if (tevent_req_nomem(tmp_pass, req)) {
2259 return tevent_req_post(req, ev);
2261 tmp_pass = trans2_bytes_push_str(tmp_pass,
2262 false, /* always DOS */
2263 pass,
2264 passlen,
2265 NULL);
2266 if (tevent_req_nomem(tmp_pass, req)) {
2267 return tevent_req_post(req, ev);
2269 pass = (const char *)tmp_pass;
2270 passlen = talloc_get_size(tmp_pass);
2274 SCVAL(vwv+0, 0, 0xFF);
2275 SCVAL(vwv+0, 1, 0);
2276 SSVAL(vwv+1, 0, 0);
2277 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2278 SSVAL(vwv+3, 0, passlen);
2280 if (passlen && pass) {
2281 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2282 } else {
2283 bytes = talloc_array(state, uint8_t, 0);
2287 * Add the sharename
2289 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2290 cli_state_remote_name(cli), share);
2291 if (tmp == NULL) {
2292 TALLOC_FREE(req);
2293 return NULL;
2295 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2296 NULL);
2297 TALLOC_FREE(tmp);
2300 * Add the devicetype
2302 tmp = talloc_strdup_upper(talloc_tos(), dev);
2303 if (tmp == NULL) {
2304 TALLOC_FREE(req);
2305 return NULL;
2307 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2308 TALLOC_FREE(tmp);
2310 if (bytes == NULL) {
2311 TALLOC_FREE(req);
2312 return NULL;
2315 state->bytes.iov_base = (void *)bytes;
2316 state->bytes.iov_len = talloc_get_size(bytes);
2318 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2319 1, &state->bytes);
2320 if (subreq == NULL) {
2321 TALLOC_FREE(req);
2322 return NULL;
2324 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2325 *psmbreq = subreq;
2326 return req;
2328 access_denied:
2329 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2330 return tevent_req_post(req, ev);
2333 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2334 struct event_context *ev,
2335 struct cli_state *cli,
2336 const char *share, const char *dev,
2337 const char *pass, int passlen)
2339 struct tevent_req *req, *subreq;
2340 NTSTATUS status;
2342 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2343 &subreq);
2344 if (req == NULL) {
2345 return NULL;
2347 if (subreq == NULL) {
2348 return req;
2350 status = cli_smb_req_send(subreq);
2351 if (!NT_STATUS_IS_OK(status)) {
2352 tevent_req_nterror(req, status);
2353 return tevent_req_post(req, ev);
2355 return req;
2358 static void cli_tcon_andx_done(struct tevent_req *subreq)
2360 struct tevent_req *req = tevent_req_callback_data(
2361 subreq, struct tevent_req);
2362 struct cli_tcon_andx_state *state = tevent_req_data(
2363 req, struct cli_tcon_andx_state);
2364 struct cli_state *cli = state->cli;
2365 uint8_t *in;
2366 char *inbuf;
2367 uint8_t wct;
2368 uint16_t *vwv;
2369 uint32_t num_bytes;
2370 uint8_t *bytes;
2371 NTSTATUS status;
2373 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2374 &num_bytes, &bytes);
2375 TALLOC_FREE(subreq);
2376 if (!NT_STATUS_IS_OK(status)) {
2377 tevent_req_nterror(req, status);
2378 return;
2381 inbuf = (char *)in;
2383 if (num_bytes) {
2384 if (clistr_pull_talloc(cli,
2385 inbuf,
2386 SVAL(inbuf, smb_flg2),
2387 &cli->dev,
2388 bytes,
2389 num_bytes,
2390 STR_TERMINATE|STR_ASCII) == -1) {
2391 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2392 return;
2394 } else {
2395 cli->dev = talloc_strdup(cli, "");
2396 if (cli->dev == NULL) {
2397 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2398 return;
2402 if ((cli_state_protocol(cli) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2403 /* almost certainly win95 - enable bug fixes */
2404 cli->win95 = True;
2408 * Make sure that we have the optional support 16-bit field. WCT > 2.
2409 * Avoids issues when connecting to Win9x boxes sharing files
2412 cli->dfsroot = false;
2414 if ((wct > 2) && (cli_state_protocol(cli) >= PROTOCOL_LANMAN2)) {
2415 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2418 cli->smb1.tid = SVAL(inbuf,smb_tid);
2419 tevent_req_done(req);
2422 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2424 return tevent_req_simple_recv_ntstatus(req);
2427 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2428 const char *dev, const char *pass, int passlen)
2430 TALLOC_CTX *frame = talloc_stackframe();
2431 struct event_context *ev;
2432 struct tevent_req *req;
2433 NTSTATUS status = NT_STATUS_OK;
2435 if (cli_has_async_calls(cli)) {
2437 * Can't use sync call while an async call is in flight
2439 status = NT_STATUS_INVALID_PARAMETER;
2440 goto fail;
2443 ev = event_context_init(frame);
2444 if (ev == NULL) {
2445 status = NT_STATUS_NO_MEMORY;
2446 goto fail;
2449 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2450 if (req == NULL) {
2451 status = NT_STATUS_NO_MEMORY;
2452 goto fail;
2455 if (!tevent_req_poll(req, ev)) {
2456 status = map_nt_error_from_unix(errno);
2457 goto fail;
2460 status = cli_tcon_andx_recv(req);
2461 fail:
2462 TALLOC_FREE(frame);
2463 return status;
2466 /****************************************************************************
2467 Send a tree disconnect.
2468 ****************************************************************************/
2470 struct cli_tdis_state {
2471 struct cli_state *cli;
2474 static void cli_tdis_done(struct tevent_req *subreq);
2476 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2477 struct tevent_context *ev,
2478 struct cli_state *cli)
2480 struct tevent_req *req, *subreq;
2481 struct cli_tdis_state *state;
2483 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2484 if (req == NULL) {
2485 return NULL;
2487 state->cli = cli;
2489 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2490 if (tevent_req_nomem(subreq, req)) {
2491 return tevent_req_post(req, ev);
2493 tevent_req_set_callback(subreq, cli_tdis_done, req);
2494 return req;
2497 static void cli_tdis_done(struct tevent_req *subreq)
2499 struct tevent_req *req = tevent_req_callback_data(
2500 subreq, struct tevent_req);
2501 struct cli_tdis_state *state = tevent_req_data(
2502 req, struct cli_tdis_state);
2503 NTSTATUS status;
2505 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2506 TALLOC_FREE(subreq);
2507 if (!NT_STATUS_IS_OK(status)) {
2508 tevent_req_nterror(req, status);
2509 return;
2511 state->cli->smb1.tid = UINT16_MAX;
2512 tevent_req_done(req);
2515 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2517 return tevent_req_simple_recv_ntstatus(req);
2520 NTSTATUS cli_tdis(struct cli_state *cli)
2522 struct tevent_context *ev;
2523 struct tevent_req *req;
2524 NTSTATUS status = NT_STATUS_NO_MEMORY;
2526 if (cli_has_async_calls(cli)) {
2527 return NT_STATUS_INVALID_PARAMETER;
2529 ev = tevent_context_init(talloc_tos());
2530 if (ev == NULL) {
2531 goto fail;
2533 req = cli_tdis_send(ev, ev, cli);
2534 if (req == NULL) {
2535 goto fail;
2537 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2538 goto fail;
2540 status = cli_tdis_recv(req);
2541 fail:
2542 TALLOC_FREE(ev);
2543 return status;
2546 /****************************************************************************
2547 Send a negprot command.
2548 ****************************************************************************/
2550 struct cli_negprot_state {
2551 struct cli_state *cli;
2554 static void cli_negprot_done(struct tevent_req *subreq);
2556 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2557 struct event_context *ev,
2558 struct cli_state *cli)
2560 struct tevent_req *req, *subreq;
2561 struct cli_negprot_state *state;
2562 uint8_t *bytes = NULL;
2563 int numprots;
2565 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2566 if (req == NULL) {
2567 return NULL;
2569 state->cli = cli;
2571 if (cli_state_protocol(cli) < PROTOCOL_NT1)
2572 cli->use_spnego = False;
2574 /* setup the protocol strings */
2575 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2576 uint8_t c = 2;
2577 if (prots[numprots].prot > cli_state_protocol(cli)) {
2578 break;
2580 bytes = (uint8_t *)talloc_append_blob(
2581 state, bytes, data_blob_const(&c, sizeof(c)));
2582 if (tevent_req_nomem(bytes, req)) {
2583 return tevent_req_post(req, ev);
2585 bytes = smb_bytes_push_str(bytes, false,
2586 prots[numprots].name,
2587 strlen(prots[numprots].name)+1,
2588 NULL);
2589 if (tevent_req_nomem(bytes, req)) {
2590 return tevent_req_post(req, ev);
2594 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2595 talloc_get_size(bytes), bytes);
2597 if (tevent_req_nomem(subreq, req)) {
2598 return tevent_req_post(req, ev);
2600 tevent_req_set_callback(subreq, cli_negprot_done, req);
2601 return req;
2604 static void cli_negprot_done(struct tevent_req *subreq)
2606 struct tevent_req *req = tevent_req_callback_data(
2607 subreq, struct tevent_req);
2608 struct cli_negprot_state *state = tevent_req_data(
2609 req, struct cli_negprot_state);
2610 struct cli_state *cli = state->cli;
2611 uint8_t wct;
2612 uint16_t *vwv;
2613 uint32_t num_bytes;
2614 uint8_t *bytes;
2615 NTSTATUS status;
2616 uint16_t protnum;
2617 uint8_t *inbuf;
2619 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2620 &num_bytes, &bytes);
2621 TALLOC_FREE(subreq);
2622 if (!NT_STATUS_IS_OK(status)) {
2623 tevent_req_nterror(req, status);
2624 return;
2627 protnum = SVAL(vwv, 0);
2629 if ((protnum >= ARRAY_SIZE(prots))
2630 || (prots[protnum].prot > cli_state_protocol(cli))) {
2631 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2632 return;
2635 cli->protocol = prots[protnum].prot;
2637 if ((cli_state_protocol(cli) < PROTOCOL_NT1) &&
2638 client_is_signing_mandatory(cli)) {
2639 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2640 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2641 return;
2644 if (cli_state_protocol(cli) >= PROTOCOL_NT1) {
2645 struct timespec ts;
2646 bool negotiated_smb_signing = false;
2648 if (wct != 0x11) {
2649 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2650 return;
2653 /* NT protocol */
2654 cli->sec_mode = CVAL(vwv + 1, 0);
2655 cli->max_mux = SVAL(vwv + 1, 1);
2656 cli->max_xmit = IVAL(vwv + 3, 1);
2657 cli->sesskey = IVAL(vwv + 7, 1);
2658 cli->serverzone = SVALS(vwv + 15, 1);
2659 cli->serverzone *= 60;
2660 /* this time arrives in real GMT */
2661 ts = interpret_long_date(((char *)(vwv+11))+1);
2662 cli->servertime = ts.tv_sec;
2663 cli->secblob = data_blob(bytes, num_bytes);
2664 cli->capabilities = IVAL(vwv + 9, 1);
2665 if (cli_state_capabilities(cli) & CAP_RAW_MODE) {
2666 cli->readbraw_supported = True;
2667 cli->writebraw_supported = True;
2669 /* work out if they sent us a workgroup */
2670 if (!(cli_state_capabilities(cli) & CAP_EXTENDED_SECURITY) &&
2671 smb_buflen(inbuf) > 8) {
2672 ssize_t ret;
2673 status = smb_bytes_talloc_string(
2674 cli, (char *)inbuf, &cli->server_domain,
2675 bytes + 8, num_bytes - 8, &ret);
2676 if (tevent_req_nterror(req, status)) {
2677 return;
2682 * As signing is slow we only turn it on if either the client or
2683 * the server require it. JRA.
2686 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2687 /* Fail if server says signing is mandatory and we don't want to support it. */
2688 if (!client_is_signing_allowed(cli)) {
2689 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2690 tevent_req_nterror(req,
2691 NT_STATUS_ACCESS_DENIED);
2692 return;
2694 negotiated_smb_signing = true;
2695 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2696 /* Fail if client says signing is mandatory and the server doesn't support it. */
2697 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2698 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2699 tevent_req_nterror(req,
2700 NT_STATUS_ACCESS_DENIED);
2701 return;
2703 negotiated_smb_signing = true;
2704 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2705 negotiated_smb_signing = true;
2708 if (negotiated_smb_signing) {
2709 cli_set_signing_negotiated(cli);
2712 } else if (cli_state_protocol(cli) >= PROTOCOL_LANMAN1) {
2713 if (wct != 0x0D) {
2714 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2715 return;
2718 cli->use_spnego = False;
2719 cli->sec_mode = SVAL(vwv + 1, 0);
2720 cli->max_xmit = SVAL(vwv + 2, 0);
2721 cli->max_mux = SVAL(vwv + 3, 0);
2722 cli->sesskey = IVAL(vwv + 6, 0);
2723 cli->serverzone = SVALS(vwv + 10, 0);
2724 cli->serverzone *= 60;
2725 /* this time is converted to GMT by make_unix_date */
2726 cli->servertime = make_unix_date(
2727 (char *)(vwv + 8), cli->serverzone);
2728 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2729 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2730 cli->secblob = data_blob(bytes, num_bytes);
2731 } else {
2732 /* the old core protocol */
2733 cli->use_spnego = False;
2734 cli->sec_mode = 0;
2735 cli->serverzone = get_time_zone(time(NULL));
2736 cli->max_xmit = 1024;
2737 cli->max_mux = 1;
2740 if (cli->max_xmit < 1024) {
2741 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2742 return;
2745 if (cli->max_mux < 1) {
2746 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2747 return;
2750 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2752 /* a way to force ascii SMB */
2753 if (cli->force_ascii) {
2754 cli->capabilities &= ~CAP_UNICODE;
2757 tevent_req_done(req);
2760 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2762 return tevent_req_simple_recv_ntstatus(req);
2765 NTSTATUS cli_negprot(struct cli_state *cli)
2767 TALLOC_CTX *frame = talloc_stackframe();
2768 struct event_context *ev;
2769 struct tevent_req *req;
2770 NTSTATUS status = NT_STATUS_OK;
2772 if (cli_has_async_calls(cli)) {
2774 * Can't use sync call while an async call is in flight
2776 status = NT_STATUS_INVALID_PARAMETER;
2777 goto fail;
2780 ev = event_context_init(frame);
2781 if (ev == NULL) {
2782 status = NT_STATUS_NO_MEMORY;
2783 goto fail;
2786 req = cli_negprot_send(frame, ev, cli);
2787 if (req == NULL) {
2788 status = NT_STATUS_NO_MEMORY;
2789 goto fail;
2792 if (!tevent_req_poll(req, ev)) {
2793 status = map_nt_error_from_unix(errno);
2794 goto fail;
2797 status = cli_negprot_recv(req);
2798 fail:
2799 TALLOC_FREE(frame);
2800 return status;
2803 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2804 const struct sockaddr_storage *pss,
2805 const char *myname, uint16_t port,
2806 int sec_timeout, int *pfd, uint16_t *pport)
2808 TALLOC_CTX *frame = talloc_stackframe();
2809 const char *prog;
2810 unsigned int i, num_addrs;
2811 const char **called_names;
2812 const char **calling_names;
2813 int *called_types;
2814 NTSTATUS status;
2815 int fd;
2817 prog = getenv("LIBSMB_PROG");
2818 if (prog != NULL) {
2819 fd = sock_exec(prog);
2820 if (fd == -1) {
2821 return map_nt_error_from_unix(errno);
2823 port = 0;
2824 goto done;
2827 if ((pss == NULL) || is_zero_addr(pss)) {
2828 struct sockaddr_storage *addrs;
2829 status = resolve_name_list(talloc_tos(), host, name_type,
2830 &addrs, &num_addrs);
2831 if (!NT_STATUS_IS_OK(status)) {
2832 goto fail;
2834 pss = addrs;
2835 } else {
2836 num_addrs = 1;
2839 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2840 if (called_names == NULL) {
2841 status = NT_STATUS_NO_MEMORY;
2842 goto fail;
2844 called_types = talloc_array(talloc_tos(), int, num_addrs);
2845 if (called_types == NULL) {
2846 status = NT_STATUS_NO_MEMORY;
2847 goto fail;
2849 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2850 if (calling_names == NULL) {
2851 status = NT_STATUS_NO_MEMORY;
2852 goto fail;
2854 for (i=0; i<num_addrs; i++) {
2855 called_names[i] = host;
2856 called_types[i] = name_type;
2857 calling_names[i] = myname;
2859 status = smbsock_any_connect(pss, called_names, called_types,
2860 calling_names, NULL, num_addrs, port,
2861 sec_timeout, &fd, NULL, &port);
2862 if (!NT_STATUS_IS_OK(status)) {
2863 goto fail;
2865 set_socket_options(fd, lp_socket_options());
2866 done:
2867 *pfd = fd;
2868 *pport = port;
2869 status = NT_STATUS_OK;
2870 fail:
2871 TALLOC_FREE(frame);
2872 return status;
2875 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2876 uint16_t port, int name_type, const char *myname,
2877 int signing_state, int flags, struct cli_state **pcli)
2879 TALLOC_CTX *frame = talloc_stackframe();
2880 struct cli_state *cli;
2881 NTSTATUS status = NT_STATUS_NO_MEMORY;
2882 int fd = -1;
2883 char *desthost;
2884 char *p;
2886 desthost = talloc_strdup(talloc_tos(), host);
2887 if (desthost == NULL) {
2888 goto fail;
2891 p = strchr(host, '#');
2892 if (p != NULL) {
2893 name_type = strtol(p+1, NULL, 16);
2894 host = talloc_strndup(talloc_tos(), host, p - host);
2895 if (host == NULL) {
2896 goto fail;
2900 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
2901 20, &fd, &port);
2902 if (!NT_STATUS_IS_OK(status)) {
2903 goto fail;
2906 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
2907 if (cli == NULL) {
2908 goto fail;
2911 *pcli = cli;
2912 status = NT_STATUS_OK;
2913 fail:
2914 TALLOC_FREE(frame);
2915 return status;
2919 establishes a connection to after the negprot.
2920 @param output_cli A fully initialised cli structure, non-null only on success
2921 @param dest_host The netbios name of the remote host
2922 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2923 @param port (optional) The destination port (0 for default)
2925 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2926 const char *my_name,
2927 const char *dest_host,
2928 const struct sockaddr_storage *dest_ss, int port,
2929 int signing_state, int flags)
2931 NTSTATUS nt_status;
2932 struct cli_state *cli;
2934 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2935 signing_state, flags, &cli);
2936 if (!NT_STATUS_IS_OK(nt_status)) {
2937 DEBUG(10, ("cli_connect_nb failed: %s\n",
2938 nt_errstr(nt_status)));
2939 return nt_status;
2942 nt_status = cli_negprot(cli);
2943 if (!NT_STATUS_IS_OK(nt_status)) {
2944 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2945 cli_shutdown(cli);
2946 return nt_status;
2949 *output_cli = cli;
2950 return NT_STATUS_OK;
2955 establishes a connection right up to doing tconX, password specified.
2956 @param output_cli A fully initialised cli structure, non-null only on success
2957 @param dest_host The netbios name of the remote host
2958 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2959 @param port (optional) The destination port (0 for default)
2960 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2961 @param service_type The 'type' of serivice.
2962 @param user Username, unix string
2963 @param domain User's domain
2964 @param password User's password, unencrypted unix string.
2967 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2968 const char *my_name,
2969 const char *dest_host,
2970 const struct sockaddr_storage *dest_ss, int port,
2971 const char *service, const char *service_type,
2972 const char *user, const char *domain,
2973 const char *password, int flags,
2974 int signing_state)
2976 NTSTATUS nt_status;
2977 struct cli_state *cli = NULL;
2978 int pw_len = password ? strlen(password)+1 : 0;
2980 *output_cli = NULL;
2982 if (password == NULL) {
2983 password = "";
2986 nt_status = cli_start_connection(&cli, my_name, dest_host,
2987 dest_ss, port, signing_state,
2988 flags);
2990 if (!NT_STATUS_IS_OK(nt_status)) {
2991 return nt_status;
2994 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2995 pw_len, domain);
2996 if (!NT_STATUS_IS_OK(nt_status)) {
2998 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2999 DEBUG(1,("failed session setup with %s\n",
3000 nt_errstr(nt_status)));
3001 cli_shutdown(cli);
3002 return nt_status;
3005 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3006 if (!NT_STATUS_IS_OK(nt_status)) {
3007 DEBUG(1,("anonymous failed session setup with %s\n",
3008 nt_errstr(nt_status)));
3009 cli_shutdown(cli);
3010 return nt_status;
3014 if (service) {
3015 nt_status = cli_tcon_andx(cli, service, service_type, password,
3016 pw_len);
3017 if (!NT_STATUS_IS_OK(nt_status)) {
3018 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3019 cli_shutdown(cli);
3020 if (NT_STATUS_IS_OK(nt_status)) {
3021 nt_status = NT_STATUS_UNSUCCESSFUL;
3023 return nt_status;
3027 nt_status = cli_init_creds(cli, user, domain, password);
3028 if (!NT_STATUS_IS_OK(nt_status)) {
3029 cli_shutdown(cli);
3030 return nt_status;
3033 *output_cli = cli;
3034 return NT_STATUS_OK;
3037 /****************************************************************************
3038 Send an old style tcon.
3039 ****************************************************************************/
3040 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3041 const char *service, const char *pass, const char *dev,
3042 uint16 *max_xmit, uint16 *tid)
3044 struct tevent_req *req;
3045 uint16_t *ret_vwv;
3046 uint8_t *bytes;
3047 NTSTATUS status;
3049 if (!lp_client_plaintext_auth() && (*pass)) {
3050 DEBUG(1, ("Server requested plaintext password but 'client "
3051 "plaintext auth' is disabled\n"));
3052 return NT_STATUS_ACCESS_DENIED;
3055 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3056 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3057 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3058 service, strlen(service)+1, NULL);
3059 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3060 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3061 pass, strlen(pass)+1, NULL);
3062 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3063 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3064 dev, strlen(dev)+1, NULL);
3066 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3067 talloc_get_size(bytes), bytes, &req,
3068 2, NULL, &ret_vwv, NULL, NULL);
3069 if (!NT_STATUS_IS_OK(status)) {
3070 return status;
3073 *max_xmit = SVAL(ret_vwv + 0, 0);
3074 *tid = SVAL(ret_vwv + 1, 0);
3076 return NT_STATUS_OK;
3079 /* Return a cli_state pointing at the IPC$ share for the given server */
3081 struct cli_state *get_ipc_connect(char *server,
3082 struct sockaddr_storage *server_ss,
3083 const struct user_auth_info *user_info)
3085 struct cli_state *cli;
3086 NTSTATUS nt_status;
3087 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3089 if (user_info->use_kerberos) {
3090 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3093 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3094 user_info->username ? user_info->username : "",
3095 lp_workgroup(),
3096 user_info->password ? user_info->password : "",
3097 flags,
3098 Undefined);
3100 if (NT_STATUS_IS_OK(nt_status)) {
3101 return cli;
3102 } else if (is_ipaddress(server)) {
3103 /* windows 9* needs a correct NMB name for connections */
3104 fstring remote_name;
3106 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3107 cli = get_ipc_connect(remote_name, server_ss, user_info);
3108 if (cli)
3109 return cli;
3112 return NULL;
3116 * Given the IP address of a master browser on the network, return its
3117 * workgroup and connect to it.
3119 * This function is provided to allow additional processing beyond what
3120 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3121 * browsers and obtain each master browsers' list of domains (in case the
3122 * first master browser is recently on the network and has not yet
3123 * synchronized with other master browsers and therefore does not yet have the
3124 * entire network browse list)
3127 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3128 struct sockaddr_storage *mb_ip,
3129 const struct user_auth_info *user_info,
3130 char **pp_workgroup_out)
3132 char addr[INET6_ADDRSTRLEN];
3133 fstring name;
3134 struct cli_state *cli;
3135 struct sockaddr_storage server_ss;
3137 *pp_workgroup_out = NULL;
3139 print_sockaddr(addr, sizeof(addr), mb_ip);
3140 DEBUG(99, ("Looking up name of master browser %s\n",
3141 addr));
3144 * Do a name status query to find out the name of the master browser.
3145 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3146 * master browser will not respond to a wildcard query (or, at least,
3147 * an NT4 server acting as the domain master browser will not).
3149 * We might be able to use ONLY the query on MSBROWSE, but that's not
3150 * yet been tested with all Windows versions, so until it is, leave
3151 * the original wildcard query as the first choice and fall back to
3152 * MSBROWSE if the wildcard query fails.
3154 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3155 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3157 DEBUG(99, ("Could not retrieve name status for %s\n",
3158 addr));
3159 return NULL;
3162 if (!find_master_ip(name, &server_ss)) {
3163 DEBUG(99, ("Could not find master ip for %s\n", name));
3164 return NULL;
3167 *pp_workgroup_out = talloc_strdup(ctx, name);
3169 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3171 print_sockaddr(addr, sizeof(addr), &server_ss);
3172 cli = get_ipc_connect(addr, &server_ss, user_info);
3174 return cli;
3178 * Return the IP address and workgroup of a master browser on the network, and
3179 * connect to it.
3182 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3183 const struct user_auth_info *user_info,
3184 char **pp_workgroup_out)
3186 struct sockaddr_storage *ip_list;
3187 struct cli_state *cli;
3188 int i, count;
3189 NTSTATUS status;
3191 *pp_workgroup_out = NULL;
3193 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3195 /* Go looking for workgroups by broadcasting on the local network */
3197 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3198 &ip_list, &count);
3199 if (!NT_STATUS_IS_OK(status)) {
3200 DEBUG(99, ("No master browsers responded: %s\n",
3201 nt_errstr(status)));
3202 return False;
3205 for (i = 0; i < count; i++) {
3206 char addr[INET6_ADDRSTRLEN];
3207 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3208 DEBUG(99, ("Found master browser %s\n", addr));
3210 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3211 user_info, pp_workgroup_out);
3212 if (cli)
3213 return(cli);
3216 return NULL;