s3:torture:delete: simplify return code handling, fixing a couple of return codes...
[Samba.git] / source3 / libsmb / cliconnect.c
blobcd914bf8529336d6171f89582f77281cec389431
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 "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "../auth/ntlmssp/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 "librpc/ndr/libndr.h"
36 #include "../libcli/smb/smbXcli_base.h"
37 #include "smb2cli.h"
39 #define STAR_SMBSERVER "*SMBSERVER"
41 /********************************************************
42 Utility function to ensure we always return at least
43 a valid char * pointer to an empty string for the
44 cli->server_os, cli->server_type and cli->server_domain
45 strings.
46 *******************************************************/
48 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
49 const uint8_t *hdr,
50 char **dest,
51 uint8_t *src,
52 size_t srclen,
53 ssize_t *destlen)
55 *destlen = clistr_pull_talloc(mem_ctx,
56 (const char *)hdr,
57 SVAL(hdr, HDR_FLG2),
58 dest,
59 (char *)src,
60 srclen,
61 STR_TERMINATE);
62 if (*destlen == -1) {
63 return NT_STATUS_NO_MEMORY;
66 if (*dest == NULL) {
67 *dest = talloc_strdup(mem_ctx, "");
68 if (*dest == NULL) {
69 return NT_STATUS_NO_MEMORY;
72 return NT_STATUS_OK;
75 /****************************************************************************
76 Do an old lanman2 style session setup.
77 ****************************************************************************/
79 struct cli_session_setup_lanman2_state {
80 struct cli_state *cli;
81 uint16_t vwv[10];
82 const char *user;
85 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
87 static struct tevent_req *cli_session_setup_lanman2_send(
88 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
89 struct cli_state *cli, const char *user,
90 const char *pass, size_t passlen,
91 const char *workgroup)
93 struct tevent_req *req, *subreq;
94 struct cli_session_setup_lanman2_state *state;
95 DATA_BLOB lm_response = data_blob_null;
96 uint16_t *vwv;
97 uint8_t *bytes;
98 char *tmp;
99 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
101 req = tevent_req_create(mem_ctx, &state,
102 struct cli_session_setup_lanman2_state);
103 if (req == NULL) {
104 return NULL;
106 state->cli = cli;
107 state->user = user;
108 vwv = state->vwv;
111 * if in share level security then don't send a password now
113 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
114 passlen = 0;
117 if (passlen > 0
118 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
119 && passlen != 24) {
121 * Encrypted mode needed, and non encrypted password
122 * supplied.
124 lm_response = data_blob(NULL, 24);
125 if (tevent_req_nomem(lm_response.data, req)) {
126 return tevent_req_post(req, ev);
129 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
130 (uint8_t *)lm_response.data)) {
131 DEBUG(1, ("Password is > 14 chars in length, and is "
132 "therefore incompatible with Lanman "
133 "authentication\n"));
134 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
135 return tevent_req_post(req, ev);
137 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
138 && passlen == 24) {
140 * Encrypted mode needed, and encrypted password
141 * supplied.
143 lm_response = data_blob(pass, passlen);
144 if (tevent_req_nomem(lm_response.data, req)) {
145 return tevent_req_post(req, ev);
147 } else if (passlen > 0) {
148 uint8_t *buf;
149 size_t converted_size;
151 * Plaintext mode needed, assume plaintext supplied.
153 buf = talloc_array(talloc_tos(), uint8_t, 0);
154 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
155 &converted_size);
156 if (tevent_req_nomem(buf, req)) {
157 return tevent_req_post(req, ev);
159 lm_response = data_blob(pass, passlen);
160 TALLOC_FREE(buf);
161 if (tevent_req_nomem(lm_response.data, req)) {
162 return tevent_req_post(req, ev);
166 SCVAL(vwv+0, 0, 0xff);
167 SCVAL(vwv+0, 1, 0);
168 SSVAL(vwv+1, 0, 0);
169 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
170 SSVAL(vwv+3, 0, 2);
171 SSVAL(vwv+4, 0, 1);
172 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
173 SSVAL(vwv+7, 0, lm_response.length);
175 bytes = talloc_array(state, uint8_t, lm_response.length);
176 if (tevent_req_nomem(bytes, req)) {
177 return tevent_req_post(req, ev);
179 if (lm_response.length != 0) {
180 memcpy(bytes, lm_response.data, lm_response.length);
182 data_blob_free(&lm_response);
184 tmp = talloc_strdup_upper(talloc_tos(), user);
185 if (tevent_req_nomem(tmp, req)) {
186 return tevent_req_post(req, ev);
188 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
189 NULL);
190 TALLOC_FREE(tmp);
192 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
193 if (tevent_req_nomem(tmp, req)) {
194 return tevent_req_post(req, ev);
196 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
197 NULL);
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
199 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
201 if (tevent_req_nomem(bytes, req)) {
202 return tevent_req_post(req, ev);
205 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
206 talloc_get_size(bytes), bytes);
207 if (tevent_req_nomem(subreq, req)) {
208 return tevent_req_post(req, ev);
210 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
211 return req;
214 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
216 struct tevent_req *req = tevent_req_callback_data(
217 subreq, struct tevent_req);
218 struct cli_session_setup_lanman2_state *state = tevent_req_data(
219 req, struct cli_session_setup_lanman2_state);
220 struct cli_state *cli = state->cli;
221 uint32_t num_bytes;
222 uint8_t *in;
223 uint8_t *inhdr;
224 uint8_t *bytes;
225 uint8_t *p;
226 NTSTATUS status;
227 ssize_t ret;
228 uint8_t wct;
229 uint16_t *vwv;
231 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
232 &num_bytes, &bytes);
233 TALLOC_FREE(subreq);
234 if (!NT_STATUS_IS_OK(status)) {
235 tevent_req_nterror(req, status);
236 return;
239 inhdr = in + NBT_HDR_SIZE;
240 p = bytes;
242 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
243 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
245 status = smb_bytes_talloc_string(cli,
246 inhdr,
247 &cli->server_os,
249 bytes+num_bytes-p,
250 &ret);
252 if (!NT_STATUS_IS_OK(status)) {
253 tevent_req_nterror(req, status);
254 return;
256 p += ret;
258 status = smb_bytes_talloc_string(cli,
259 inhdr,
260 &cli->server_type,
262 bytes+num_bytes-p,
263 &ret);
265 if (!NT_STATUS_IS_OK(status)) {
266 tevent_req_nterror(req, status);
267 return;
269 p += ret;
271 status = smb_bytes_talloc_string(cli,
272 inhdr,
273 &cli->server_domain,
275 bytes+num_bytes-p,
276 &ret);
278 if (!NT_STATUS_IS_OK(status)) {
279 tevent_req_nterror(req, status);
280 return;
282 p += ret;
284 status = cli_set_username(cli, state->user);
285 if (tevent_req_nterror(req, status)) {
286 return;
288 tevent_req_done(req);
291 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
293 return tevent_req_simple_recv_ntstatus(req);
296 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
297 const char *pass, size_t passlen,
298 const char *workgroup)
300 TALLOC_CTX *frame = talloc_stackframe();
301 struct event_context *ev;
302 struct tevent_req *req;
303 NTSTATUS status = NT_STATUS_NO_MEMORY;
305 if (smbXcli_conn_has_async_calls(cli->conn)) {
307 * Can't use sync call while an async call is in flight
309 status = NT_STATUS_INVALID_PARAMETER;
310 goto fail;
312 ev = event_context_init(frame);
313 if (ev == NULL) {
314 goto fail;
316 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
317 workgroup);
318 if (req == NULL) {
319 goto fail;
321 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
322 goto fail;
324 status = cli_session_setup_lanman2_recv(req);
325 fail:
326 TALLOC_FREE(frame);
327 return status;
330 /****************************************************************************
331 Work out suitable capabilities to offer the server.
332 ****************************************************************************/
334 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
335 uint32_t sesssetup_capabilities)
337 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
340 * We only send capabilities based on the mask for:
341 * - client only flags
342 * - flags used in both directions
344 * We do not echo the server only flags.
346 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_CLIENT_MASK);
349 * Session Setup specific flags CAP_DYNAMIC_REAUTH
350 * and CAP_EXTENDED_SECURITY are passed by the caller.
351 * We need that in order to do guest logins even if
352 * CAP_EXTENDED_SECURITY is negotiated.
354 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
355 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
356 client_capabilities |= sesssetup_capabilities;
358 return client_capabilities;
361 /****************************************************************************
362 Do a NT1 guest session setup.
363 ****************************************************************************/
365 struct cli_session_setup_guest_state {
366 struct cli_state *cli;
367 uint16_t vwv[13];
368 struct iovec bytes;
371 static void cli_session_setup_guest_done(struct tevent_req *subreq);
373 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
374 struct event_context *ev,
375 struct cli_state *cli,
376 struct tevent_req **psmbreq)
378 struct tevent_req *req, *subreq;
379 struct cli_session_setup_guest_state *state;
380 uint16_t *vwv;
381 uint8_t *bytes;
383 req = tevent_req_create(mem_ctx, &state,
384 struct cli_session_setup_guest_state);
385 if (req == NULL) {
386 return NULL;
388 state->cli = cli;
389 vwv = state->vwv;
391 SCVAL(vwv+0, 0, 0xFF);
392 SCVAL(vwv+0, 1, 0);
393 SSVAL(vwv+1, 0, 0);
394 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
395 SSVAL(vwv+3, 0, 2);
396 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
397 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
398 SSVAL(vwv+7, 0, 0);
399 SSVAL(vwv+8, 0, 0);
400 SSVAL(vwv+9, 0, 0);
401 SSVAL(vwv+10, 0, 0);
402 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
404 bytes = talloc_array(state, uint8_t, 0);
406 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
407 NULL);
408 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
409 NULL);
410 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
411 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
413 if (bytes == NULL) {
414 TALLOC_FREE(req);
415 return NULL;
418 state->bytes.iov_base = (void *)bytes;
419 state->bytes.iov_len = talloc_get_size(bytes);
421 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
422 1, &state->bytes);
423 if (subreq == NULL) {
424 TALLOC_FREE(req);
425 return NULL;
427 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
428 *psmbreq = subreq;
429 return req;
432 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
433 struct event_context *ev,
434 struct cli_state *cli)
436 struct tevent_req *req, *subreq;
437 NTSTATUS status;
439 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
440 if (req == NULL) {
441 return NULL;
444 status = smb1cli_req_chain_submit(&subreq, 1);
445 if (NT_STATUS_IS_OK(status)) {
446 tevent_req_nterror(req, status);
447 return tevent_req_post(req, ev);
449 return req;
452 static void cli_session_setup_guest_done(struct tevent_req *subreq)
454 struct tevent_req *req = tevent_req_callback_data(
455 subreq, struct tevent_req);
456 struct cli_session_setup_guest_state *state = tevent_req_data(
457 req, struct cli_session_setup_guest_state);
458 struct cli_state *cli = state->cli;
459 uint32_t num_bytes;
460 uint8_t *in;
461 uint8_t *inhdr;
462 uint8_t *bytes;
463 uint8_t *p;
464 NTSTATUS status;
465 ssize_t ret;
466 uint8_t wct;
467 uint16_t *vwv;
469 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
470 &num_bytes, &bytes);
471 TALLOC_FREE(subreq);
472 if (!NT_STATUS_IS_OK(status)) {
473 tevent_req_nterror(req, status);
474 return;
477 inhdr = in + NBT_HDR_SIZE;
478 p = bytes;
480 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
481 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
483 status = smb_bytes_talloc_string(cli,
484 inhdr,
485 &cli->server_os,
487 bytes+num_bytes-p,
488 &ret);
490 if (!NT_STATUS_IS_OK(status)) {
491 tevent_req_nterror(req, status);
492 return;
494 p += ret;
496 status = smb_bytes_talloc_string(cli,
497 inhdr,
498 &cli->server_type,
500 bytes+num_bytes-p,
501 &ret);
503 if (!NT_STATUS_IS_OK(status)) {
504 tevent_req_nterror(req, status);
505 return;
507 p += ret;
509 status = smb_bytes_talloc_string(cli,
510 inhdr,
511 &cli->server_domain,
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 = cli_set_username(cli, "");
523 if (!NT_STATUS_IS_OK(status)) {
524 tevent_req_nterror(req, status);
525 return;
527 tevent_req_done(req);
530 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
532 return tevent_req_simple_recv_ntstatus(req);
535 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
537 TALLOC_CTX *frame = talloc_stackframe();
538 struct event_context *ev;
539 struct tevent_req *req;
540 NTSTATUS status = NT_STATUS_OK;
542 if (smbXcli_conn_has_async_calls(cli->conn)) {
544 * Can't use sync call while an async call is in flight
546 status = NT_STATUS_INVALID_PARAMETER;
547 goto fail;
550 ev = event_context_init(frame);
551 if (ev == NULL) {
552 status = NT_STATUS_NO_MEMORY;
553 goto fail;
556 req = cli_session_setup_guest_send(frame, ev, cli);
557 if (req == NULL) {
558 status = NT_STATUS_NO_MEMORY;
559 goto fail;
562 if (!tevent_req_poll(req, ev)) {
563 status = map_nt_error_from_unix(errno);
564 goto fail;
567 status = cli_session_setup_guest_recv(req);
568 fail:
569 TALLOC_FREE(frame);
570 return status;
573 /****************************************************************************
574 Do a NT1 plaintext session setup.
575 ****************************************************************************/
577 struct cli_session_setup_plain_state {
578 struct cli_state *cli;
579 uint16_t vwv[13];
580 const char *user;
583 static void cli_session_setup_plain_done(struct tevent_req *subreq);
585 static struct tevent_req *cli_session_setup_plain_send(
586 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
587 struct cli_state *cli,
588 const char *user, const char *pass, const char *workgroup)
590 struct tevent_req *req, *subreq;
591 struct cli_session_setup_plain_state *state;
592 uint16_t *vwv;
593 uint8_t *bytes;
594 size_t passlen;
595 char *version;
597 req = tevent_req_create(mem_ctx, &state,
598 struct cli_session_setup_plain_state);
599 if (req == NULL) {
600 return NULL;
602 state->cli = cli;
603 state->user = user;
604 vwv = state->vwv;
606 SCVAL(vwv+0, 0, 0xff);
607 SCVAL(vwv+0, 1, 0);
608 SSVAL(vwv+1, 0, 0);
609 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
610 SSVAL(vwv+3, 0, 2);
611 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
612 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
613 SSVAL(vwv+7, 0, 0);
614 SSVAL(vwv+8, 0, 0);
615 SSVAL(vwv+9, 0, 0);
616 SSVAL(vwv+10, 0, 0);
617 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
619 bytes = talloc_array(state, uint8_t, 0);
620 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
621 &passlen);
622 if (tevent_req_nomem(bytes, req)) {
623 return tevent_req_post(req, ev);
625 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
627 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
628 user, strlen(user)+1, NULL);
629 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
630 workgroup, strlen(workgroup)+1, NULL);
631 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
632 "Unix", 5, NULL);
634 version = talloc_asprintf(talloc_tos(), "Samba %s",
635 samba_version_string());
636 if (tevent_req_nomem(version, req)){
637 return tevent_req_post(req, ev);
639 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
640 version, strlen(version)+1, NULL);
641 TALLOC_FREE(version);
643 if (tevent_req_nomem(bytes, req)) {
644 return tevent_req_post(req, ev);
647 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
648 talloc_get_size(bytes), bytes);
649 if (tevent_req_nomem(subreq, req)) {
650 return tevent_req_post(req, ev);
652 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
653 return req;
656 static void cli_session_setup_plain_done(struct tevent_req *subreq)
658 struct tevent_req *req = tevent_req_callback_data(
659 subreq, struct tevent_req);
660 struct cli_session_setup_plain_state *state = tevent_req_data(
661 req, struct cli_session_setup_plain_state);
662 struct cli_state *cli = state->cli;
663 uint32_t num_bytes;
664 uint8_t *in;
665 uint8_t *inhdr;
666 uint8_t *bytes;
667 uint8_t *p;
668 NTSTATUS status;
669 ssize_t ret;
670 uint8_t wct;
671 uint16_t *vwv;
673 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
674 &num_bytes, &bytes);
675 TALLOC_FREE(subreq);
676 if (tevent_req_nterror(req, status)) {
677 return;
680 inhdr = in + NBT_HDR_SIZE;
681 p = bytes;
683 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
684 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
686 status = smb_bytes_talloc_string(cli,
687 inhdr,
688 &cli->server_os,
690 bytes+num_bytes-p,
691 &ret);
693 if (!NT_STATUS_IS_OK(status)) {
694 tevent_req_nterror(req, status);
695 return;
697 p += ret;
699 status = smb_bytes_talloc_string(cli,
700 inhdr,
701 &cli->server_type,
703 bytes+num_bytes-p,
704 &ret);
706 if (!NT_STATUS_IS_OK(status)) {
707 tevent_req_nterror(req, status);
708 return;
710 p += ret;
712 status = smb_bytes_talloc_string(cli,
713 inhdr,
714 &cli->server_domain,
716 bytes+num_bytes-p,
717 &ret);
719 if (!NT_STATUS_IS_OK(status)) {
720 tevent_req_nterror(req, status);
721 return;
723 p += ret;
725 status = cli_set_username(cli, state->user);
726 if (tevent_req_nterror(req, status)) {
727 return;
730 tevent_req_done(req);
733 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
735 return tevent_req_simple_recv_ntstatus(req);
738 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
739 const char *user, const char *pass,
740 const char *workgroup)
742 TALLOC_CTX *frame = talloc_stackframe();
743 struct event_context *ev;
744 struct tevent_req *req;
745 NTSTATUS status = NT_STATUS_NO_MEMORY;
747 if (smbXcli_conn_has_async_calls(cli->conn)) {
749 * Can't use sync call while an async call is in flight
751 status = NT_STATUS_INVALID_PARAMETER;
752 goto fail;
754 ev = event_context_init(frame);
755 if (ev == NULL) {
756 goto fail;
758 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
759 workgroup);
760 if (req == NULL) {
761 goto fail;
763 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
764 goto fail;
766 status = cli_session_setup_plain_recv(req);
767 fail:
768 TALLOC_FREE(frame);
769 return status;
772 /****************************************************************************
773 do a NT1 NTLM/LM encrypted session setup - for when extended security
774 is not negotiated.
775 @param cli client state to create do session setup on
776 @param user username
777 @param pass *either* cleartext password (passlen !=24) or LM response.
778 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
779 @param workgroup The user's domain.
780 ****************************************************************************/
782 struct cli_session_setup_nt1_state {
783 struct cli_state *cli;
784 uint16_t vwv[13];
785 DATA_BLOB response;
786 DATA_BLOB session_key;
787 const char *user;
790 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
792 static struct tevent_req *cli_session_setup_nt1_send(
793 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
794 struct cli_state *cli, const char *user,
795 const char *pass, size_t passlen,
796 const char *ntpass, size_t ntpasslen,
797 const char *workgroup)
799 struct tevent_req *req, *subreq;
800 struct cli_session_setup_nt1_state *state;
801 DATA_BLOB lm_response = data_blob_null;
802 DATA_BLOB nt_response = data_blob_null;
803 DATA_BLOB session_key = data_blob_null;
804 uint16_t *vwv;
805 uint8_t *bytes;
806 char *workgroup_upper;
808 req = tevent_req_create(mem_ctx, &state,
809 struct cli_session_setup_nt1_state);
810 if (req == NULL) {
811 return NULL;
813 state->cli = cli;
814 state->user = user;
815 vwv = state->vwv;
817 if (passlen == 0) {
818 /* do nothing - guest login */
819 } else if (passlen != 24) {
820 if (lp_client_ntlmv2_auth()) {
821 DATA_BLOB server_chal;
822 DATA_BLOB names_blob;
824 server_chal =
825 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
829 * note that the 'workgroup' here is a best
830 * guess - we don't know the server's domain
831 * at this point. Windows clients also don't
832 * use hostname...
834 names_blob = NTLMv2_generate_names_blob(
835 NULL, NULL, workgroup);
837 if (tevent_req_nomem(names_blob.data, req)) {
838 return tevent_req_post(req, ev);
841 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
842 &server_chal, &names_blob,
843 &lm_response, &nt_response,
844 NULL, &session_key)) {
845 data_blob_free(&names_blob);
846 tevent_req_nterror(
847 req, NT_STATUS_ACCESS_DENIED);
848 return tevent_req_post(req, ev);
850 data_blob_free(&names_blob);
852 } else {
853 uchar nt_hash[16];
854 E_md4hash(pass, nt_hash);
856 #ifdef LANMAN_ONLY
857 nt_response = data_blob_null;
858 #else
859 nt_response = data_blob(NULL, 24);
860 if (tevent_req_nomem(nt_response.data, req)) {
861 return tevent_req_post(req, ev);
864 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
865 nt_response.data);
866 #endif
867 /* non encrypted password supplied. Ignore ntpass. */
868 if (lp_client_lanman_auth()) {
870 lm_response = data_blob(NULL, 24);
871 if (tevent_req_nomem(lm_response.data, req)) {
872 return tevent_req_post(req, ev);
875 if (!SMBencrypt(pass,
876 smb1cli_conn_server_challenge(cli->conn),
877 lm_response.data)) {
879 * Oops, the LM response is
880 * invalid, just put the NT
881 * response there instead
883 data_blob_free(&lm_response);
884 lm_response = data_blob(
885 nt_response.data,
886 nt_response.length);
888 } else {
890 * LM disabled, place NT# in LM field
891 * instead
893 lm_response = data_blob(
894 nt_response.data, nt_response.length);
897 if (tevent_req_nomem(lm_response.data, req)) {
898 return tevent_req_post(req, ev);
901 session_key = data_blob(NULL, 16);
902 if (tevent_req_nomem(session_key.data, req)) {
903 return tevent_req_post(req, ev);
905 #ifdef LANMAN_ONLY
906 E_deshash(pass, session_key.data);
907 memset(&session_key.data[8], '\0', 8);
908 #else
909 SMBsesskeygen_ntv1(nt_hash, session_key.data);
910 #endif
912 } else {
913 /* pre-encrypted password supplied. Only used for
914 security=server, can't do
915 signing because we don't have original key */
917 lm_response = data_blob(pass, passlen);
918 if (tevent_req_nomem(lm_response.data, req)) {
919 return tevent_req_post(req, ev);
922 nt_response = data_blob(ntpass, ntpasslen);
923 if (tevent_req_nomem(nt_response.data, req)) {
924 return tevent_req_post(req, ev);
928 #ifdef LANMAN_ONLY
929 state->response = data_blob_talloc(
930 state, lm_response.data, lm_response.length);
931 #else
932 state->response = data_blob_talloc(
933 state, nt_response.data, nt_response.length);
934 #endif
935 if (tevent_req_nomem(state->response.data, req)) {
936 return tevent_req_post(req, ev);
939 if (session_key.data) {
940 state->session_key = data_blob_talloc(
941 state, session_key.data, session_key.length);
942 if (tevent_req_nomem(state->session_key.data, req)) {
943 return tevent_req_post(req, ev);
946 data_blob_free(&session_key);
948 SCVAL(vwv+0, 0, 0xff);
949 SCVAL(vwv+0, 1, 0);
950 SSVAL(vwv+1, 0, 0);
951 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
952 SSVAL(vwv+3, 0, 2);
953 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
954 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
955 SSVAL(vwv+7, 0, lm_response.length);
956 SSVAL(vwv+8, 0, nt_response.length);
957 SSVAL(vwv+9, 0, 0);
958 SSVAL(vwv+10, 0, 0);
959 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
961 bytes = talloc_array(state, uint8_t,
962 lm_response.length + nt_response.length);
963 if (tevent_req_nomem(bytes, req)) {
964 return tevent_req_post(req, ev);
966 if (lm_response.length != 0) {
967 memcpy(bytes, lm_response.data, lm_response.length);
969 if (nt_response.length != 0) {
970 memcpy(bytes + lm_response.length,
971 nt_response.data, nt_response.length);
973 data_blob_free(&lm_response);
974 data_blob_free(&nt_response);
976 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
977 user, strlen(user)+1, NULL);
980 * Upper case here might help some NTLMv2 implementations
982 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
983 if (tevent_req_nomem(workgroup_upper, req)) {
984 return tevent_req_post(req, ev);
986 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
987 workgroup_upper, strlen(workgroup_upper)+1,
988 NULL);
989 TALLOC_FREE(workgroup_upper);
991 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
992 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
993 if (tevent_req_nomem(bytes, req)) {
994 return tevent_req_post(req, ev);
997 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
998 talloc_get_size(bytes), bytes);
999 if (tevent_req_nomem(subreq, req)) {
1000 return tevent_req_post(req, ev);
1002 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1003 return req;
1006 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1008 struct tevent_req *req = tevent_req_callback_data(
1009 subreq, struct tevent_req);
1010 struct cli_session_setup_nt1_state *state = tevent_req_data(
1011 req, struct cli_session_setup_nt1_state);
1012 struct cli_state *cli = state->cli;
1013 uint32_t num_bytes;
1014 uint8_t *in;
1015 uint8_t *inhdr;
1016 uint8_t *bytes;
1017 uint8_t *p;
1018 NTSTATUS status;
1019 ssize_t ret;
1020 uint8_t wct;
1021 uint16_t *vwv;
1023 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1024 &num_bytes, &bytes);
1025 TALLOC_FREE(subreq);
1026 if (!NT_STATUS_IS_OK(status)) {
1027 tevent_req_nterror(req, status);
1028 return;
1031 inhdr = in + NBT_HDR_SIZE;
1032 p = bytes;
1034 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1035 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1037 status = smb_bytes_talloc_string(cli,
1038 inhdr,
1039 &cli->server_os,
1041 bytes+num_bytes-p,
1042 &ret);
1043 if (!NT_STATUS_IS_OK(status)) {
1044 tevent_req_nterror(req, status);
1045 return;
1047 p += ret;
1049 status = smb_bytes_talloc_string(cli,
1050 inhdr,
1051 &cli->server_type,
1053 bytes+num_bytes-p,
1054 &ret);
1055 if (!NT_STATUS_IS_OK(status)) {
1056 tevent_req_nterror(req, status);
1057 return;
1059 p += ret;
1061 status = smb_bytes_talloc_string(cli,
1062 inhdr,
1063 &cli->server_domain,
1065 bytes+num_bytes-p,
1066 &ret);
1067 if (!NT_STATUS_IS_OK(status)) {
1068 tevent_req_nterror(req, status);
1069 return;
1071 p += ret;
1073 status = cli_set_username(cli, state->user);
1074 if (tevent_req_nterror(req, status)) {
1075 return;
1077 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
1078 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
1079 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1080 return;
1082 if (state->session_key.data) {
1083 struct smbXcli_session *session = state->cli->smb1.session;
1085 status = smb1cli_session_set_session_key(session,
1086 state->session_key);
1087 if (tevent_req_nterror(req, status)) {
1088 return;
1091 tevent_req_done(req);
1094 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1096 return tevent_req_simple_recv_ntstatus(req);
1099 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1100 const char *pass, size_t passlen,
1101 const char *ntpass, size_t ntpasslen,
1102 const char *workgroup)
1104 TALLOC_CTX *frame = talloc_stackframe();
1105 struct event_context *ev;
1106 struct tevent_req *req;
1107 NTSTATUS status = NT_STATUS_NO_MEMORY;
1109 if (smbXcli_conn_has_async_calls(cli->conn)) {
1111 * Can't use sync call while an async call is in flight
1113 status = NT_STATUS_INVALID_PARAMETER;
1114 goto fail;
1116 ev = event_context_init(frame);
1117 if (ev == NULL) {
1118 goto fail;
1120 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1121 ntpass, ntpasslen, workgroup);
1122 if (req == NULL) {
1123 goto fail;
1125 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1126 goto fail;
1128 status = cli_session_setup_nt1_recv(req);
1129 fail:
1130 TALLOC_FREE(frame);
1131 return status;
1134 /* The following is calculated from :
1135 * (smb_size-4) = 35
1136 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1137 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1138 * end of packet.
1141 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1143 struct cli_sesssetup_blob_state {
1144 struct tevent_context *ev;
1145 struct cli_state *cli;
1146 DATA_BLOB blob;
1147 uint16_t max_blob_size;
1148 uint16_t vwv[12];
1149 uint8_t *buf;
1151 DATA_BLOB smb2_blob;
1152 struct iovec *recv_iov;
1154 NTSTATUS status;
1155 uint8_t *inbuf;
1156 DATA_BLOB ret_blob;
1159 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1160 struct tevent_req **psubreq);
1161 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1163 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1164 struct tevent_context *ev,
1165 struct cli_state *cli,
1166 DATA_BLOB blob)
1168 struct tevent_req *req, *subreq;
1169 struct cli_sesssetup_blob_state *state;
1170 uint32_t usable_space;
1172 req = tevent_req_create(mem_ctx, &state,
1173 struct cli_sesssetup_blob_state);
1174 if (req == NULL) {
1175 return NULL;
1177 state->ev = ev;
1178 state->blob = blob;
1179 state->cli = cli;
1181 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1182 usable_space = UINT16_MAX;
1183 } else {
1184 usable_space = cli_state_available_size(cli,
1185 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1188 if (usable_space == 0) {
1189 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1190 "(not possible to send %u bytes)\n",
1191 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1192 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1193 return tevent_req_post(req, ev);
1195 state->max_blob_size = MIN(usable_space, 0xFFFF);
1197 if (!cli_sesssetup_blob_next(state, &subreq)) {
1198 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1199 return tevent_req_post(req, ev);
1201 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1202 return req;
1205 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1206 struct tevent_req **psubreq)
1208 struct tevent_req *subreq;
1209 uint16_t thistime;
1211 thistime = MIN(state->blob.length, state->max_blob_size);
1213 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1215 state->smb2_blob.data = state->blob.data;
1216 state->smb2_blob.length = thistime;
1218 state->blob.data += thistime;
1219 state->blob.length -= thistime;
1221 subreq = smb2cli_session_setup_send(state, state->ev,
1222 state->cli->conn,
1223 state->cli->timeout,
1224 state->cli->smb2.session,
1225 0, /* in_flags */
1226 SMB2_CAP_DFS, /* in_capabilities */
1227 0, /* in_channel */
1228 0, /* in_previous_session_id */
1229 &state->smb2_blob);
1230 if (subreq == NULL) {
1231 return false;
1233 *psubreq = subreq;
1234 return true;
1237 SCVAL(state->vwv+0, 0, 0xFF);
1238 SCVAL(state->vwv+0, 1, 0);
1239 SSVAL(state->vwv+1, 0, 0);
1240 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1241 SSVAL(state->vwv+3, 0, 2);
1242 SSVAL(state->vwv+4, 0, 1);
1243 SIVAL(state->vwv+5, 0, 0);
1245 SSVAL(state->vwv+7, 0, thistime);
1247 SSVAL(state->vwv+8, 0, 0);
1248 SSVAL(state->vwv+9, 0, 0);
1249 SIVAL(state->vwv+10, 0,
1250 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1252 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1253 thistime);
1254 if (state->buf == NULL) {
1255 return false;
1257 state->blob.data += thistime;
1258 state->blob.length -= thistime;
1260 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1261 "Unix", 5, NULL);
1262 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1263 "Samba", 6, NULL);
1264 if (state->buf == NULL) {
1265 return false;
1267 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1268 12, state->vwv,
1269 talloc_get_size(state->buf), state->buf);
1270 if (subreq == NULL) {
1271 return false;
1273 *psubreq = subreq;
1274 return true;
1277 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1279 struct tevent_req *req = tevent_req_callback_data(
1280 subreq, struct tevent_req);
1281 struct cli_sesssetup_blob_state *state = tevent_req_data(
1282 req, struct cli_sesssetup_blob_state);
1283 struct cli_state *cli = state->cli;
1284 uint8_t wct;
1285 uint16_t *vwv;
1286 uint32_t num_bytes;
1287 uint8_t *bytes;
1288 NTSTATUS status;
1289 uint8_t *p;
1290 uint16_t blob_length;
1291 uint8_t *in;
1292 uint8_t *inhdr;
1293 ssize_t ret;
1295 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1296 status = smb2cli_session_setup_recv(subreq, state,
1297 &state->recv_iov,
1298 &state->ret_blob);
1299 } else {
1300 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1301 &num_bytes, &bytes);
1302 TALLOC_FREE(state->buf);
1304 TALLOC_FREE(subreq);
1305 if (!NT_STATUS_IS_OK(status)
1306 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1307 tevent_req_nterror(req, status);
1308 return;
1311 state->status = status;
1313 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1314 goto next;
1317 state->inbuf = in;
1318 inhdr = in + NBT_HDR_SIZE;
1319 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1320 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1322 blob_length = SVAL(vwv+3, 0);
1323 if (blob_length > num_bytes) {
1324 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1325 return;
1327 state->ret_blob = data_blob_const(bytes, blob_length);
1329 p = bytes + blob_length;
1331 status = smb_bytes_talloc_string(cli,
1332 inhdr,
1333 &cli->server_os,
1335 bytes+num_bytes-p,
1336 &ret);
1338 if (!NT_STATUS_IS_OK(status)) {
1339 tevent_req_nterror(req, status);
1340 return;
1342 p += ret;
1344 status = smb_bytes_talloc_string(cli,
1345 inhdr,
1346 &cli->server_type,
1348 bytes+num_bytes-p,
1349 &ret);
1351 if (!NT_STATUS_IS_OK(status)) {
1352 tevent_req_nterror(req, status);
1353 return;
1355 p += ret;
1357 status = smb_bytes_talloc_string(cli,
1358 inhdr,
1359 &cli->server_domain,
1361 bytes+num_bytes-p,
1362 &ret);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 tevent_req_nterror(req, status);
1366 return;
1368 p += ret;
1370 next:
1371 if (state->blob.length != 0) {
1373 * More to send
1375 if (!cli_sesssetup_blob_next(state, &subreq)) {
1376 tevent_req_oom(req);
1377 return;
1379 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1380 return;
1382 tevent_req_done(req);
1385 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1386 TALLOC_CTX *mem_ctx,
1387 DATA_BLOB *pblob,
1388 uint8_t **pinbuf,
1389 struct iovec **precv_iov)
1391 struct cli_sesssetup_blob_state *state = tevent_req_data(
1392 req, struct cli_sesssetup_blob_state);
1393 NTSTATUS status;
1394 uint8_t *inbuf;
1395 struct iovec *recv_iov;
1397 if (tevent_req_is_nterror(req, &status)) {
1398 TALLOC_FREE(state->cli->smb2.session);
1399 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1400 return status;
1403 inbuf = talloc_move(mem_ctx, &state->inbuf);
1404 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1405 if (pblob != NULL) {
1406 *pblob = state->ret_blob;
1408 if (pinbuf != NULL) {
1409 *pinbuf = inbuf;
1411 if (precv_iov != NULL) {
1412 *precv_iov = recv_iov;
1414 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1415 return state->status;
1418 #ifdef HAVE_KRB5
1420 /****************************************************************************
1421 Use in-memory credentials cache
1422 ****************************************************************************/
1424 static void use_in_memory_ccache(void) {
1425 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1428 /****************************************************************************
1429 Do a spnego/kerberos encrypted session setup.
1430 ****************************************************************************/
1432 struct cli_session_setup_kerberos_state {
1433 struct cli_state *cli;
1434 DATA_BLOB negTokenTarg;
1435 DATA_BLOB session_key_krb5;
1436 ADS_STATUS ads_status;
1439 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1441 static struct tevent_req *cli_session_setup_kerberos_send(
1442 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1443 const char *principal)
1445 struct tevent_req *req, *subreq;
1446 struct cli_session_setup_kerberos_state *state;
1447 int rc;
1449 DEBUG(2,("Doing kerberos session setup\n"));
1451 req = tevent_req_create(mem_ctx, &state,
1452 struct cli_session_setup_kerberos_state);
1453 if (req == NULL) {
1454 return NULL;
1456 state->cli = cli;
1457 state->ads_status = ADS_SUCCESS;
1460 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1461 * we have to acquire a ticket. To be fixed later :-)
1463 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1464 &state->session_key_krb5, 0, NULL);
1465 if (rc) {
1466 DEBUG(1, ("cli_session_setup_kerberos: "
1467 "spnego_gen_krb5_negTokenInit failed: %s\n",
1468 error_message(rc)));
1469 state->ads_status = ADS_ERROR_KRB5(rc);
1470 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1471 return tevent_req_post(req, ev);
1474 #if 0
1475 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1476 state->negTokenTarg.length);
1477 #endif
1479 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1480 state->cli->smb2.session = smbXcli_session_create(cli,
1481 cli->conn);
1482 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1483 return tevent_req_post(req, ev);
1487 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1488 if (tevent_req_nomem(subreq, req)) {
1489 return tevent_req_post(req, ev);
1491 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1492 return req;
1495 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1497 struct tevent_req *req = tevent_req_callback_data(
1498 subreq, struct tevent_req);
1499 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1500 req, struct cli_session_setup_kerberos_state);
1501 uint8_t *inbuf = NULL;
1502 struct iovec *recv_iov = NULL;
1503 NTSTATUS status;
1505 status = cli_sesssetup_blob_recv(subreq, state,
1506 NULL, &inbuf, &recv_iov);
1507 TALLOC_FREE(subreq);
1508 if (!NT_STATUS_IS_OK(status)) {
1509 tevent_req_nterror(req, status);
1510 return;
1513 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1514 struct smbXcli_session *session = state->cli->smb2.session;
1515 status = smb2cli_session_set_session_key(session,
1516 state->session_key_krb5,
1517 recv_iov);
1518 if (tevent_req_nterror(req, status)) {
1519 return;
1521 } else {
1522 struct smbXcli_session *session = state->cli->smb1.session;
1524 status = smb1cli_session_set_session_key(session,
1525 state->session_key_krb5);
1526 if (tevent_req_nterror(req, status)) {
1527 return;
1530 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1531 data_blob_null)
1532 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1533 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1534 return;
1538 tevent_req_done(req);
1541 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1543 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1544 req, struct cli_session_setup_kerberos_state);
1545 NTSTATUS status;
1547 if (tevent_req_is_nterror(req, &status)) {
1548 return ADS_ERROR_NT(status);
1550 return state->ads_status;
1553 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1554 const char *principal)
1556 struct tevent_context *ev;
1557 struct tevent_req *req;
1558 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1560 if (smbXcli_conn_has_async_calls(cli->conn)) {
1561 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1563 ev = tevent_context_init(talloc_tos());
1564 if (ev == NULL) {
1565 goto fail;
1567 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1568 if (req == NULL) {
1569 goto fail;
1571 if (!tevent_req_poll(req, ev)) {
1572 status = ADS_ERROR_SYSTEM(errno);
1573 goto fail;
1575 status = cli_session_setup_kerberos_recv(req);
1576 fail:
1577 TALLOC_FREE(ev);
1578 return status;
1580 #endif /* HAVE_KRB5 */
1582 /****************************************************************************
1583 Do a spnego/NTLMSSP encrypted session setup.
1584 ****************************************************************************/
1586 struct cli_session_setup_ntlmssp_state {
1587 struct tevent_context *ev;
1588 struct cli_state *cli;
1589 struct ntlmssp_state *ntlmssp_state;
1590 int turn;
1591 DATA_BLOB blob_out;
1594 static int cli_session_setup_ntlmssp_state_destructor(
1595 struct cli_session_setup_ntlmssp_state *state)
1597 if (state->ntlmssp_state != NULL) {
1598 TALLOC_FREE(state->ntlmssp_state);
1600 return 0;
1603 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1605 static struct tevent_req *cli_session_setup_ntlmssp_send(
1606 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1607 const char *user, const char *pass, const char *domain)
1609 struct tevent_req *req, *subreq;
1610 struct cli_session_setup_ntlmssp_state *state;
1611 NTSTATUS status;
1612 DATA_BLOB blob_out;
1613 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1615 req = tevent_req_create(mem_ctx, &state,
1616 struct cli_session_setup_ntlmssp_state);
1617 if (req == NULL) {
1618 return NULL;
1620 state->ev = ev;
1621 state->cli = cli;
1622 state->turn = 1;
1624 state->ntlmssp_state = NULL;
1625 talloc_set_destructor(
1626 state, cli_session_setup_ntlmssp_state_destructor);
1628 status = ntlmssp_client_start(state,
1629 lp_netbios_name(),
1630 lp_workgroup(),
1631 lp_client_ntlmv2_auth(),
1632 &state->ntlmssp_state);
1633 if (!NT_STATUS_IS_OK(status)) {
1634 goto fail;
1636 ntlmssp_want_feature(state->ntlmssp_state,
1637 NTLMSSP_FEATURE_SESSION_KEY);
1638 if (cli->use_ccache) {
1639 ntlmssp_want_feature(state->ntlmssp_state,
1640 NTLMSSP_FEATURE_CCACHE);
1642 status = ntlmssp_set_username(state->ntlmssp_state, user);
1643 if (!NT_STATUS_IS_OK(status)) {
1644 goto fail;
1646 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1647 if (!NT_STATUS_IS_OK(status)) {
1648 goto fail;
1650 if (cli->pw_nt_hash) {
1651 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1652 } else {
1653 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1655 if (!NT_STATUS_IS_OK(status)) {
1656 goto fail;
1658 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1659 &blob_out);
1660 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1661 goto fail;
1664 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1665 data_blob_free(&blob_out);
1667 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1668 state->cli->smb2.session = smbXcli_session_create(cli,
1669 cli->conn);
1670 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1671 return tevent_req_post(req, ev);
1675 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1676 if (tevent_req_nomem(subreq, req)) {
1677 return tevent_req_post(req, ev);
1679 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1680 return req;
1681 fail:
1682 tevent_req_nterror(req, status);
1683 return tevent_req_post(req, ev);
1686 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1688 struct tevent_req *req = tevent_req_callback_data(
1689 subreq, struct tevent_req);
1690 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1691 req, struct cli_session_setup_ntlmssp_state);
1692 DATA_BLOB blob_in, msg_in, blob_out;
1693 uint8_t *inbuf = NULL;
1694 struct iovec *recv_iov = NULL;
1695 bool parse_ret;
1696 NTSTATUS status;
1698 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1699 &inbuf, &recv_iov);
1700 TALLOC_FREE(subreq);
1701 data_blob_free(&state->blob_out);
1703 if (NT_STATUS_IS_OK(status)) {
1704 if (state->cli->server_domain[0] == '\0') {
1705 TALLOC_FREE(state->cli->server_domain);
1706 state->cli->server_domain = talloc_strdup(state->cli,
1707 state->ntlmssp_state->server.netbios_domain);
1708 if (state->cli->server_domain == NULL) {
1709 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1710 return;
1714 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1715 struct smbXcli_session *session = state->cli->smb2.session;
1717 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1719 * Windows server does not set the
1720 * SMB2_SESSION_FLAG_IS_GUEST nor
1721 * SMB2_SESSION_FLAG_IS_NULL flag.
1723 * This fix makes sure we do not try
1724 * to verify a signature on the final
1725 * session setup response.
1727 TALLOC_FREE(state->ntlmssp_state);
1728 tevent_req_done(req);
1729 return;
1732 status = smb2cli_session_set_session_key(session,
1733 state->ntlmssp_state->session_key,
1734 recv_iov);
1735 if (tevent_req_nterror(req, status)) {
1736 return;
1738 } else {
1739 struct smbXcli_session *session = state->cli->smb1.session;
1741 status = smb1cli_session_set_session_key(session,
1742 state->ntlmssp_state->session_key);
1743 if (tevent_req_nterror(req, status)) {
1744 return;
1747 if (smb1cli_conn_activate_signing(
1748 state->cli->conn, state->ntlmssp_state->session_key,
1749 data_blob_null)
1750 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1751 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1752 return;
1755 TALLOC_FREE(state->ntlmssp_state);
1756 tevent_req_done(req);
1757 return;
1759 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1760 tevent_req_nterror(req, status);
1761 return;
1764 if (blob_in.length == 0) {
1765 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1766 return;
1769 if ((state->turn == 1)
1770 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1771 DATA_BLOB tmp_blob = data_blob_null;
1772 /* the server might give us back two challenges */
1773 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1774 &tmp_blob);
1775 data_blob_free(&tmp_blob);
1776 } else {
1777 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1778 OID_NTLMSSP, &msg_in);
1780 state->turn += 1;
1782 if (!parse_ret) {
1783 DEBUG(3,("Failed to parse auth response\n"));
1784 if (NT_STATUS_IS_OK(status)
1785 || NT_STATUS_EQUAL(status,
1786 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1787 tevent_req_nterror(
1788 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1789 return;
1793 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1795 if (!NT_STATUS_IS_OK(status)
1796 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1797 TALLOC_FREE(state->ntlmssp_state);
1798 tevent_req_nterror(req, status);
1799 return;
1802 state->blob_out = spnego_gen_auth(state, blob_out);
1803 if (tevent_req_nomem(state->blob_out.data, req)) {
1804 return;
1807 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1808 state->blob_out);
1809 if (tevent_req_nomem(subreq, req)) {
1810 return;
1812 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1815 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1817 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1818 req, struct cli_session_setup_ntlmssp_state);
1819 NTSTATUS status;
1821 if (tevent_req_is_nterror(req, &status)) {
1822 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1823 return status;
1825 return NT_STATUS_OK;
1828 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1829 const char *user,
1830 const char *pass,
1831 const char *domain)
1833 struct tevent_context *ev;
1834 struct tevent_req *req;
1835 NTSTATUS status = NT_STATUS_NO_MEMORY;
1837 if (smbXcli_conn_has_async_calls(cli->conn)) {
1838 return NT_STATUS_INVALID_PARAMETER;
1840 ev = tevent_context_init(talloc_tos());
1841 if (ev == NULL) {
1842 goto fail;
1844 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1845 if (req == NULL) {
1846 goto fail;
1848 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1849 goto fail;
1851 status = cli_session_setup_ntlmssp_recv(req);
1852 fail:
1853 TALLOC_FREE(ev);
1854 return status;
1857 /****************************************************************************
1858 Do a spnego encrypted session setup.
1860 user_domain: The shortname of the domain the user/machine is a member of.
1861 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1862 ****************************************************************************/
1864 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1865 const char *user,
1866 const char *pass,
1867 const char *user_domain,
1868 const char * dest_realm)
1870 char *principal = NULL;
1871 char *OIDs[ASN1_MAX_OIDS];
1872 int i;
1873 const DATA_BLOB *server_blob;
1874 DATA_BLOB blob = data_blob_null;
1875 const char *p = NULL;
1876 char *account = NULL;
1877 NTSTATUS status;
1879 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1880 if (server_blob) {
1881 blob = data_blob(server_blob->data, server_blob->length);
1884 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)blob.length));
1886 /* the server might not even do spnego */
1887 if (blob.length == 0) {
1888 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1889 goto ntlmssp;
1892 #if 0
1893 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1894 #endif
1896 /* The server sent us the first part of the SPNEGO exchange in the
1897 * negprot reply. It is WRONG to depend on the principal sent in the
1898 * negprot reply, but right now we do it. If we don't receive one,
1899 * we try to best guess, then fall back to NTLM. */
1900 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1901 OIDs[0] == NULL) {
1902 data_blob_free(&blob);
1903 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1905 data_blob_free(&blob);
1907 /* make sure the server understands kerberos */
1908 for (i=0;OIDs[i];i++) {
1909 if (i == 0)
1910 DEBUG(3,("got OID=%s\n", OIDs[i]));
1911 else
1912 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1913 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1914 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1915 cli->got_kerberos_mechanism = True;
1917 talloc_free(OIDs[i]);
1920 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1922 status = cli_set_username(cli, user);
1923 if (!NT_STATUS_IS_OK(status)) {
1924 TALLOC_FREE(principal);
1925 return ADS_ERROR_NT(status);
1928 #ifdef HAVE_KRB5
1929 /* If password is set we reauthenticate to kerberos server
1930 * and do not store results */
1932 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1933 ADS_STATUS rc;
1934 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1936 if (pass && *pass) {
1937 int ret;
1939 use_in_memory_ccache();
1940 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1942 if (ret){
1943 TALLOC_FREE(principal);
1944 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1945 if (cli->fallback_after_kerberos)
1946 goto ntlmssp;
1947 return ADS_ERROR_KRB5(ret);
1951 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1953 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1954 TALLOC_FREE(principal);
1957 if (principal == NULL &&
1958 !is_ipaddress(remote_name) &&
1959 !strequal(STAR_SMBSERVER,
1960 remote_name)) {
1961 DEBUG(3,("cli_session_setup_spnego: using target "
1962 "hostname not SPNEGO principal\n"));
1964 if (dest_realm) {
1965 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1966 if (realm) {
1967 principal = talloc_asprintf(talloc_tos(),
1968 "cifs/%s@%s",
1969 remote_name,
1970 realm);
1971 TALLOC_FREE(realm);
1973 } else {
1974 principal = kerberos_get_principal_from_service_hostname(talloc_tos(),
1975 "cifs",
1976 remote_name,
1977 lp_realm());
1980 if (!principal) {
1981 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1983 DEBUG(3,("cli_session_setup_spnego: guessed "
1984 "server principal=%s\n",
1985 principal ? principal : "<null>"));
1988 if (principal) {
1989 rc = cli_session_setup_kerberos(cli, principal);
1990 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1991 TALLOC_FREE(principal);
1992 return rc;
1996 #endif
1998 TALLOC_FREE(principal);
2000 ntlmssp:
2002 account = talloc_strdup(talloc_tos(), user);
2003 if (!account) {
2004 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
2007 /* when falling back to ntlmssp while authenticating with a machine
2008 * account strip off the realm - gd */
2010 if ((p = strchr_m(user, '@')) != NULL) {
2011 account[PTR_DIFF(p,user)] = '\0';
2014 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
2017 /****************************************************************************
2018 Send a session setup. The username and workgroup is in UNIX character
2019 format and must be converted to DOS codepage format before sending. If the
2020 password is in plaintext, the same should be done.
2021 ****************************************************************************/
2023 NTSTATUS cli_session_setup(struct cli_state *cli,
2024 const char *user,
2025 const char *pass, int passlen,
2026 const char *ntpass, int ntpasslen,
2027 const char *workgroup)
2029 char *p;
2030 char *user2;
2031 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2033 if (user) {
2034 user2 = talloc_strdup(talloc_tos(), user);
2035 } else {
2036 user2 = talloc_strdup(talloc_tos(), "");
2038 if (user2 == NULL) {
2039 return NT_STATUS_NO_MEMORY;
2042 if (!workgroup) {
2043 workgroup = "";
2046 /* allow for workgroups as part of the username */
2047 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2048 (p=strchr_m(user2,*lp_winbind_separator()))) {
2049 *p = 0;
2050 user = p+1;
2051 strupper_m(user2);
2052 workgroup = user2;
2055 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2056 return NT_STATUS_OK;
2059 /* now work out what sort of session setup we are going to
2060 do. I have split this into separate functions to make the
2061 flow a bit easier to understand (tridge) */
2063 /* if its an older server then we have to use the older request format */
2065 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2066 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2067 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2068 " or 'client ntlmv2 auth = yes'\n"));
2069 return NT_STATUS_ACCESS_DENIED;
2072 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2073 !lp_client_plaintext_auth() && (*pass)) {
2074 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2075 " or 'client ntlmv2 auth = yes'\n"));
2076 return NT_STATUS_ACCESS_DENIED;
2079 return cli_session_setup_lanman2(cli, user, pass, passlen,
2080 workgroup);
2083 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2084 const char *remote_realm = cli_state_remote_realm(cli);
2085 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2086 workgroup,
2087 remote_realm);
2088 if (!ADS_ERR_OK(status)) {
2089 DEBUG(3, ("SMB2-SPNEGO login failed: %s\n", ads_errstr(status)));
2090 return ads_ntstatus(status);
2092 return NT_STATUS_OK;
2095 /* if no user is supplied then we have to do an anonymous connection.
2096 passwords are ignored */
2098 if (!user || !*user)
2099 return cli_session_setup_guest(cli);
2101 /* if the server is share level then send a plaintext null
2102 password at this point. The password is sent in the tree
2103 connect */
2105 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2106 return cli_session_setup_plain(cli, user, "", workgroup);
2108 /* if the server doesn't support encryption then we have to use
2109 plaintext. The second password is ignored */
2111 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2112 if (!lp_client_plaintext_auth() && (*pass)) {
2113 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2114 " or 'client ntlmv2 auth = yes'\n"));
2115 return NT_STATUS_ACCESS_DENIED;
2117 return cli_session_setup_plain(cli, user, pass, workgroup);
2120 /* if the server supports extended security then use SPNEGO */
2122 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2123 const char *remote_realm = cli_state_remote_realm(cli);
2124 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2125 workgroup,
2126 remote_realm);
2127 if (!ADS_ERR_OK(status)) {
2128 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2129 return ads_ntstatus(status);
2131 } else {
2132 NTSTATUS status;
2134 /* otherwise do a NT1 style session setup */
2135 status = cli_session_setup_nt1(cli, user, pass, passlen,
2136 ntpass, ntpasslen, workgroup);
2137 if (!NT_STATUS_IS_OK(status)) {
2138 DEBUG(3,("cli_session_setup: NT1 session setup "
2139 "failed: %s\n", nt_errstr(status)));
2140 return status;
2144 return NT_STATUS_OK;
2147 /****************************************************************************
2148 Send a uloggoff.
2149 *****************************************************************************/
2151 struct cli_ulogoff_state {
2152 struct cli_state *cli;
2153 uint16_t vwv[3];
2156 static void cli_ulogoff_done(struct tevent_req *subreq);
2158 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2159 struct tevent_context *ev,
2160 struct cli_state *cli)
2162 struct tevent_req *req, *subreq;
2163 struct cli_ulogoff_state *state;
2165 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2166 if (req == NULL) {
2167 return NULL;
2169 state->cli = cli;
2171 SCVAL(state->vwv+0, 0, 0xFF);
2172 SCVAL(state->vwv+1, 0, 0);
2173 SSVAL(state->vwv+2, 0, 0);
2175 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2176 0, NULL);
2177 if (tevent_req_nomem(subreq, req)) {
2178 return tevent_req_post(req, ev);
2180 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2181 return req;
2184 static void cli_ulogoff_done(struct tevent_req *subreq)
2186 struct tevent_req *req = tevent_req_callback_data(
2187 subreq, struct tevent_req);
2188 struct cli_ulogoff_state *state = tevent_req_data(
2189 req, struct cli_ulogoff_state);
2190 NTSTATUS status;
2192 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2193 if (!NT_STATUS_IS_OK(status)) {
2194 tevent_req_nterror(req, status);
2195 return;
2197 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2198 tevent_req_done(req);
2201 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2203 return tevent_req_simple_recv_ntstatus(req);
2206 NTSTATUS cli_ulogoff(struct cli_state *cli)
2208 struct tevent_context *ev;
2209 struct tevent_req *req;
2210 NTSTATUS status = NT_STATUS_NO_MEMORY;
2212 if (smbXcli_conn_has_async_calls(cli->conn)) {
2213 return NT_STATUS_INVALID_PARAMETER;
2215 ev = tevent_context_init(talloc_tos());
2216 if (ev == NULL) {
2217 goto fail;
2219 req = cli_ulogoff_send(ev, ev, cli);
2220 if (req == NULL) {
2221 goto fail;
2223 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2224 goto fail;
2226 status = cli_ulogoff_recv(req);
2227 fail:
2228 TALLOC_FREE(ev);
2229 return status;
2232 /****************************************************************************
2233 Send a tconX.
2234 ****************************************************************************/
2236 struct cli_tcon_andx_state {
2237 struct cli_state *cli;
2238 uint16_t vwv[4];
2239 struct iovec bytes;
2242 static void cli_tcon_andx_done(struct tevent_req *subreq);
2244 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2245 struct event_context *ev,
2246 struct cli_state *cli,
2247 const char *share, const char *dev,
2248 const char *pass, int passlen,
2249 struct tevent_req **psmbreq)
2251 struct tevent_req *req, *subreq;
2252 struct cli_tcon_andx_state *state;
2253 uint8_t p24[24];
2254 uint16_t *vwv;
2255 char *tmp = NULL;
2256 uint8_t *bytes;
2257 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2258 uint16_t tcon_flags = 0;
2260 *psmbreq = NULL;
2262 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2263 if (req == NULL) {
2264 return NULL;
2266 state->cli = cli;
2267 vwv = state->vwv;
2269 cli->share = talloc_strdup(cli, share);
2270 if (!cli->share) {
2271 return NULL;
2274 /* in user level security don't send a password now */
2275 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2276 passlen = 1;
2277 pass = "";
2278 } else if (pass == NULL) {
2279 DEBUG(1, ("Server not using user level security and no "
2280 "password supplied.\n"));
2281 goto access_denied;
2284 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2285 *pass && passlen != 24) {
2286 if (!lp_client_lanman_auth()) {
2287 DEBUG(1, ("Server requested LANMAN password "
2288 "(share-level security) but "
2289 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2290 goto access_denied;
2294 * Non-encrypted passwords - convert to DOS codepage before
2295 * encryption.
2297 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2298 passlen = 24;
2299 pass = (const char *)p24;
2300 } else {
2301 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2302 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2303 == 0) {
2304 uint8_t *tmp_pass;
2306 if (!lp_client_plaintext_auth() && (*pass)) {
2307 DEBUG(1, ("Server requested PLAINTEXT "
2308 "password but "
2309 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2310 goto access_denied;
2314 * Non-encrypted passwords - convert to DOS codepage
2315 * before using.
2317 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2318 if (tevent_req_nomem(tmp_pass, req)) {
2319 return tevent_req_post(req, ev);
2321 tmp_pass = trans2_bytes_push_str(tmp_pass,
2322 false, /* always DOS */
2323 pass,
2324 passlen,
2325 NULL);
2326 if (tevent_req_nomem(tmp_pass, req)) {
2327 return tevent_req_post(req, ev);
2329 pass = (const char *)tmp_pass;
2330 passlen = talloc_get_size(tmp_pass);
2334 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2335 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2337 SCVAL(vwv+0, 0, 0xFF);
2338 SCVAL(vwv+0, 1, 0);
2339 SSVAL(vwv+1, 0, 0);
2340 SSVAL(vwv+2, 0, tcon_flags);
2341 SSVAL(vwv+3, 0, passlen);
2343 if (passlen && pass) {
2344 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2345 } else {
2346 bytes = talloc_array(state, uint8_t, 0);
2350 * Add the sharename
2352 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2353 smbXcli_conn_remote_name(cli->conn), share);
2354 if (tmp == NULL) {
2355 TALLOC_FREE(req);
2356 return NULL;
2358 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2359 NULL);
2360 TALLOC_FREE(tmp);
2363 * Add the devicetype
2365 tmp = talloc_strdup_upper(talloc_tos(), dev);
2366 if (tmp == NULL) {
2367 TALLOC_FREE(req);
2368 return NULL;
2370 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2371 TALLOC_FREE(tmp);
2373 if (bytes == NULL) {
2374 TALLOC_FREE(req);
2375 return NULL;
2378 state->bytes.iov_base = (void *)bytes;
2379 state->bytes.iov_len = talloc_get_size(bytes);
2381 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2382 1, &state->bytes);
2383 if (subreq == NULL) {
2384 TALLOC_FREE(req);
2385 return NULL;
2387 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2388 *psmbreq = subreq;
2389 return req;
2391 access_denied:
2392 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2393 return tevent_req_post(req, ev);
2396 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2397 struct event_context *ev,
2398 struct cli_state *cli,
2399 const char *share, const char *dev,
2400 const char *pass, int passlen)
2402 struct tevent_req *req, *subreq;
2403 NTSTATUS status;
2405 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2406 &subreq);
2407 if (req == NULL) {
2408 return NULL;
2410 if (subreq == NULL) {
2411 return req;
2413 status = smb1cli_req_chain_submit(&subreq, 1);
2414 if (!NT_STATUS_IS_OK(status)) {
2415 tevent_req_nterror(req, status);
2416 return tevent_req_post(req, ev);
2418 return req;
2421 static void cli_tcon_andx_done(struct tevent_req *subreq)
2423 struct tevent_req *req = tevent_req_callback_data(
2424 subreq, struct tevent_req);
2425 struct cli_tcon_andx_state *state = tevent_req_data(
2426 req, struct cli_tcon_andx_state);
2427 struct cli_state *cli = state->cli;
2428 uint8_t *in;
2429 uint8_t *inhdr;
2430 uint8_t wct;
2431 uint16_t *vwv;
2432 uint32_t num_bytes;
2433 uint8_t *bytes;
2434 NTSTATUS status;
2435 uint16_t optional_support = 0;
2437 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2438 &num_bytes, &bytes);
2439 TALLOC_FREE(subreq);
2440 if (!NT_STATUS_IS_OK(status)) {
2441 tevent_req_nterror(req, status);
2442 return;
2445 inhdr = in + NBT_HDR_SIZE;
2447 if (num_bytes) {
2448 if (clistr_pull_talloc(cli,
2449 (const char *)inhdr,
2450 SVAL(inhdr, HDR_FLG2),
2451 &cli->dev,
2452 bytes,
2453 num_bytes,
2454 STR_TERMINATE|STR_ASCII) == -1) {
2455 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2456 return;
2458 } else {
2459 cli->dev = talloc_strdup(cli, "");
2460 if (cli->dev == NULL) {
2461 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2462 return;
2466 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2467 /* almost certainly win95 - enable bug fixes */
2468 cli->win95 = True;
2472 * Make sure that we have the optional support 16-bit field. WCT > 2.
2473 * Avoids issues when connecting to Win9x boxes sharing files
2476 cli->dfsroot = false;
2478 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2479 optional_support = SVAL(vwv+2, 0);
2482 if (optional_support & SMB_SHARE_IN_DFS) {
2483 cli->dfsroot = true;
2486 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2487 smb1cli_session_protect_session_key(cli->smb1.session);
2490 cli_state_set_tid(cli, SVAL(inhdr, HDR_TID));
2491 tevent_req_done(req);
2494 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2496 return tevent_req_simple_recv_ntstatus(req);
2499 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2500 const char *dev, const char *pass, int passlen)
2502 TALLOC_CTX *frame = talloc_stackframe();
2503 struct event_context *ev;
2504 struct tevent_req *req;
2505 NTSTATUS status = NT_STATUS_OK;
2507 if (smbXcli_conn_has_async_calls(cli->conn)) {
2509 * Can't use sync call while an async call is in flight
2511 status = NT_STATUS_INVALID_PARAMETER;
2512 goto fail;
2515 ev = event_context_init(frame);
2516 if (ev == NULL) {
2517 status = NT_STATUS_NO_MEMORY;
2518 goto fail;
2521 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2522 if (req == NULL) {
2523 status = NT_STATUS_NO_MEMORY;
2524 goto fail;
2527 if (!tevent_req_poll(req, ev)) {
2528 status = map_nt_error_from_unix(errno);
2529 goto fail;
2532 status = cli_tcon_andx_recv(req);
2533 fail:
2534 TALLOC_FREE(frame);
2535 return status;
2538 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2539 const char *dev, const char *pass, int passlen)
2541 NTSTATUS status;
2542 uint16_t max_xmit = 0;
2543 uint16_t tid = 0;
2545 cli->share = talloc_strdup(cli, share);
2546 if (!cli->share) {
2547 return NT_STATUS_NO_MEMORY;
2550 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2551 return smb2cli_tcon(cli, share);
2554 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2555 return cli_tcon_andx(cli, share, dev, pass, passlen);
2558 status = cli_raw_tcon(cli, share, pass, dev, &max_xmit, &tid);
2559 if (!NT_STATUS_IS_OK(status)) {
2560 return status;
2563 cli_state_set_tid(cli, tid);
2565 return NT_STATUS_OK;
2568 /****************************************************************************
2569 Send a tree disconnect.
2570 ****************************************************************************/
2572 struct cli_tdis_state {
2573 struct cli_state *cli;
2576 static void cli_tdis_done(struct tevent_req *subreq);
2578 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2579 struct tevent_context *ev,
2580 struct cli_state *cli)
2582 struct tevent_req *req, *subreq;
2583 struct cli_tdis_state *state;
2585 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2586 if (req == NULL) {
2587 return NULL;
2589 state->cli = cli;
2591 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2592 if (tevent_req_nomem(subreq, req)) {
2593 return tevent_req_post(req, ev);
2595 tevent_req_set_callback(subreq, cli_tdis_done, req);
2596 return req;
2599 static void cli_tdis_done(struct tevent_req *subreq)
2601 struct tevent_req *req = tevent_req_callback_data(
2602 subreq, struct tevent_req);
2603 struct cli_tdis_state *state = tevent_req_data(
2604 req, struct cli_tdis_state);
2605 NTSTATUS status;
2607 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2608 TALLOC_FREE(subreq);
2609 if (!NT_STATUS_IS_OK(status)) {
2610 tevent_req_nterror(req, status);
2611 return;
2613 cli_state_set_tid(state->cli, UINT16_MAX);
2614 tevent_req_done(req);
2617 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2619 return tevent_req_simple_recv_ntstatus(req);
2622 NTSTATUS cli_tdis(struct cli_state *cli)
2624 struct tevent_context *ev;
2625 struct tevent_req *req;
2626 NTSTATUS status = NT_STATUS_NO_MEMORY;
2628 if (smbXcli_conn_has_async_calls(cli->conn)) {
2629 return NT_STATUS_INVALID_PARAMETER;
2631 ev = tevent_context_init(talloc_tos());
2632 if (ev == NULL) {
2633 goto fail;
2635 req = cli_tdis_send(ev, ev, cli);
2636 if (req == NULL) {
2637 goto fail;
2639 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2640 goto fail;
2642 status = cli_tdis_recv(req);
2643 fail:
2644 TALLOC_FREE(ev);
2645 return status;
2648 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2649 const struct sockaddr_storage *pss,
2650 const char *myname, uint16_t port,
2651 int sec_timeout, int *pfd, uint16_t *pport)
2653 TALLOC_CTX *frame = talloc_stackframe();
2654 const char *prog;
2655 unsigned int i, num_addrs;
2656 const char **called_names;
2657 const char **calling_names;
2658 int *called_types;
2659 NTSTATUS status;
2660 int fd;
2662 prog = getenv("LIBSMB_PROG");
2663 if (prog != NULL) {
2664 fd = sock_exec(prog);
2665 if (fd == -1) {
2666 return map_nt_error_from_unix(errno);
2668 port = 0;
2669 goto done;
2672 if ((pss == NULL) || is_zero_addr(pss)) {
2673 struct sockaddr_storage *addrs;
2674 status = resolve_name_list(talloc_tos(), host, name_type,
2675 &addrs, &num_addrs);
2676 if (!NT_STATUS_IS_OK(status)) {
2677 goto fail;
2679 pss = addrs;
2680 } else {
2681 num_addrs = 1;
2684 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2685 if (called_names == NULL) {
2686 status = NT_STATUS_NO_MEMORY;
2687 goto fail;
2689 called_types = talloc_array(talloc_tos(), int, num_addrs);
2690 if (called_types == NULL) {
2691 status = NT_STATUS_NO_MEMORY;
2692 goto fail;
2694 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2695 if (calling_names == NULL) {
2696 status = NT_STATUS_NO_MEMORY;
2697 goto fail;
2699 for (i=0; i<num_addrs; i++) {
2700 called_names[i] = host;
2701 called_types[i] = name_type;
2702 calling_names[i] = myname;
2704 status = smbsock_any_connect(pss, called_names, called_types,
2705 calling_names, NULL, num_addrs, port,
2706 sec_timeout, &fd, NULL, &port);
2707 if (!NT_STATUS_IS_OK(status)) {
2708 goto fail;
2710 set_socket_options(fd, lp_socket_options());
2711 done:
2712 *pfd = fd;
2713 *pport = port;
2714 status = NT_STATUS_OK;
2715 fail:
2716 TALLOC_FREE(frame);
2717 return status;
2720 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2721 uint16_t port, int name_type, const char *myname,
2722 int signing_state, int flags, struct cli_state **pcli)
2724 TALLOC_CTX *frame = talloc_stackframe();
2725 struct cli_state *cli;
2726 NTSTATUS status = NT_STATUS_NO_MEMORY;
2727 int fd = -1;
2728 char *desthost;
2729 char *p;
2731 desthost = talloc_strdup(talloc_tos(), host);
2732 if (desthost == NULL) {
2733 goto fail;
2736 p = strchr(host, '#');
2737 if (p != NULL) {
2738 name_type = strtol(p+1, NULL, 16);
2739 host = talloc_strndup(talloc_tos(), host, p - host);
2740 if (host == NULL) {
2741 goto fail;
2745 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
2746 20, &fd, &port);
2747 if (!NT_STATUS_IS_OK(status)) {
2748 goto fail;
2751 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
2752 if (cli == NULL) {
2753 close(fd);
2754 fd = -1;
2755 goto fail;
2758 *pcli = cli;
2759 status = NT_STATUS_OK;
2760 fail:
2761 TALLOC_FREE(frame);
2762 return status;
2766 establishes a connection to after the negprot.
2767 @param output_cli A fully initialised cli structure, non-null only on success
2768 @param dest_host The netbios name of the remote host
2769 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2770 @param port (optional) The destination port (0 for default)
2772 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2773 const char *my_name,
2774 const char *dest_host,
2775 const struct sockaddr_storage *dest_ss, int port,
2776 int signing_state, int flags)
2778 NTSTATUS nt_status;
2779 struct cli_state *cli;
2781 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2782 signing_state, flags, &cli);
2783 if (!NT_STATUS_IS_OK(nt_status)) {
2784 DEBUG(10, ("cli_connect_nb failed: %s\n",
2785 nt_errstr(nt_status)));
2786 return nt_status;
2789 nt_status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
2790 PROTOCOL_NT1);
2791 if (!NT_STATUS_IS_OK(nt_status)) {
2792 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2793 cli_shutdown(cli);
2794 return nt_status;
2797 *output_cli = cli;
2798 return NT_STATUS_OK;
2803 establishes a connection right up to doing tconX, password specified.
2804 @param output_cli A fully initialised cli structure, non-null only on success
2805 @param dest_host The netbios name of the remote host
2806 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2807 @param port (optional) The destination port (0 for default)
2808 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2809 @param service_type The 'type' of serivice.
2810 @param user Username, unix string
2811 @param domain User's domain
2812 @param password User's password, unencrypted unix string.
2815 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2816 const char *my_name,
2817 const char *dest_host,
2818 const struct sockaddr_storage *dest_ss, int port,
2819 const char *service, const char *service_type,
2820 const char *user, const char *domain,
2821 const char *password, int flags,
2822 int signing_state)
2824 NTSTATUS nt_status;
2825 struct cli_state *cli = NULL;
2826 int pw_len = password ? strlen(password)+1 : 0;
2828 *output_cli = NULL;
2830 if (password == NULL) {
2831 password = "";
2834 nt_status = cli_start_connection(&cli, my_name, dest_host,
2835 dest_ss, port, signing_state,
2836 flags);
2838 if (!NT_STATUS_IS_OK(nt_status)) {
2839 return nt_status;
2842 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2843 pw_len, domain);
2844 if (!NT_STATUS_IS_OK(nt_status)) {
2846 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2847 DEBUG(1,("failed session setup with %s\n",
2848 nt_errstr(nt_status)));
2849 cli_shutdown(cli);
2850 return nt_status;
2853 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2854 if (!NT_STATUS_IS_OK(nt_status)) {
2855 DEBUG(1,("anonymous failed session setup with %s\n",
2856 nt_errstr(nt_status)));
2857 cli_shutdown(cli);
2858 return nt_status;
2862 if (service) {
2863 nt_status = cli_tree_connect(cli, service, service_type,
2864 password, pw_len);
2865 if (!NT_STATUS_IS_OK(nt_status)) {
2866 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2867 cli_shutdown(cli);
2868 if (NT_STATUS_IS_OK(nt_status)) {
2869 nt_status = NT_STATUS_UNSUCCESSFUL;
2871 return nt_status;
2875 nt_status = cli_init_creds(cli, user, domain, password);
2876 if (!NT_STATUS_IS_OK(nt_status)) {
2877 cli_shutdown(cli);
2878 return nt_status;
2881 *output_cli = cli;
2882 return NT_STATUS_OK;
2885 /****************************************************************************
2886 Send an old style tcon.
2887 ****************************************************************************/
2888 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2889 const char *service, const char *pass, const char *dev,
2890 uint16 *max_xmit, uint16 *tid)
2892 struct tevent_req *req;
2893 uint16_t *ret_vwv;
2894 uint8_t *bytes;
2895 NTSTATUS status;
2897 if (!lp_client_plaintext_auth() && (*pass)) {
2898 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2899 " or 'client ntlmv2 auth = yes'\n"));
2900 return NT_STATUS_ACCESS_DENIED;
2903 bytes = talloc_array(talloc_tos(), uint8_t, 0);
2904 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2905 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2906 service, strlen(service)+1, NULL);
2907 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2908 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2909 pass, strlen(pass)+1, NULL);
2910 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2911 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2912 dev, strlen(dev)+1, NULL);
2914 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
2915 talloc_get_size(bytes), bytes, &req,
2916 2, NULL, &ret_vwv, NULL, NULL);
2917 if (!NT_STATUS_IS_OK(status)) {
2918 return status;
2921 *max_xmit = SVAL(ret_vwv + 0, 0);
2922 *tid = SVAL(ret_vwv + 1, 0);
2924 return NT_STATUS_OK;
2927 /* Return a cli_state pointing at the IPC$ share for the given server */
2929 struct cli_state *get_ipc_connect(char *server,
2930 struct sockaddr_storage *server_ss,
2931 const struct user_auth_info *user_info)
2933 struct cli_state *cli;
2934 NTSTATUS nt_status;
2935 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2937 if (user_info->use_kerberos) {
2938 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2941 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2942 user_info->username ? user_info->username : "",
2943 lp_workgroup(),
2944 user_info->password ? user_info->password : "",
2945 flags,
2946 SMB_SIGNING_DEFAULT);
2948 if (NT_STATUS_IS_OK(nt_status)) {
2949 return cli;
2950 } else if (is_ipaddress(server)) {
2951 /* windows 9* needs a correct NMB name for connections */
2952 fstring remote_name;
2954 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2955 cli = get_ipc_connect(remote_name, server_ss, user_info);
2956 if (cli)
2957 return cli;
2960 return NULL;
2964 * Given the IP address of a master browser on the network, return its
2965 * workgroup and connect to it.
2967 * This function is provided to allow additional processing beyond what
2968 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2969 * browsers and obtain each master browsers' list of domains (in case the
2970 * first master browser is recently on the network and has not yet
2971 * synchronized with other master browsers and therefore does not yet have the
2972 * entire network browse list)
2975 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2976 struct sockaddr_storage *mb_ip,
2977 const struct user_auth_info *user_info,
2978 char **pp_workgroup_out)
2980 char addr[INET6_ADDRSTRLEN];
2981 fstring name;
2982 struct cli_state *cli;
2983 struct sockaddr_storage server_ss;
2985 *pp_workgroup_out = NULL;
2987 print_sockaddr(addr, sizeof(addr), mb_ip);
2988 DEBUG(99, ("Looking up name of master browser %s\n",
2989 addr));
2992 * Do a name status query to find out the name of the master browser.
2993 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2994 * master browser will not respond to a wildcard query (or, at least,
2995 * an NT4 server acting as the domain master browser will not).
2997 * We might be able to use ONLY the query on MSBROWSE, but that's not
2998 * yet been tested with all Windows versions, so until it is, leave
2999 * the original wildcard query as the first choice and fall back to
3000 * MSBROWSE if the wildcard query fails.
3002 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3003 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3005 DEBUG(99, ("Could not retrieve name status for %s\n",
3006 addr));
3007 return NULL;
3010 if (!find_master_ip(name, &server_ss)) {
3011 DEBUG(99, ("Could not find master ip for %s\n", name));
3012 return NULL;
3015 *pp_workgroup_out = talloc_strdup(ctx, name);
3017 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3019 print_sockaddr(addr, sizeof(addr), &server_ss);
3020 cli = get_ipc_connect(addr, &server_ss, user_info);
3022 return cli;
3026 * Return the IP address and workgroup of a master browser on the network, and
3027 * connect to it.
3030 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3031 const struct user_auth_info *user_info,
3032 char **pp_workgroup_out)
3034 struct sockaddr_storage *ip_list;
3035 struct cli_state *cli;
3036 int i, count;
3037 NTSTATUS status;
3039 *pp_workgroup_out = NULL;
3041 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3043 /* Go looking for workgroups by broadcasting on the local network */
3045 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3046 &ip_list, &count);
3047 if (!NT_STATUS_IS_OK(status)) {
3048 DEBUG(99, ("No master browsers responded: %s\n",
3049 nt_errstr(status)));
3050 return NULL;
3053 for (i = 0; i < count; i++) {
3054 char addr[INET6_ADDRSTRLEN];
3055 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3056 DEBUG(99, ("Found master browser %s\n", addr));
3058 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3059 user_info, pp_workgroup_out);
3060 if (cli)
3061 return(cli);
3064 return NULL;