s3:libsmb: make use of smb1cli_session_setup_{nt1,lm21}_send/recv()
[Samba.git] / source3 / libsmb / cliconnect.c
blob04b21d577c503d45098098ce55a84f25d5446648
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/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/ntlmssp/ntlmssp.h"
32 #include "auth_generic.h"
33 #include "libads/kerberos_proto.h"
34 #include "krb5_env.h"
35 #include "../lib/util/tevent_ntstatus.h"
36 #include "async_smb.h"
37 #include "libsmb/nmblib.h"
38 #include "librpc/ndr/libndr.h"
39 #include "../libcli/smb/smbXcli_base.h"
41 #define STAR_SMBSERVER "*SMBSERVER"
43 /********************************************************
44 Utility function to ensure we always return at least
45 a valid char * pointer to an empty string for the
46 cli->server_os, cli->server_type and cli->server_domain
47 strings.
48 *******************************************************/
50 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
51 const uint8_t *hdr,
52 char **dest,
53 uint8_t *src,
54 size_t srclen,
55 ssize_t *destlen)
57 *destlen = clistr_pull_talloc(mem_ctx,
58 (const char *)hdr,
59 SVAL(hdr, HDR_FLG2),
60 dest,
61 (char *)src,
62 srclen,
63 STR_TERMINATE);
64 if (*destlen == -1) {
65 return NT_STATUS_NO_MEMORY;
68 if (*dest == NULL) {
69 *dest = talloc_strdup(mem_ctx, "");
70 if (*dest == NULL) {
71 return NT_STATUS_NO_MEMORY;
74 return NT_STATUS_OK;
77 #if 0
78 /****************************************************************************
79 Do an old lanman2 style session setup.
80 ****************************************************************************/
82 struct cli_session_setup_lanman2_state {
83 struct cli_state *cli;
84 uint16_t vwv[10];
85 const char *user;
88 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
90 static struct tevent_req *cli_session_setup_lanman2_send(
91 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
92 struct cli_state *cli, const char *user,
93 const char *pass, size_t passlen,
94 const char *workgroup)
96 struct tevent_req *req, *subreq;
97 struct cli_session_setup_lanman2_state *state;
98 DATA_BLOB lm_response = data_blob_null;
99 uint16_t *vwv;
100 uint8_t *bytes;
101 char *tmp;
102 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
104 req = tevent_req_create(mem_ctx, &state,
105 struct cli_session_setup_lanman2_state);
106 if (req == NULL) {
107 return NULL;
109 state->cli = cli;
110 state->user = user;
111 vwv = state->vwv;
114 * if in share level security then don't send a password now
116 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
117 passlen = 0;
120 if (passlen > 0
121 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
122 && passlen != 24) {
124 * Encrypted mode needed, and non encrypted password
125 * supplied.
127 lm_response = data_blob(NULL, 24);
128 if (tevent_req_nomem(lm_response.data, req)) {
129 return tevent_req_post(req, ev);
132 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
133 (uint8_t *)lm_response.data)) {
134 DEBUG(1, ("Password is > 14 chars in length, and is "
135 "therefore incompatible with Lanman "
136 "authentication\n"));
137 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
138 return tevent_req_post(req, ev);
140 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
141 && passlen == 24) {
143 * Encrypted mode needed, and encrypted password
144 * supplied.
146 lm_response = data_blob(pass, passlen);
147 if (tevent_req_nomem(lm_response.data, req)) {
148 return tevent_req_post(req, ev);
150 } else if (passlen > 0) {
151 uint8_t *buf;
152 size_t converted_size;
154 * Plaintext mode needed, assume plaintext supplied.
156 buf = talloc_array(talloc_tos(), uint8_t, 0);
157 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
158 &converted_size);
159 if (tevent_req_nomem(buf, req)) {
160 return tevent_req_post(req, ev);
162 lm_response = data_blob(pass, passlen);
163 TALLOC_FREE(buf);
164 if (tevent_req_nomem(lm_response.data, req)) {
165 return tevent_req_post(req, ev);
169 SCVAL(vwv+0, 0, 0xff);
170 SCVAL(vwv+0, 1, 0);
171 SSVAL(vwv+1, 0, 0);
172 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
173 SSVAL(vwv+3, 0, 2);
174 SSVAL(vwv+4, 0, 1);
175 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
176 SSVAL(vwv+7, 0, lm_response.length);
178 bytes = talloc_array(state, uint8_t, lm_response.length);
179 if (tevent_req_nomem(bytes, req)) {
180 return tevent_req_post(req, ev);
182 if (lm_response.length != 0) {
183 memcpy(bytes, lm_response.data, lm_response.length);
185 data_blob_free(&lm_response);
187 tmp = talloc_strdup_upper(talloc_tos(), user);
188 if (tevent_req_nomem(tmp, req)) {
189 return tevent_req_post(req, ev);
191 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
192 NULL);
193 TALLOC_FREE(tmp);
195 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
196 if (tevent_req_nomem(tmp, req)) {
197 return tevent_req_post(req, ev);
199 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
200 NULL);
201 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
202 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
204 if (tevent_req_nomem(bytes, req)) {
205 return tevent_req_post(req, ev);
208 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 0, 10, vwv,
209 talloc_get_size(bytes), bytes);
210 if (tevent_req_nomem(subreq, req)) {
211 return tevent_req_post(req, ev);
213 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
214 return req;
217 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
219 struct tevent_req *req = tevent_req_callback_data(
220 subreq, struct tevent_req);
221 struct cli_session_setup_lanman2_state *state = tevent_req_data(
222 req, struct cli_session_setup_lanman2_state);
223 struct cli_state *cli = state->cli;
224 uint32_t num_bytes;
225 uint8_t *in;
226 uint8_t *inhdr;
227 uint8_t *bytes;
228 uint8_t *p;
229 NTSTATUS status;
230 ssize_t ret;
231 uint8_t wct;
232 uint16_t *vwv;
234 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
235 &num_bytes, &bytes);
236 TALLOC_FREE(subreq);
237 if (!NT_STATUS_IS_OK(status)) {
238 tevent_req_nterror(req, status);
239 return;
242 inhdr = in + NBT_HDR_SIZE;
243 p = bytes;
245 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
246 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
248 status = smb_bytes_talloc_string(cli,
249 inhdr,
250 &cli->server_os,
252 bytes+num_bytes-p,
253 &ret);
255 if (!NT_STATUS_IS_OK(status)) {
256 tevent_req_nterror(req, status);
257 return;
259 p += ret;
261 status = smb_bytes_talloc_string(cli,
262 inhdr,
263 &cli->server_type,
265 bytes+num_bytes-p,
266 &ret);
268 if (!NT_STATUS_IS_OK(status)) {
269 tevent_req_nterror(req, status);
270 return;
272 p += ret;
274 status = smb_bytes_talloc_string(cli,
275 inhdr,
276 &cli->server_domain,
278 bytes+num_bytes-p,
279 &ret);
281 if (!NT_STATUS_IS_OK(status)) {
282 tevent_req_nterror(req, status);
283 return;
285 p += ret;
287 tevent_req_done(req);
290 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
292 return tevent_req_simple_recv_ntstatus(req);
294 #endif
296 /****************************************************************************
297 Work out suitable capabilities to offer the server.
298 ****************************************************************************/
300 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
301 uint32_t sesssetup_capabilities)
303 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
306 * We only send capabilities based on the mask for:
307 * - client only flags
308 * - flags used in both directions
310 * We do not echo the server only flags, except some legacy flags.
312 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
313 * CAP_LARGE_WRITEX in order to allow us to do large reads
314 * against old Samba releases (<= 3.6.x).
316 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
319 * Session Setup specific flags CAP_DYNAMIC_REAUTH
320 * and CAP_EXTENDED_SECURITY are passed by the caller.
321 * We need that in order to do guest logins even if
322 * CAP_EXTENDED_SECURITY is negotiated.
324 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
325 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
326 client_capabilities |= sesssetup_capabilities;
328 return client_capabilities;
331 /****************************************************************************
332 Do a NT1 guest session setup.
333 ****************************************************************************/
335 struct cli_session_setup_guest_state {
336 struct cli_state *cli;
337 uint16_t vwv[13];
338 struct iovec bytes;
341 static void cli_session_setup_guest_done(struct tevent_req *subreq);
343 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
344 struct tevent_context *ev,
345 struct cli_state *cli,
346 struct tevent_req **psmbreq)
348 struct tevent_req *req, *subreq;
349 struct cli_session_setup_guest_state *state;
350 uint16_t *vwv;
351 uint8_t *bytes;
353 req = tevent_req_create(mem_ctx, &state,
354 struct cli_session_setup_guest_state);
355 if (req == NULL) {
356 return NULL;
358 state->cli = cli;
359 vwv = state->vwv;
361 SCVAL(vwv+0, 0, 0xFF);
362 SCVAL(vwv+0, 1, 0);
363 SSVAL(vwv+1, 0, 0);
364 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
365 SSVAL(vwv+3, 0, 2);
366 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
367 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
368 SSVAL(vwv+7, 0, 0);
369 SSVAL(vwv+8, 0, 0);
370 SSVAL(vwv+9, 0, 0);
371 SSVAL(vwv+10, 0, 0);
372 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
374 bytes = talloc_array(state, uint8_t, 0);
376 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
377 NULL);
378 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
379 NULL);
380 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
381 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
383 if (bytes == NULL) {
384 TALLOC_FREE(req);
385 return NULL;
388 state->bytes.iov_base = (void *)bytes;
389 state->bytes.iov_len = talloc_get_size(bytes);
391 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
392 vwv, 1, &state->bytes);
393 if (subreq == NULL) {
394 TALLOC_FREE(req);
395 return NULL;
397 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
398 *psmbreq = subreq;
399 return req;
402 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
403 struct tevent_context *ev,
404 struct cli_state *cli)
406 struct tevent_req *req, *subreq;
407 NTSTATUS status;
409 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
410 if (req == NULL) {
411 return NULL;
414 status = smb1cli_req_chain_submit(&subreq, 1);
415 if (!NT_STATUS_IS_OK(status)) {
416 tevent_req_nterror(req, status);
417 return tevent_req_post(req, ev);
419 return req;
422 static void cli_session_setup_guest_done(struct tevent_req *subreq)
424 struct tevent_req *req = tevent_req_callback_data(
425 subreq, struct tevent_req);
426 struct cli_session_setup_guest_state *state = tevent_req_data(
427 req, struct cli_session_setup_guest_state);
428 struct cli_state *cli = state->cli;
429 uint32_t num_bytes;
430 uint8_t *in;
431 uint8_t *inhdr;
432 uint8_t *bytes;
433 uint8_t *p;
434 NTSTATUS status;
435 ssize_t ret;
436 uint8_t wct;
437 uint16_t *vwv;
439 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
440 &num_bytes, &bytes);
441 TALLOC_FREE(subreq);
442 if (!NT_STATUS_IS_OK(status)) {
443 tevent_req_nterror(req, status);
444 return;
447 inhdr = in + NBT_HDR_SIZE;
448 p = bytes;
450 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
451 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
453 status = smb_bytes_talloc_string(cli,
454 inhdr,
455 &cli->server_os,
457 bytes+num_bytes-p,
458 &ret);
460 if (!NT_STATUS_IS_OK(status)) {
461 tevent_req_nterror(req, status);
462 return;
464 p += ret;
466 status = smb_bytes_talloc_string(cli,
467 inhdr,
468 &cli->server_type,
470 bytes+num_bytes-p,
471 &ret);
473 if (!NT_STATUS_IS_OK(status)) {
474 tevent_req_nterror(req, status);
475 return;
477 p += ret;
479 status = smb_bytes_talloc_string(cli,
480 inhdr,
481 &cli->server_domain,
483 bytes+num_bytes-p,
484 &ret);
486 if (!NT_STATUS_IS_OK(status)) {
487 tevent_req_nterror(req, status);
488 return;
490 p += ret;
492 tevent_req_done(req);
495 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
497 return tevent_req_simple_recv_ntstatus(req);
500 #if 0
501 /****************************************************************************
502 Do a NT1 plaintext session setup.
503 ****************************************************************************/
505 struct cli_session_setup_plain_state {
506 struct cli_state *cli;
507 uint16_t vwv[13];
508 const char *user;
511 static void cli_session_setup_plain_done(struct tevent_req *subreq);
513 static struct tevent_req *cli_session_setup_plain_send(
514 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
515 struct cli_state *cli,
516 const char *user, const char *pass, const char *workgroup)
518 struct tevent_req *req, *subreq;
519 struct cli_session_setup_plain_state *state;
520 uint16_t *vwv;
521 uint8_t *bytes;
522 size_t passlen;
523 char *version;
525 req = tevent_req_create(mem_ctx, &state,
526 struct cli_session_setup_plain_state);
527 if (req == NULL) {
528 return NULL;
530 state->cli = cli;
531 state->user = user;
532 vwv = state->vwv;
534 SCVAL(vwv+0, 0, 0xff);
535 SCVAL(vwv+0, 1, 0);
536 SSVAL(vwv+1, 0, 0);
537 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
538 SSVAL(vwv+3, 0, 2);
539 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
540 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
541 SSVAL(vwv+7, 0, 0);
542 SSVAL(vwv+8, 0, 0);
543 SSVAL(vwv+9, 0, 0);
544 SSVAL(vwv+10, 0, 0);
545 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
547 bytes = talloc_array(state, uint8_t, 0);
548 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
549 &passlen);
550 if (tevent_req_nomem(bytes, req)) {
551 return tevent_req_post(req, ev);
553 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
555 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
556 user, strlen(user)+1, NULL);
557 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
558 workgroup, strlen(workgroup)+1, NULL);
559 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
560 "Unix", 5, NULL);
562 version = talloc_asprintf(talloc_tos(), "Samba %s",
563 samba_version_string());
564 if (tevent_req_nomem(version, req)){
565 return tevent_req_post(req, ev);
567 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
568 version, strlen(version)+1, NULL);
569 TALLOC_FREE(version);
571 if (tevent_req_nomem(bytes, req)) {
572 return tevent_req_post(req, ev);
575 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 0, 13, vwv,
576 talloc_get_size(bytes), bytes);
577 if (tevent_req_nomem(subreq, req)) {
578 return tevent_req_post(req, ev);
580 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
581 return req;
584 static void cli_session_setup_plain_done(struct tevent_req *subreq)
586 struct tevent_req *req = tevent_req_callback_data(
587 subreq, struct tevent_req);
588 struct cli_session_setup_plain_state *state = tevent_req_data(
589 req, struct cli_session_setup_plain_state);
590 struct cli_state *cli = state->cli;
591 uint32_t num_bytes;
592 uint8_t *in;
593 uint8_t *inhdr;
594 uint8_t *bytes;
595 uint8_t *p;
596 NTSTATUS status;
597 ssize_t ret;
598 uint8_t wct;
599 uint16_t *vwv;
601 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
602 &num_bytes, &bytes);
603 TALLOC_FREE(subreq);
604 if (tevent_req_nterror(req, status)) {
605 return;
608 inhdr = in + NBT_HDR_SIZE;
609 p = bytes;
611 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
612 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
614 status = smb_bytes_talloc_string(cli,
615 inhdr,
616 &cli->server_os,
618 bytes+num_bytes-p,
619 &ret);
621 if (!NT_STATUS_IS_OK(status)) {
622 tevent_req_nterror(req, status);
623 return;
625 p += ret;
627 status = smb_bytes_talloc_string(cli,
628 inhdr,
629 &cli->server_type,
631 bytes+num_bytes-p,
632 &ret);
634 if (!NT_STATUS_IS_OK(status)) {
635 tevent_req_nterror(req, status);
636 return;
638 p += ret;
640 status = smb_bytes_talloc_string(cli,
641 inhdr,
642 &cli->server_domain,
644 bytes+num_bytes-p,
645 &ret);
647 if (!NT_STATUS_IS_OK(status)) {
648 tevent_req_nterror(req, status);
649 return;
651 p += ret;
653 tevent_req_done(req);
656 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
658 return tevent_req_simple_recv_ntstatus(req);
661 /****************************************************************************
662 do a NT1 NTLM/LM encrypted session setup - for when extended security
663 is not negotiated.
664 @param cli client state to create do session setup on
665 @param user username
666 @param pass *either* cleartext password (passlen !=24) or LM response.
667 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
668 @param workgroup The user's domain.
669 ****************************************************************************/
671 struct cli_session_setup_nt1_state {
672 struct cli_state *cli;
673 uint16_t vwv[13];
674 DATA_BLOB response;
675 DATA_BLOB session_key;
676 const char *user;
679 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
681 static struct tevent_req *cli_session_setup_nt1_send(
682 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
683 struct cli_state *cli, const char *user,
684 const char *pass, size_t passlen,
685 const char *ntpass, size_t ntpasslen,
686 const char *workgroup)
688 struct tevent_req *req, *subreq;
689 struct cli_session_setup_nt1_state *state;
690 DATA_BLOB lm_response = data_blob_null;
691 DATA_BLOB nt_response = data_blob_null;
692 DATA_BLOB session_key = data_blob_null;
693 uint16_t *vwv;
694 uint8_t *bytes;
695 char *workgroup_upper;
697 req = tevent_req_create(mem_ctx, &state,
698 struct cli_session_setup_nt1_state);
699 if (req == NULL) {
700 return NULL;
702 state->cli = cli;
703 state->user = user;
704 vwv = state->vwv;
706 if (passlen == 0) {
707 /* do nothing - guest login */
708 } else if (passlen != 24) {
709 if (lp_client_ntlmv2_auth()) {
710 DATA_BLOB server_chal;
711 DATA_BLOB names_blob;
713 server_chal =
714 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
718 * note that the 'workgroup' here is a best
719 * guess - we don't know the server's domain
720 * at this point. Windows clients also don't
721 * use hostname...
723 names_blob = NTLMv2_generate_names_blob(
724 NULL, NULL, workgroup);
726 if (tevent_req_nomem(names_blob.data, req)) {
727 return tevent_req_post(req, ev);
730 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
731 &server_chal, &names_blob,
732 &lm_response, &nt_response,
733 NULL, &session_key)) {
734 data_blob_free(&names_blob);
735 tevent_req_nterror(
736 req, NT_STATUS_ACCESS_DENIED);
737 return tevent_req_post(req, ev);
739 data_blob_free(&names_blob);
741 } else {
742 uchar nt_hash[16];
743 E_md4hash(pass, nt_hash);
745 #ifdef LANMAN_ONLY
746 nt_response = data_blob_null;
747 #else
748 nt_response = data_blob(NULL, 24);
749 if (tevent_req_nomem(nt_response.data, req)) {
750 return tevent_req_post(req, ev);
753 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
754 nt_response.data);
755 #endif
756 /* non encrypted password supplied. Ignore ntpass. */
757 if (lp_client_lanman_auth()) {
759 lm_response = data_blob(NULL, 24);
760 if (tevent_req_nomem(lm_response.data, req)) {
761 return tevent_req_post(req, ev);
764 if (!SMBencrypt(pass,
765 smb1cli_conn_server_challenge(cli->conn),
766 lm_response.data)) {
768 * Oops, the LM response is
769 * invalid, just put the NT
770 * response there instead
772 data_blob_free(&lm_response);
773 lm_response = data_blob(
774 nt_response.data,
775 nt_response.length);
777 } else {
779 * LM disabled, place NT# in LM field
780 * instead
782 lm_response = data_blob(
783 nt_response.data, nt_response.length);
786 if (tevent_req_nomem(lm_response.data, req)) {
787 return tevent_req_post(req, ev);
790 session_key = data_blob(NULL, 16);
791 if (tevent_req_nomem(session_key.data, req)) {
792 return tevent_req_post(req, ev);
794 #ifdef LANMAN_ONLY
795 E_deshash(pass, session_key.data);
796 memset(&session_key.data[8], '\0', 8);
797 #else
798 SMBsesskeygen_ntv1(nt_hash, session_key.data);
799 #endif
801 } else {
802 /* pre-encrypted password supplied. Only used for
803 security=server, can't do
804 signing because we don't have original key */
806 lm_response = data_blob(pass, passlen);
807 if (tevent_req_nomem(lm_response.data, req)) {
808 return tevent_req_post(req, ev);
811 nt_response = data_blob(ntpass, ntpasslen);
812 if (tevent_req_nomem(nt_response.data, req)) {
813 return tevent_req_post(req, ev);
817 #ifdef LANMAN_ONLY
818 state->response = data_blob_talloc(
819 state, lm_response.data, lm_response.length);
820 #else
821 state->response = data_blob_talloc(
822 state, nt_response.data, nt_response.length);
823 #endif
824 if (tevent_req_nomem(state->response.data, req)) {
825 return tevent_req_post(req, ev);
828 if (session_key.data) {
829 state->session_key = data_blob_talloc(
830 state, session_key.data, session_key.length);
831 if (tevent_req_nomem(state->session_key.data, req)) {
832 return tevent_req_post(req, ev);
835 data_blob_free(&session_key);
837 SCVAL(vwv+0, 0, 0xff);
838 SCVAL(vwv+0, 1, 0);
839 SSVAL(vwv+1, 0, 0);
840 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
841 SSVAL(vwv+3, 0, 2);
842 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
843 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
844 SSVAL(vwv+7, 0, lm_response.length);
845 SSVAL(vwv+8, 0, nt_response.length);
846 SSVAL(vwv+9, 0, 0);
847 SSVAL(vwv+10, 0, 0);
848 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
850 bytes = talloc_array(state, uint8_t,
851 lm_response.length + nt_response.length);
852 if (tevent_req_nomem(bytes, req)) {
853 return tevent_req_post(req, ev);
855 if (lm_response.length != 0) {
856 memcpy(bytes, lm_response.data, lm_response.length);
858 if (nt_response.length != 0) {
859 memcpy(bytes + lm_response.length,
860 nt_response.data, nt_response.length);
862 data_blob_free(&lm_response);
863 data_blob_free(&nt_response);
865 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
866 user, strlen(user)+1, NULL);
869 * Upper case here might help some NTLMv2 implementations
871 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
872 if (tevent_req_nomem(workgroup_upper, req)) {
873 return tevent_req_post(req, ev);
875 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
876 workgroup_upper, strlen(workgroup_upper)+1,
877 NULL);
878 TALLOC_FREE(workgroup_upper);
880 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
881 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
882 if (tevent_req_nomem(bytes, req)) {
883 return tevent_req_post(req, ev);
886 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 0, 13, vwv,
887 talloc_get_size(bytes), bytes);
888 if (tevent_req_nomem(subreq, req)) {
889 return tevent_req_post(req, ev);
891 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
892 return req;
895 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
897 struct tevent_req *req = tevent_req_callback_data(
898 subreq, struct tevent_req);
899 struct cli_session_setup_nt1_state *state = tevent_req_data(
900 req, struct cli_session_setup_nt1_state);
901 struct cli_state *cli = state->cli;
902 uint32_t num_bytes;
903 uint8_t *in;
904 uint8_t *inhdr;
905 uint8_t *bytes;
906 uint8_t *p;
907 NTSTATUS status;
908 ssize_t ret;
909 uint8_t wct;
910 uint16_t *vwv;
912 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
913 &num_bytes, &bytes);
914 TALLOC_FREE(subreq);
915 if (!NT_STATUS_IS_OK(status)) {
916 tevent_req_nterror(req, status);
917 return;
920 inhdr = in + NBT_HDR_SIZE;
921 p = bytes;
923 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
924 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
926 status = smb_bytes_talloc_string(cli,
927 inhdr,
928 &cli->server_os,
930 bytes+num_bytes-p,
931 &ret);
932 if (!NT_STATUS_IS_OK(status)) {
933 tevent_req_nterror(req, status);
934 return;
936 p += ret;
938 status = smb_bytes_talloc_string(cli,
939 inhdr,
940 &cli->server_type,
942 bytes+num_bytes-p,
943 &ret);
944 if (!NT_STATUS_IS_OK(status)) {
945 tevent_req_nterror(req, status);
946 return;
948 p += ret;
950 status = smb_bytes_talloc_string(cli,
951 inhdr,
952 &cli->server_domain,
954 bytes+num_bytes-p,
955 &ret);
956 if (!NT_STATUS_IS_OK(status)) {
957 tevent_req_nterror(req, status);
958 return;
960 p += ret;
962 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
963 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
964 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
965 return;
967 if (state->session_key.data) {
968 struct smbXcli_session *session = state->cli->smb1.session;
970 status = smb1cli_session_set_session_key(session,
971 state->session_key);
972 if (tevent_req_nterror(req, status)) {
973 return;
976 tevent_req_done(req);
979 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
981 return tevent_req_simple_recv_ntstatus(req);
983 #endif
985 /* The following is calculated from :
986 * (smb_size-4) = 35
987 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
988 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
989 * end of packet.
992 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
994 struct cli_sesssetup_blob_state {
995 struct tevent_context *ev;
996 struct cli_state *cli;
997 DATA_BLOB blob;
998 uint16_t max_blob_size;
1000 DATA_BLOB this_blob;
1001 struct iovec *recv_iov;
1003 NTSTATUS status;
1004 const uint8_t *inbuf;
1005 DATA_BLOB ret_blob;
1007 char *out_native_os;
1008 char *out_native_lm;
1011 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1012 struct tevent_req **psubreq);
1013 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1015 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1016 struct tevent_context *ev,
1017 struct cli_state *cli,
1018 DATA_BLOB blob)
1020 struct tevent_req *req, *subreq;
1021 struct cli_sesssetup_blob_state *state;
1022 uint32_t usable_space;
1024 req = tevent_req_create(mem_ctx, &state,
1025 struct cli_sesssetup_blob_state);
1026 if (req == NULL) {
1027 return NULL;
1029 state->ev = ev;
1030 state->blob = blob;
1031 state->cli = cli;
1033 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1034 usable_space = UINT16_MAX;
1035 } else {
1036 usable_space = cli_state_available_size(cli,
1037 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1040 if (usable_space == 0) {
1041 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1042 "(not possible to send %u bytes)\n",
1043 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1044 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1045 return tevent_req_post(req, ev);
1047 state->max_blob_size = MIN(usable_space, 0xFFFF);
1049 if (!cli_sesssetup_blob_next(state, &subreq)) {
1050 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1051 return tevent_req_post(req, ev);
1053 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1054 return req;
1057 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1058 struct tevent_req **psubreq)
1060 struct tevent_req *subreq;
1061 uint16_t thistime;
1063 thistime = MIN(state->blob.length, state->max_blob_size);
1065 state->this_blob.data = state->blob.data;
1066 state->this_blob.length = thistime;
1068 state->blob.data += thistime;
1069 state->blob.length -= thistime;
1071 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1072 subreq = smb2cli_session_setup_send(state, state->ev,
1073 state->cli->conn,
1074 state->cli->timeout,
1075 state->cli->smb2.session,
1076 0, /* in_flags */
1077 SMB2_CAP_DFS, /* in_capabilities */
1078 0, /* in_channel */
1079 0, /* in_previous_session_id */
1080 &state->this_blob);
1081 if (subreq == NULL) {
1082 return false;
1084 } else {
1085 uint16_t in_buf_size = 0;
1086 uint16_t in_mpx_max = 0;
1087 uint16_t in_vc_num = 0;
1088 uint32_t in_sess_key = 0;
1089 uint32_t in_capabilities = 0;
1090 const char *in_native_os = NULL;
1091 const char *in_native_lm = NULL;
1093 in_buf_size = CLI_BUFFER_SIZE;
1094 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
1095 in_vc_num = cli_state_get_vc_num(state->cli);
1096 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
1097 in_capabilities = cli_session_setup_capabilities(state->cli,
1098 CAP_EXTENDED_SECURITY);
1099 in_native_os = "Unix";
1100 in_native_lm = "Samba";
1103 * For now we keep the same values as before,
1104 * we may remove these in a separate commit later.
1106 in_mpx_max = 2;
1107 in_vc_num = 1;
1108 in_sess_key = 0;
1110 subreq = smb1cli_session_setup_ext_send(state, state->ev,
1111 state->cli->conn,
1112 state->cli->timeout,
1113 state->cli->smb1.pid,
1114 state->cli->smb1.session,
1115 in_buf_size,
1116 in_mpx_max,
1117 in_vc_num,
1118 in_sess_key,
1119 state->this_blob,
1120 in_capabilities,
1121 in_native_os,
1122 in_native_lm);
1123 if (subreq == NULL) {
1124 return false;
1127 *psubreq = subreq;
1128 return true;
1131 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1133 struct tevent_req *req = tevent_req_callback_data(
1134 subreq, struct tevent_req);
1135 struct cli_sesssetup_blob_state *state = tevent_req_data(
1136 req, struct cli_sesssetup_blob_state);
1137 struct cli_state *cli = state->cli;
1138 NTSTATUS status;
1140 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1141 status = smb2cli_session_setup_recv(subreq, state,
1142 &state->recv_iov,
1143 &state->ret_blob);
1144 } else {
1145 status = smb1cli_session_setup_ext_recv(subreq, state,
1146 &state->recv_iov,
1147 &state->inbuf,
1148 &state->ret_blob,
1149 &state->out_native_os,
1150 &state->out_native_lm);
1152 TALLOC_FREE(subreq);
1153 if (!NT_STATUS_IS_OK(status)
1154 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1155 tevent_req_nterror(req, status);
1156 return;
1159 if (cli->server_os == NULL) {
1160 cli->server_os = talloc_move(cli, &state->out_native_os);
1162 if (cli->server_type == NULL) {
1163 cli->server_type = talloc_move(cli, &state->out_native_lm);
1166 state->status = status;
1168 if (state->blob.length != 0) {
1170 * More to send
1172 if (!cli_sesssetup_blob_next(state, &subreq)) {
1173 tevent_req_oom(req);
1174 return;
1176 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1177 return;
1179 tevent_req_done(req);
1182 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1183 TALLOC_CTX *mem_ctx,
1184 DATA_BLOB *pblob,
1185 const uint8_t **pinbuf,
1186 struct iovec **precv_iov)
1188 struct cli_sesssetup_blob_state *state = tevent_req_data(
1189 req, struct cli_sesssetup_blob_state);
1190 NTSTATUS status;
1191 struct iovec *recv_iov;
1193 if (tevent_req_is_nterror(req, &status)) {
1194 TALLOC_FREE(state->cli->smb2.session);
1195 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1196 tevent_req_received(req);
1197 return status;
1200 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1201 if (pblob != NULL) {
1202 *pblob = state->ret_blob;
1204 if (pinbuf != NULL) {
1205 *pinbuf = state->inbuf;
1207 if (precv_iov != NULL) {
1208 *precv_iov = recv_iov;
1210 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1211 status = state->status;
1212 tevent_req_received(req);
1213 return status;
1216 #ifdef HAVE_KRB5
1218 /****************************************************************************
1219 Use in-memory credentials cache
1220 ****************************************************************************/
1222 static void use_in_memory_ccache(void) {
1223 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1226 #endif /* HAVE_KRB5 */
1228 /****************************************************************************
1229 Do a spnego/NTLMSSP encrypted session setup.
1230 ****************************************************************************/
1232 struct cli_session_setup_gensec_state {
1233 struct tevent_context *ev;
1234 struct cli_state *cli;
1235 struct auth_generic_state *auth_generic;
1236 bool is_anonymous;
1237 DATA_BLOB blob_in;
1238 const uint8_t *inbuf;
1239 struct iovec *recv_iov;
1240 DATA_BLOB blob_out;
1241 bool local_ready;
1242 bool remote_ready;
1243 DATA_BLOB session_key;
1246 static int cli_session_setup_gensec_state_destructor(
1247 struct cli_session_setup_gensec_state *state)
1249 TALLOC_FREE(state->auth_generic);
1250 data_blob_clear_free(&state->session_key);
1251 return 0;
1254 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
1255 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
1256 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
1257 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
1258 static void cli_session_setup_gensec_ready(struct tevent_req *req);
1260 static struct tevent_req *cli_session_setup_gensec_send(
1261 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1262 const char *user, const char *pass, const char *domain,
1263 enum credentials_use_kerberos krb5_state,
1264 const char *target_service,
1265 const char *target_hostname,
1266 const char *target_principal)
1268 struct tevent_req *req;
1269 struct cli_session_setup_gensec_state *state;
1270 NTSTATUS status;
1271 bool use_spnego_principal = lp_client_use_spnego_principal();
1273 req = tevent_req_create(mem_ctx, &state,
1274 struct cli_session_setup_gensec_state);
1275 if (req == NULL) {
1276 return NULL;
1278 state->ev = ev;
1279 state->cli = cli;
1281 talloc_set_destructor(
1282 state, cli_session_setup_gensec_state_destructor);
1284 if (user == NULL || strlen(user) == 0) {
1285 if (pass != NULL && strlen(pass) == 0) {
1287 * some callers pass "" as no password
1289 * gensec only handles NULL as no password.
1291 pass = NULL;
1295 status = auth_generic_client_prepare(state, &state->auth_generic);
1296 if (tevent_req_nterror(req, status)) {
1297 return tevent_req_post(req, ev);
1300 gensec_want_feature(state->auth_generic->gensec_security,
1301 GENSEC_FEATURE_SESSION_KEY);
1302 if (cli->use_ccache) {
1303 gensec_want_feature(state->auth_generic->gensec_security,
1304 GENSEC_FEATURE_NTLM_CCACHE);
1305 if (pass != NULL && strlen(pass) == 0) {
1307 * some callers pass "" as no password
1309 * GENSEC_FEATURE_NTLM_CCACHE only handles
1310 * NULL as no password.
1312 pass = NULL;
1316 status = auth_generic_set_username(state->auth_generic, user);
1317 if (tevent_req_nterror(req, status)) {
1318 return tevent_req_post(req, ev);
1321 status = auth_generic_set_domain(state->auth_generic, domain);
1322 if (tevent_req_nterror(req, status)) {
1323 return tevent_req_post(req, ev);
1326 if (cli->pw_nt_hash) {
1327 struct samr_Password nt_hash;
1328 size_t converted;
1329 bool ok;
1331 if (pass == NULL) {
1332 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1333 return tevent_req_post(req, ev);
1336 converted = strhex_to_str((char *)nt_hash.hash,
1337 sizeof(nt_hash.hash),
1338 pass, strlen(pass));
1339 if (converted != sizeof(nt_hash.hash)) {
1340 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1341 return tevent_req_post(req, ev);
1344 ok = cli_credentials_set_nt_hash(state->auth_generic->credentials,
1345 &nt_hash, CRED_SPECIFIED);
1346 if (!ok) {
1347 tevent_req_oom(req);
1348 return tevent_req_post(req, ev);
1350 } else {
1351 status = auth_generic_set_password(state->auth_generic, pass);
1352 if (tevent_req_nterror(req, status)) {
1353 return tevent_req_post(req, ev);
1357 cli_credentials_set_kerberos_state(state->auth_generic->credentials,
1358 krb5_state);
1360 if (krb5_state == CRED_DONT_USE_KERBEROS) {
1361 use_spnego_principal = false;
1364 if (target_service != NULL) {
1365 status = gensec_set_target_service(
1366 state->auth_generic->gensec_security,
1367 target_service);
1368 if (tevent_req_nterror(req, status)) {
1369 return tevent_req_post(req, ev);
1373 if (target_hostname != NULL) {
1374 status = gensec_set_target_hostname(
1375 state->auth_generic->gensec_security,
1376 target_hostname);
1377 if (tevent_req_nterror(req, status)) {
1378 return tevent_req_post(req, ev);
1382 if (target_principal != NULL) {
1383 status = gensec_set_target_principal(
1384 state->auth_generic->gensec_security,
1385 target_principal);
1386 if (tevent_req_nterror(req, status)) {
1387 return tevent_req_post(req, ev);
1389 use_spnego_principal = false;
1390 } else if (target_service != NULL && target_hostname != NULL) {
1391 use_spnego_principal = false;
1394 if (use_spnego_principal) {
1395 const DATA_BLOB *b;
1396 b = smbXcli_conn_server_gss_blob(cli->conn);
1397 if (b != NULL) {
1398 state->blob_in = *b;
1402 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
1404 status = auth_generic_client_start(state->auth_generic,
1405 GENSEC_OID_SPNEGO);
1406 if (tevent_req_nterror(req, status)) {
1407 return tevent_req_post(req, ev);
1410 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1411 state->cli->smb2.session = smbXcli_session_create(cli,
1412 cli->conn);
1413 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1414 return tevent_req_post(req, ev);
1418 cli_session_setup_gensec_local_next(req);
1419 if (!tevent_req_is_in_progress(req)) {
1420 return tevent_req_post(req, ev);
1423 return req;
1426 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
1428 struct cli_session_setup_gensec_state *state =
1429 tevent_req_data(req,
1430 struct cli_session_setup_gensec_state);
1431 struct tevent_req *subreq = NULL;
1433 if (state->local_ready) {
1434 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1435 return;
1438 subreq = gensec_update_send(state, state->ev,
1439 state->auth_generic->gensec_security,
1440 state->blob_in);
1441 if (tevent_req_nomem(subreq, req)) {
1442 return;
1444 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1447 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1449 struct tevent_req *req =
1450 tevent_req_callback_data(subreq,
1451 struct tevent_req);
1452 struct cli_session_setup_gensec_state *state =
1453 tevent_req_data(req,
1454 struct cli_session_setup_gensec_state);
1455 NTSTATUS status;
1457 status = gensec_update_recv(subreq, state, &state->blob_out);
1458 TALLOC_FREE(subreq);
1459 state->blob_in = data_blob_null;
1460 if (!NT_STATUS_IS_OK(status) &&
1461 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1463 tevent_req_nterror(req, status);
1464 return;
1467 if (NT_STATUS_IS_OK(status)) {
1468 state->local_ready = true;
1471 if (state->local_ready && state->remote_ready) {
1472 cli_session_setup_gensec_ready(req);
1473 return;
1476 cli_session_setup_gensec_remote_next(req);
1479 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1481 struct cli_session_setup_gensec_state *state =
1482 tevent_req_data(req,
1483 struct cli_session_setup_gensec_state);
1484 struct tevent_req *subreq = NULL;
1486 if (state->remote_ready) {
1487 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1488 return;
1491 subreq = cli_sesssetup_blob_send(state, state->ev,
1492 state->cli, state->blob_out);
1493 if (tevent_req_nomem(subreq, req)) {
1494 return;
1496 tevent_req_set_callback(subreq,
1497 cli_session_setup_gensec_remote_done,
1498 req);
1501 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1503 struct tevent_req *req =
1504 tevent_req_callback_data(subreq,
1505 struct tevent_req);
1506 struct cli_session_setup_gensec_state *state =
1507 tevent_req_data(req,
1508 struct cli_session_setup_gensec_state);
1509 NTSTATUS status;
1511 state->inbuf = NULL;
1512 TALLOC_FREE(state->recv_iov);
1514 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1515 &state->inbuf, &state->recv_iov);
1516 TALLOC_FREE(subreq);
1517 data_blob_free(&state->blob_out);
1518 if (!NT_STATUS_IS_OK(status) &&
1519 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1521 tevent_req_nterror(req, status);
1522 return;
1525 if (NT_STATUS_IS_OK(status)) {
1526 struct smbXcli_session *session = NULL;
1527 bool is_guest = false;
1529 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1530 session = state->cli->smb2.session;
1531 } else {
1532 session = state->cli->smb1.session;
1535 is_guest = smbXcli_session_is_guest(session);
1536 if (is_guest) {
1538 * We can't finish the gensec handshake, we don't
1539 * have a negotiated session key.
1541 * So just pretend we are completely done.
1543 * Note that smbXcli_session_is_guest()
1544 * always returns false if we require signing.
1546 state->blob_in = data_blob_null;
1547 state->local_ready = true;
1550 state->remote_ready = true;
1553 if (state->local_ready && state->remote_ready) {
1554 cli_session_setup_gensec_ready(req);
1555 return;
1558 cli_session_setup_gensec_local_next(req);
1561 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1563 struct cli_session_setup_gensec_state *state =
1564 tevent_req_data(req,
1565 struct cli_session_setup_gensec_state);
1566 const char *server_domain = NULL;
1567 NTSTATUS status;
1569 if (state->blob_in.length != 0) {
1570 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1571 return;
1574 if (state->blob_out.length != 0) {
1575 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1576 return;
1580 * gensec_ntlmssp_server_domain() returns NULL
1581 * if NTLMSSP is not used.
1583 * We can remove this later
1584 * and leave the server domain empty for SMB2 and above
1585 * in future releases.
1587 server_domain = gensec_ntlmssp_server_domain(
1588 state->auth_generic->gensec_security);
1590 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1591 TALLOC_FREE(state->cli->server_domain);
1592 state->cli->server_domain = talloc_strdup(state->cli,
1593 server_domain);
1594 if (state->cli->server_domain == NULL) {
1595 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1596 return;
1600 if (state->is_anonymous) {
1602 * Windows server does not set the
1603 * SMB2_SESSION_FLAG_IS_NULL flag.
1605 * This fix makes sure we do not try
1606 * to verify a signature on the final
1607 * session setup response.
1609 tevent_req_done(req);
1610 return;
1613 status = gensec_session_key(state->auth_generic->gensec_security,
1614 state, &state->session_key);
1615 if (tevent_req_nterror(req, status)) {
1616 return;
1619 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1620 struct smbXcli_session *session = state->cli->smb2.session;
1622 status = smb2cli_session_set_session_key(session,
1623 state->session_key,
1624 state->recv_iov);
1625 if (tevent_req_nterror(req, status)) {
1626 return;
1628 } else {
1629 struct smbXcli_session *session = state->cli->smb1.session;
1630 bool active;
1632 status = smb1cli_session_set_session_key(session,
1633 state->session_key);
1634 if (tevent_req_nterror(req, status)) {
1635 return;
1638 active = smb1cli_conn_activate_signing(state->cli->conn,
1639 state->session_key,
1640 data_blob_null);
1641 if (active) {
1642 bool ok;
1644 ok = smb1cli_conn_check_signing(state->cli->conn,
1645 state->inbuf, 1);
1646 if (!ok) {
1647 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1648 return;
1653 tevent_req_done(req);
1656 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1658 struct cli_session_setup_gensec_state *state =
1659 tevent_req_data(req,
1660 struct cli_session_setup_gensec_state);
1661 NTSTATUS status;
1663 if (tevent_req_is_nterror(req, &status)) {
1664 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1665 return status;
1667 return NT_STATUS_OK;
1670 #ifdef HAVE_KRB5
1672 static char *cli_session_setup_get_principal(
1673 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1674 const char *remote_name, const char *dest_realm)
1676 char *principal = NULL;
1678 if (!lp_client_use_spnego_principal() ||
1679 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
1680 spnego_principal = NULL;
1682 if (spnego_principal != NULL) {
1683 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1684 "principal %s\n", spnego_principal));
1685 return talloc_strdup(mem_ctx, spnego_principal);
1687 if (is_ipaddress(remote_name) ||
1688 strequal(remote_name, STAR_SMBSERVER)) {
1689 return NULL;
1692 DEBUG(3, ("cli_session_setup_spnego: using target "
1693 "hostname not SPNEGO principal\n"));
1695 if (dest_realm) {
1696 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1697 if (realm == NULL) {
1698 return NULL;
1700 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1701 remote_name, realm);
1702 TALLOC_FREE(realm);
1703 } else {
1704 principal =
1705 smb_krb5_get_principal_from_service_hostname(talloc_tos(),
1706 "cifs",
1707 remote_name,
1708 lp_realm());
1710 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1711 principal ? principal : "<null>"));
1713 return principal;
1715 #endif
1717 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1718 const char *principal)
1720 char *account, *p;
1722 account = talloc_strdup(mem_ctx, principal);
1723 if (account == NULL) {
1724 return NULL;
1726 p = strchr_m(account, '@');
1727 if (p != NULL) {
1728 *p = '\0';
1730 return account;
1733 /****************************************************************************
1734 Do a spnego encrypted session setup.
1736 user_domain: The shortname of the domain the user/machine is a member of.
1737 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1738 ****************************************************************************/
1740 struct cli_session_setup_spnego_state {
1741 struct tevent_context *ev;
1742 struct cli_state *cli;
1743 const char *target_hostname;
1744 const char *user;
1745 const char *account;
1746 const char *pass;
1747 const char *user_domain;
1748 const char *dest_realm;
1749 ADS_STATUS result;
1752 #ifdef HAVE_KRB5
1753 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1754 #endif
1756 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1758 static struct tevent_req *cli_session_setup_spnego_send(
1759 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1760 const char *user, const char *pass, const char *user_domain)
1762 struct tevent_req *req, *subreq;
1763 struct cli_session_setup_spnego_state *state;
1764 char *principal = NULL;
1765 char *OIDs[ASN1_MAX_OIDS];
1766 int i;
1767 const char *dest_realm = cli_state_remote_realm(cli);
1768 const DATA_BLOB *server_blob;
1770 req = tevent_req_create(mem_ctx, &state,
1771 struct cli_session_setup_spnego_state);
1772 if (req == NULL) {
1773 return NULL;
1775 state->ev = ev;
1776 state->cli = cli;
1777 state->user = user;
1778 state->pass = pass;
1779 state->user_domain = user_domain;
1780 state->dest_realm = dest_realm;
1782 state->account = cli_session_setup_get_account(state, user);
1783 if (tevent_req_nomem(state->account, req)) {
1784 return tevent_req_post(req, ev);
1787 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1788 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1790 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1791 (unsigned long)server_blob->length));
1793 /* the server might not even do spnego */
1794 if (server_blob->length == 0) {
1795 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1796 goto ntlmssp;
1799 #if 0
1800 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1801 #endif
1803 /* The server sent us the first part of the SPNEGO exchange in the
1804 * negprot reply. It is WRONG to depend on the principal sent in the
1805 * negprot reply, but right now we do it. If we don't receive one,
1806 * we try to best guess, then fall back to NTLM. */
1807 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1808 &principal, NULL) ||
1809 OIDs[0] == NULL) {
1810 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1811 tevent_req_done(req);
1812 return tevent_req_post(req, ev);
1815 /* make sure the server understands kerberos */
1816 for (i=0;OIDs[i];i++) {
1817 if (i == 0)
1818 DEBUG(3,("got OID=%s\n", OIDs[i]));
1819 else
1820 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1821 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1822 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1823 cli->got_kerberos_mechanism = True;
1825 talloc_free(OIDs[i]);
1828 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1830 #ifdef HAVE_KRB5
1831 /* If password is set we reauthenticate to kerberos server
1832 * and do not store results */
1834 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1835 char *tmp;
1837 tmp = cli_session_setup_get_principal(
1838 talloc_tos(), principal, state->target_hostname, dest_realm);
1839 TALLOC_FREE(principal);
1840 principal = tmp;
1842 if (pass && *pass) {
1843 int ret;
1845 use_in_memory_ccache();
1846 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1848 if (ret){
1849 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1850 TALLOC_FREE(principal);
1851 if (cli->fallback_after_kerberos)
1852 goto ntlmssp;
1853 state->result = ADS_ERROR_KRB5(ret);
1854 tevent_req_done(req);
1855 return tevent_req_post(req, ev);
1859 if (principal) {
1860 subreq = cli_session_setup_gensec_send(
1861 state, ev, cli,
1862 state->account, pass, user_domain,
1863 CRED_MUST_USE_KERBEROS,
1864 "cifs", state->target_hostname, principal);
1865 if (tevent_req_nomem(subreq, req)) {
1866 return tevent_req_post(req, ev);
1868 tevent_req_set_callback(
1869 subreq, cli_session_setup_spnego_done_krb,
1870 req);
1871 return req;
1874 #endif
1876 ntlmssp:
1877 subreq = cli_session_setup_gensec_send(
1878 state, state->ev, state->cli,
1879 state->account, state->pass, state->user_domain,
1880 CRED_DONT_USE_KERBEROS,
1881 "cifs", state->target_hostname, NULL);
1882 if (tevent_req_nomem(subreq, req)) {
1883 return tevent_req_post(req, ev);
1885 tevent_req_set_callback(
1886 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1887 return req;
1890 #ifdef HAVE_KRB5
1891 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1893 struct tevent_req *req = tevent_req_callback_data(
1894 subreq, struct tevent_req);
1895 struct cli_session_setup_spnego_state *state = tevent_req_data(
1896 req, struct cli_session_setup_spnego_state);
1897 NTSTATUS status;
1899 status = cli_session_setup_gensec_recv(subreq);
1900 TALLOC_FREE(subreq);
1901 state->result = ADS_ERROR_NT(status);
1903 if (ADS_ERR_OK(state->result) ||
1904 !state->cli->fallback_after_kerberos) {
1905 tevent_req_done(req);
1906 return;
1909 subreq = cli_session_setup_gensec_send(
1910 state, state->ev, state->cli,
1911 state->account, state->pass, state->user_domain,
1912 CRED_DONT_USE_KERBEROS,
1913 "cifs", state->target_hostname, NULL);
1914 if (tevent_req_nomem(subreq, req)) {
1915 return;
1917 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1918 req);
1920 #endif
1922 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1924 struct tevent_req *req = tevent_req_callback_data(
1925 subreq, struct tevent_req);
1926 struct cli_session_setup_spnego_state *state = tevent_req_data(
1927 req, struct cli_session_setup_spnego_state);
1928 NTSTATUS status;
1930 status = cli_session_setup_gensec_recv(subreq);
1931 TALLOC_FREE(subreq);
1932 state->result = ADS_ERROR_NT(status);
1933 tevent_req_done(req);
1936 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1938 struct cli_session_setup_spnego_state *state = tevent_req_data(
1939 req, struct cli_session_setup_spnego_state);
1941 return state->result;
1944 struct cli_session_setup_state {
1945 struct cli_state *cli;
1946 uint8_t nt_hash[16];
1947 uint8_t lm_hash[16];
1948 DATA_BLOB apassword_blob;
1949 DATA_BLOB upassword_blob;
1950 DATA_BLOB lm_session_key;
1951 DATA_BLOB session_key;
1952 char *out_native_os;
1953 char *out_native_lm;
1954 char *out_primary_domain;
1957 static void cli_session_setup_cleanup(struct tevent_req *req,
1958 enum tevent_req_state req_state)
1960 struct cli_session_setup_state *state = tevent_req_data(
1961 req, struct cli_session_setup_state);
1963 if (req_state != TEVENT_REQ_RECEIVED) {
1964 return;
1968 * We only call data_blob_clear() as
1969 * some of the blobs point to the same memory.
1971 * We let the talloc hierachy free the memory.
1973 data_blob_clear(&state->apassword_blob);
1974 data_blob_clear(&state->upassword_blob);
1975 data_blob_clear(&state->lm_session_key);
1976 data_blob_clear(&state->session_key);
1977 ZERO_STRUCTP(state);
1980 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1981 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1982 static void cli_session_setup_done_lm21(struct tevent_req *subreq);
1984 /****************************************************************************
1985 Send a session setup. The username and workgroup is in UNIX character
1986 format and must be converted to DOS codepage format before sending. If the
1987 password is in plaintext, the same should be done.
1988 ****************************************************************************/
1990 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1991 struct tevent_context *ev,
1992 struct cli_state *cli,
1993 const char *user,
1994 const char *pass,
1995 const char *workgroup)
1997 struct tevent_req *req, *subreq;
1998 struct cli_session_setup_state *state;
1999 char *p;
2000 char *user2;
2001 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2002 bool use_spnego = false;
2003 bool do_lmresponse = false;
2004 const char *username = "";
2005 const char *domain = "";
2006 const char *password = "";
2007 DATA_BLOB target_info = data_blob_null;
2008 DATA_BLOB challenge = data_blob_null;
2009 uint16_t in_buf_size = 0;
2010 uint16_t in_mpx_max = 0;
2011 uint16_t in_vc_num = 0;
2012 uint32_t in_sess_key = 0;
2013 const char *in_native_os = NULL;
2014 const char *in_native_lm = NULL;
2016 req = tevent_req_create(mem_ctx, &state,
2017 struct cli_session_setup_state);
2018 if (req == NULL) {
2019 return NULL;
2021 state->cli = cli;
2023 tevent_req_set_cleanup_fn(req, cli_session_setup_cleanup);
2025 if (user) {
2026 user2 = talloc_strdup(state, user);
2027 } else {
2028 user2 = talloc_strdup(state, "");
2030 if (user2 == NULL) {
2031 tevent_req_oom(req);
2032 return tevent_req_post(req, ev);
2035 if (!workgroup) {
2036 workgroup = "";
2039 /* allow for workgroups as part of the username */
2040 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2041 (p=strchr_m(user2,*lp_winbind_separator()))) {
2042 *p = 0;
2043 user = p+1;
2044 if (!strupper_m(user2)) {
2045 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2046 return tevent_req_post(req, ev);
2048 workgroup = user2;
2052 * Now work out what sort of session setup we are going to
2053 * do. I have split this into separate functions to make the flow a bit
2054 * easier to understand (tridge).
2056 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2057 use_spnego = false;
2058 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2059 use_spnego = true;
2060 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2062 * if the server supports extended security then use SPNEGO
2063 * even for anonymous connections.
2065 use_spnego = true;
2066 } else {
2067 use_spnego = false;
2070 if (use_spnego) {
2071 subreq = cli_session_setup_spnego_send(
2072 state, ev, cli, user, pass, workgroup);
2073 if (tevent_req_nomem(subreq, req)) {
2074 return tevent_req_post(req, ev);
2076 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2077 req);
2078 return req;
2081 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2083 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
2084 * this step against older servers.
2086 tevent_req_done(req);
2087 return tevent_req_post(req, ev);
2090 if (user == NULL || strlen(user) == 0) {
2092 * Do an anonymous session setup
2094 goto non_spnego_creds_done;
2097 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2099 * Do an anonymous session setup,
2100 * the password is passed via the tree connect.
2102 goto non_spnego_creds_done;
2105 username = user;
2106 domain = workgroup;
2107 if (pass != NULL) {
2108 password = pass;
2111 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2112 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
2113 uint8_t *bytes = NULL;
2114 size_t bytes_len = 0;
2115 const char *pw = password;
2116 size_t pw_len = 0;
2118 if (pw == NULL) {
2119 pw = "";
2121 pw_len = strlen(pw) + 1;
2123 if (!lp_client_plaintext_auth()) {
2124 DEBUG(1, ("Server requested PLAINTEXT password but "
2125 "'client plaintext auth = no'\n"));
2126 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2127 return tevent_req_post(req, ev);
2130 bytes = talloc_array(state, uint8_t, 0);
2131 bytes = trans2_bytes_push_str(bytes, use_unicode,
2132 pw, pw_len, &bytes_len);
2133 if (tevent_req_nomem(bytes, req)) {
2134 return tevent_req_post(req, ev);
2137 if (use_unicode) {
2139 * CAP_UNICODE, can only be negotiated by NT1.
2141 state->upassword_blob = data_blob_const(bytes,
2142 bytes_len);
2143 } else {
2144 state->apassword_blob = data_blob_const(bytes,
2145 bytes_len);
2148 goto non_spnego_creds_done;
2151 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
2152 E_md4hash(password, state->nt_hash);
2154 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
2155 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2157 * Don't send an NTLMv2 response without NTLMSSP if we
2158 * want to use spnego support.
2160 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2161 " but 'client use spnego = yes'"
2162 " and 'client ntlmv2 auth = yes' is set\n"));
2163 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2164 return tevent_req_post(req, ev);
2167 if (lp_client_ntlmv2_auth()) {
2168 bool ok;
2171 * note that the 'domain' here is a best
2172 * guess - we don't know the server's domain
2173 * at this point. Windows clients also don't
2174 * use hostname...
2176 target_info = NTLMv2_generate_names_blob(state,
2177 NULL,
2178 domain);
2179 if (tevent_req_nomem(target_info.data, req)) {
2180 return tevent_req_post(req, ev);
2183 ok = SMBNTLMv2encrypt_hash(state,
2184 username,
2185 domain,
2186 state->nt_hash,
2187 &challenge,
2188 NULL, /* server_timestamp */
2189 &target_info,
2190 &state->apassword_blob,
2191 &state->upassword_blob,
2192 &state->lm_session_key,
2193 &state->session_key);
2194 if (!ok) {
2195 tevent_req_nterror(req,
2196 NT_STATUS_ACCESS_DENIED);
2197 return tevent_req_post(req, ev);
2199 } else {
2200 state->upassword_blob = data_blob_talloc_zero(state, 24);
2201 if (tevent_req_nomem(state->upassword_blob.data, req)) {
2202 return tevent_req_post(req, ev);
2204 state->session_key = data_blob_talloc_zero(state, 16);
2205 if (tevent_req_nomem(state->session_key.data, req)) {
2206 return tevent_req_post(req, ev);
2209 SMBNTencrypt_hash(state->nt_hash, challenge.data,
2210 state->upassword_blob.data);
2211 SMBsesskeygen_ntv1(state->nt_hash,
2212 state->session_key.data);
2214 if (lp_client_lanman_auth()) {
2215 do_lmresponse = E_deshash(password,
2216 state->lm_hash);
2219 } else {
2220 if (!lp_client_lanman_auth()) {
2221 DEBUG(1, ("Server requested LM password but "
2222 "'client lanman auth = no' "
2223 "or 'client ntlmv2 auth = yes' is set\n"));
2224 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2225 return tevent_req_post(req, ev);
2228 do_lmresponse = E_deshash(password, state->lm_hash);
2231 if (do_lmresponse) {
2232 state->apassword_blob = data_blob_talloc_zero(state, 24);
2233 if (tevent_req_nomem(state->apassword_blob.data, req)) {
2234 return tevent_req_post(req, ev);
2237 SMBencrypt_hash(state->lm_hash,
2238 challenge.data,
2239 state->apassword_blob.data);
2242 if (state->apassword_blob.length == 0) {
2243 if (state->upassword_blob.length == 0) {
2244 DEBUG(1, ("Password is > 14 chars in length, and is "
2245 "therefore incompatible with Lanman "
2246 "authentication\n"));
2247 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2248 return tevent_req_post(req, ev);
2252 * LM disabled, place NT# in LM field
2253 * instead
2255 state->apassword_blob = state->upassword_blob;
2258 non_spnego_creds_done:
2260 in_buf_size = CLI_BUFFER_SIZE;
2261 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
2262 in_vc_num = cli_state_get_vc_num(cli);
2263 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
2264 in_native_os = "Unix";
2265 in_native_lm = "Samba";
2267 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
2268 uint32_t in_capabilities = 0;
2270 in_capabilities = cli_session_setup_capabilities(cli, 0);
2273 * For now we keep the same values as before,
2274 * we may remove these in a separate commit later.
2276 in_mpx_max = 2;
2278 subreq = smb1cli_session_setup_nt1_send(state, ev,
2279 cli->conn,
2280 cli->timeout,
2281 cli->smb1.pid,
2282 cli->smb1.session,
2283 in_buf_size,
2284 in_mpx_max,
2285 in_vc_num,
2286 in_sess_key,
2287 username,
2288 domain,
2289 state->apassword_blob,
2290 state->upassword_blob,
2291 in_capabilities,
2292 in_native_os,
2293 in_native_lm);
2294 if (tevent_req_nomem(subreq, req)) {
2295 return tevent_req_post(req, ev);
2297 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2298 req);
2299 return req;
2303 * For now we keep the same values as before,
2304 * we may remove these in a separate commit later.
2306 in_mpx_max = 2;
2307 in_vc_num = 1;
2309 subreq = smb1cli_session_setup_lm21_send(state, ev,
2310 cli->conn,
2311 cli->timeout,
2312 cli->smb1.pid,
2313 cli->smb1.session,
2314 in_buf_size,
2315 in_mpx_max,
2316 in_vc_num,
2317 in_sess_key,
2318 username,
2319 domain,
2320 state->apassword_blob,
2321 in_native_os,
2322 in_native_lm);
2323 if (tevent_req_nomem(subreq, req)) {
2324 return tevent_req_post(req, ev);
2326 tevent_req_set_callback(subreq, cli_session_setup_done_lm21,
2327 req);
2328 return req;
2331 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2333 struct tevent_req *req = tevent_req_callback_data(
2334 subreq, struct tevent_req);
2335 ADS_STATUS status;
2337 status = cli_session_setup_spnego_recv(subreq);
2338 TALLOC_FREE(subreq);
2339 if (!ADS_ERR_OK(status)) {
2340 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2341 tevent_req_nterror(req, ads_ntstatus(status));
2342 return;
2344 tevent_req_done(req);
2347 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2349 struct tevent_req *req = tevent_req_callback_data(
2350 subreq, struct tevent_req);
2351 struct cli_session_setup_state *state = tevent_req_data(
2352 req, struct cli_session_setup_state);
2353 struct cli_state *cli = state->cli;
2354 NTSTATUS status;
2355 struct iovec *recv_iov = NULL;
2356 const uint8_t *inbuf = NULL;
2357 bool ok;
2359 status = smb1cli_session_setup_nt1_recv(subreq, state,
2360 &recv_iov,
2361 &inbuf,
2362 &state->out_native_os,
2363 &state->out_native_lm,
2364 &state->out_primary_domain);
2365 TALLOC_FREE(subreq);
2366 if (!NT_STATUS_IS_OK(status)) {
2367 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
2368 tevent_req_nterror(req, status);
2369 return;
2372 if (cli->server_os == NULL) {
2373 cli->server_os = talloc_move(cli, &state->out_native_os);
2375 if (cli->server_type == NULL) {
2376 cli->server_type = talloc_move(cli, &state->out_native_lm);
2378 if (cli->server_domain == NULL) {
2379 cli->server_domain = talloc_move(cli, &state->out_primary_domain);
2382 ok = smb1cli_conn_activate_signing(cli->conn,
2383 state->session_key,
2384 state->upassword_blob);
2385 if (ok) {
2386 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
2387 if (!ok) {
2388 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2389 return;
2393 if (state->session_key.data) {
2394 struct smbXcli_session *session = cli->smb1.session;
2396 status = smb1cli_session_set_session_key(session,
2397 state->session_key);
2398 if (tevent_req_nterror(req, status)) {
2399 return;
2403 tevent_req_done(req);
2406 static void cli_session_setup_done_lm21(struct tevent_req *subreq)
2408 struct tevent_req *req = tevent_req_callback_data(
2409 subreq, struct tevent_req);
2410 struct cli_session_setup_state *state = tevent_req_data(
2411 req, struct cli_session_setup_state);
2412 struct cli_state *cli = state->cli;
2413 NTSTATUS status;
2415 status = smb1cli_session_setup_lm21_recv(subreq, state,
2416 &state->out_native_os,
2417 &state->out_native_lm);
2418 TALLOC_FREE(subreq);
2419 if (!NT_STATUS_IS_OK(status)) {
2420 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
2421 tevent_req_nterror(req, status);
2422 return;
2425 if (cli->server_os == NULL) {
2426 cli->server_os = talloc_move(cli, &state->out_native_os);
2428 if (cli->server_type == NULL) {
2429 cli->server_type = talloc_move(cli, &state->out_native_lm);
2432 tevent_req_done(req);
2435 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2437 return tevent_req_simple_recv_ntstatus(req);
2440 NTSTATUS cli_session_setup(struct cli_state *cli,
2441 const char *user,
2442 const char *pass,
2443 const char *workgroup)
2445 struct tevent_context *ev;
2446 struct tevent_req *req;
2447 NTSTATUS status = NT_STATUS_NO_MEMORY;
2449 if (smbXcli_conn_has_async_calls(cli->conn)) {
2450 return NT_STATUS_INVALID_PARAMETER;
2452 ev = samba_tevent_context_init(talloc_tos());
2453 if (ev == NULL) {
2454 goto fail;
2456 req = cli_session_setup_send(ev, ev, cli, user, pass, workgroup);
2457 if (req == NULL) {
2458 goto fail;
2460 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2461 goto fail;
2463 status = cli_session_setup_recv(req);
2464 fail:
2465 TALLOC_FREE(ev);
2466 return status;
2469 /****************************************************************************
2470 Send a uloggoff.
2471 *****************************************************************************/
2473 struct cli_ulogoff_state {
2474 struct cli_state *cli;
2475 uint16_t vwv[3];
2478 static void cli_ulogoff_done(struct tevent_req *subreq);
2480 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2481 struct tevent_context *ev,
2482 struct cli_state *cli)
2484 struct tevent_req *req, *subreq;
2485 struct cli_ulogoff_state *state;
2487 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2488 if (req == NULL) {
2489 return NULL;
2491 state->cli = cli;
2493 SCVAL(state->vwv+0, 0, 0xFF);
2494 SCVAL(state->vwv+1, 0, 0);
2495 SSVAL(state->vwv+2, 0, 0);
2497 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
2498 0, NULL);
2499 if (tevent_req_nomem(subreq, req)) {
2500 return tevent_req_post(req, ev);
2502 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2503 return req;
2506 static void cli_ulogoff_done(struct tevent_req *subreq)
2508 struct tevent_req *req = tevent_req_callback_data(
2509 subreq, struct tevent_req);
2510 struct cli_ulogoff_state *state = tevent_req_data(
2511 req, struct cli_ulogoff_state);
2512 NTSTATUS status;
2514 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2515 if (!NT_STATUS_IS_OK(status)) {
2516 tevent_req_nterror(req, status);
2517 return;
2519 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2520 tevent_req_done(req);
2523 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2525 return tevent_req_simple_recv_ntstatus(req);
2528 NTSTATUS cli_ulogoff(struct cli_state *cli)
2530 struct tevent_context *ev;
2531 struct tevent_req *req;
2532 NTSTATUS status = NT_STATUS_NO_MEMORY;
2534 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2535 status = smb2cli_logoff(cli->conn,
2536 cli->timeout,
2537 cli->smb2.session);
2538 if (!NT_STATUS_IS_OK(status)) {
2539 return status;
2541 smb2cli_session_set_id_and_flags(cli->smb2.session,
2542 UINT64_MAX, 0);
2543 return NT_STATUS_OK;
2546 if (smbXcli_conn_has_async_calls(cli->conn)) {
2547 return NT_STATUS_INVALID_PARAMETER;
2549 ev = samba_tevent_context_init(talloc_tos());
2550 if (ev == NULL) {
2551 goto fail;
2553 req = cli_ulogoff_send(ev, ev, cli);
2554 if (req == NULL) {
2555 goto fail;
2557 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2558 goto fail;
2560 status = cli_ulogoff_recv(req);
2561 fail:
2562 TALLOC_FREE(ev);
2563 return status;
2566 /****************************************************************************
2567 Send a tconX.
2568 ****************************************************************************/
2570 struct cli_tcon_andx_state {
2571 struct cli_state *cli;
2572 uint16_t vwv[4];
2573 struct iovec bytes;
2576 static void cli_tcon_andx_done(struct tevent_req *subreq);
2578 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2579 struct tevent_context *ev,
2580 struct cli_state *cli,
2581 const char *share, const char *dev,
2582 const char *pass, int passlen,
2583 struct tevent_req **psmbreq)
2585 struct tevent_req *req, *subreq;
2586 struct cli_tcon_andx_state *state;
2587 uint8_t p24[24];
2588 uint16_t *vwv;
2589 char *tmp = NULL;
2590 uint8_t *bytes;
2591 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2592 uint16_t tcon_flags = 0;
2594 *psmbreq = NULL;
2596 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2597 if (req == NULL) {
2598 return NULL;
2600 state->cli = cli;
2601 vwv = state->vwv;
2603 cli->share = talloc_strdup(cli, share);
2604 if (!cli->share) {
2605 return NULL;
2608 /* in user level security don't send a password now */
2609 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2610 passlen = 1;
2611 pass = "";
2612 } else if (pass == NULL) {
2613 DEBUG(1, ("Server not using user level security and no "
2614 "password supplied.\n"));
2615 goto access_denied;
2618 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2619 *pass && passlen != 24) {
2620 if (!lp_client_lanman_auth()) {
2621 DEBUG(1, ("Server requested LANMAN password "
2622 "(share-level security) but "
2623 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2624 goto access_denied;
2628 * Non-encrypted passwords - convert to DOS codepage before
2629 * encryption.
2631 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2632 passlen = 24;
2633 pass = (const char *)p24;
2634 } else {
2635 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2636 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2637 == 0) {
2638 uint8_t *tmp_pass;
2640 if (!lp_client_plaintext_auth() && (*pass)) {
2641 DEBUG(1, ("Server requested PLAINTEXT "
2642 "password but "
2643 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2644 goto access_denied;
2648 * Non-encrypted passwords - convert to DOS codepage
2649 * before using.
2651 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2652 if (tevent_req_nomem(tmp_pass, req)) {
2653 return tevent_req_post(req, ev);
2655 tmp_pass = trans2_bytes_push_str(tmp_pass,
2656 false, /* always DOS */
2657 pass,
2658 passlen,
2659 NULL);
2660 if (tevent_req_nomem(tmp_pass, req)) {
2661 return tevent_req_post(req, ev);
2663 pass = (const char *)tmp_pass;
2664 passlen = talloc_get_size(tmp_pass);
2668 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2669 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2671 SCVAL(vwv+0, 0, 0xFF);
2672 SCVAL(vwv+0, 1, 0);
2673 SSVAL(vwv+1, 0, 0);
2674 SSVAL(vwv+2, 0, tcon_flags);
2675 SSVAL(vwv+3, 0, passlen);
2677 if (passlen && pass) {
2678 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2679 } else {
2680 bytes = talloc_array(state, uint8_t, 0);
2684 * Add the sharename
2686 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2687 smbXcli_conn_remote_name(cli->conn), share);
2688 if (tmp == NULL) {
2689 TALLOC_FREE(req);
2690 return NULL;
2692 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2693 NULL);
2694 TALLOC_FREE(tmp);
2697 * Add the devicetype
2699 tmp = talloc_strdup_upper(talloc_tos(), dev);
2700 if (tmp == NULL) {
2701 TALLOC_FREE(req);
2702 return NULL;
2704 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2705 TALLOC_FREE(tmp);
2707 if (bytes == NULL) {
2708 TALLOC_FREE(req);
2709 return NULL;
2712 state->bytes.iov_base = (void *)bytes;
2713 state->bytes.iov_len = talloc_get_size(bytes);
2715 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2716 1, &state->bytes);
2717 if (subreq == NULL) {
2718 TALLOC_FREE(req);
2719 return NULL;
2721 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2722 *psmbreq = subreq;
2723 return req;
2725 access_denied:
2726 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2727 return tevent_req_post(req, ev);
2730 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2731 struct tevent_context *ev,
2732 struct cli_state *cli,
2733 const char *share, const char *dev,
2734 const char *pass, int passlen)
2736 struct tevent_req *req, *subreq;
2737 NTSTATUS status;
2739 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2740 &subreq);
2741 if (req == NULL) {
2742 return NULL;
2744 if (subreq == NULL) {
2745 return req;
2747 status = smb1cli_req_chain_submit(&subreq, 1);
2748 if (!NT_STATUS_IS_OK(status)) {
2749 tevent_req_nterror(req, status);
2750 return tevent_req_post(req, ev);
2752 return req;
2755 static void cli_tcon_andx_done(struct tevent_req *subreq)
2757 struct tevent_req *req = tevent_req_callback_data(
2758 subreq, struct tevent_req);
2759 struct cli_tcon_andx_state *state = tevent_req_data(
2760 req, struct cli_tcon_andx_state);
2761 struct cli_state *cli = state->cli;
2762 uint8_t *in;
2763 uint8_t *inhdr;
2764 uint8_t wct;
2765 uint16_t *vwv;
2766 uint32_t num_bytes;
2767 uint8_t *bytes;
2768 NTSTATUS status;
2769 uint16_t optional_support = 0;
2771 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2772 &num_bytes, &bytes);
2773 TALLOC_FREE(subreq);
2774 if (!NT_STATUS_IS_OK(status)) {
2775 tevent_req_nterror(req, status);
2776 return;
2779 inhdr = in + NBT_HDR_SIZE;
2781 if (num_bytes) {
2782 if (clistr_pull_talloc(cli,
2783 (const char *)inhdr,
2784 SVAL(inhdr, HDR_FLG2),
2785 &cli->dev,
2786 bytes,
2787 num_bytes,
2788 STR_TERMINATE|STR_ASCII) == -1) {
2789 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2790 return;
2792 } else {
2793 cli->dev = talloc_strdup(cli, "");
2794 if (cli->dev == NULL) {
2795 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2796 return;
2800 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2801 /* almost certainly win95 - enable bug fixes */
2802 cli->win95 = True;
2806 * Make sure that we have the optional support 16-bit field. WCT > 2.
2807 * Avoids issues when connecting to Win9x boxes sharing files
2810 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2811 optional_support = SVAL(vwv+2, 0);
2814 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2815 smb1cli_session_protect_session_key(cli->smb1.session);
2818 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2819 SVAL(inhdr, HDR_TID),
2820 optional_support,
2821 0, /* maximal_access */
2822 0, /* guest_maximal_access */
2823 NULL, /* service */
2824 NULL); /* fs_type */
2826 tevent_req_done(req);
2829 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2831 return tevent_req_simple_recv_ntstatus(req);
2834 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2835 const char *dev, const char *pass, int passlen)
2837 TALLOC_CTX *frame = talloc_stackframe();
2838 struct tevent_context *ev;
2839 struct tevent_req *req;
2840 NTSTATUS status = NT_STATUS_NO_MEMORY;
2842 if (smbXcli_conn_has_async_calls(cli->conn)) {
2844 * Can't use sync call while an async call is in flight
2846 status = NT_STATUS_INVALID_PARAMETER;
2847 goto fail;
2850 ev = samba_tevent_context_init(frame);
2851 if (ev == NULL) {
2852 goto fail;
2855 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2856 if (req == NULL) {
2857 goto fail;
2860 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2861 goto fail;
2864 status = cli_tcon_andx_recv(req);
2865 fail:
2866 TALLOC_FREE(frame);
2867 return status;
2870 struct cli_tree_connect_state {
2871 struct cli_state *cli;
2874 static struct tevent_req *cli_raw_tcon_send(
2875 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2876 const char *service, const char *pass, const char *dev);
2877 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2878 uint16_t *max_xmit, uint16_t *tid);
2880 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2881 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2882 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2884 static struct tevent_req *cli_tree_connect_send(
2885 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2886 const char *share, const char *dev, const char *pass, int passlen)
2888 struct tevent_req *req, *subreq;
2889 struct cli_tree_connect_state *state;
2891 req = tevent_req_create(mem_ctx, &state,
2892 struct cli_tree_connect_state);
2893 if (req == NULL) {
2894 return NULL;
2896 state->cli = cli;
2898 cli->share = talloc_strdup(cli, share);
2899 if (tevent_req_nomem(cli->share, req)) {
2900 return tevent_req_post(req, ev);
2903 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2904 char *unc;
2906 cli->smb2.tcon = smbXcli_tcon_create(cli);
2907 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2908 return tevent_req_post(req, ev);
2911 unc = talloc_asprintf(state, "\\\\%s\\%s",
2912 smbXcli_conn_remote_name(cli->conn),
2913 share);
2914 if (tevent_req_nomem(unc, req)) {
2915 return tevent_req_post(req, ev);
2918 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2919 cli->smb2.session, cli->smb2.tcon,
2920 0, /* flags */
2921 unc);
2922 if (tevent_req_nomem(subreq, req)) {
2923 return tevent_req_post(req, ev);
2925 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2926 req);
2927 return req;
2930 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2931 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2932 pass, passlen);
2933 if (tevent_req_nomem(subreq, req)) {
2934 return tevent_req_post(req, ev);
2936 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2937 req);
2938 return req;
2941 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2942 if (tevent_req_nomem(subreq, req)) {
2943 return tevent_req_post(req, ev);
2945 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2947 return req;
2950 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2952 tevent_req_simple_finish_ntstatus(
2953 subreq, smb2cli_tcon_recv(subreq));
2956 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2958 tevent_req_simple_finish_ntstatus(
2959 subreq, cli_tcon_andx_recv(subreq));
2962 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2964 struct tevent_req *req = tevent_req_callback_data(
2965 subreq, struct tevent_req);
2966 struct cli_tree_connect_state *state = tevent_req_data(
2967 req, struct cli_tree_connect_state);
2968 NTSTATUS status;
2969 uint16_t max_xmit = 0;
2970 uint16_t tid = 0;
2972 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2973 if (tevent_req_nterror(req, status)) {
2974 return;
2977 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2978 tid,
2979 0, /* optional_support */
2980 0, /* maximal_access */
2981 0, /* guest_maximal_access */
2982 NULL, /* service */
2983 NULL); /* fs_type */
2985 tevent_req_done(req);
2988 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2990 return tevent_req_simple_recv_ntstatus(req);
2993 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2994 const char *dev, const char *pass, int passlen)
2996 struct tevent_context *ev;
2997 struct tevent_req *req;
2998 NTSTATUS status = NT_STATUS_NO_MEMORY;
3000 if (smbXcli_conn_has_async_calls(cli->conn)) {
3001 return NT_STATUS_INVALID_PARAMETER;
3003 ev = samba_tevent_context_init(talloc_tos());
3004 if (ev == NULL) {
3005 goto fail;
3007 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
3008 if (req == NULL) {
3009 goto fail;
3011 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3012 goto fail;
3014 status = cli_tree_connect_recv(req);
3015 fail:
3016 TALLOC_FREE(ev);
3017 return status;
3020 /****************************************************************************
3021 Send a tree disconnect.
3022 ****************************************************************************/
3024 struct cli_tdis_state {
3025 struct cli_state *cli;
3028 static void cli_tdis_done(struct tevent_req *subreq);
3030 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
3031 struct tevent_context *ev,
3032 struct cli_state *cli)
3034 struct tevent_req *req, *subreq;
3035 struct cli_tdis_state *state;
3037 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
3038 if (req == NULL) {
3039 return NULL;
3041 state->cli = cli;
3043 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
3044 if (tevent_req_nomem(subreq, req)) {
3045 return tevent_req_post(req, ev);
3047 tevent_req_set_callback(subreq, cli_tdis_done, req);
3048 return req;
3051 static void cli_tdis_done(struct tevent_req *subreq)
3053 struct tevent_req *req = tevent_req_callback_data(
3054 subreq, struct tevent_req);
3055 struct cli_tdis_state *state = tevent_req_data(
3056 req, struct cli_tdis_state);
3057 NTSTATUS status;
3059 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3060 TALLOC_FREE(subreq);
3061 if (!NT_STATUS_IS_OK(status)) {
3062 tevent_req_nterror(req, status);
3063 return;
3065 cli_state_set_tid(state->cli, UINT16_MAX);
3066 tevent_req_done(req);
3069 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
3071 return tevent_req_simple_recv_ntstatus(req);
3074 NTSTATUS cli_tdis(struct cli_state *cli)
3076 struct tevent_context *ev;
3077 struct tevent_req *req;
3078 NTSTATUS status = NT_STATUS_NO_MEMORY;
3080 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3081 return smb2cli_tdis(cli->conn,
3082 cli->timeout,
3083 cli->smb2.session,
3084 cli->smb2.tcon);
3087 if (smbXcli_conn_has_async_calls(cli->conn)) {
3088 return NT_STATUS_INVALID_PARAMETER;
3090 ev = samba_tevent_context_init(talloc_tos());
3091 if (ev == NULL) {
3092 goto fail;
3094 req = cli_tdis_send(ev, ev, cli);
3095 if (req == NULL) {
3096 goto fail;
3098 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3099 goto fail;
3101 status = cli_tdis_recv(req);
3102 fail:
3103 TALLOC_FREE(ev);
3104 return status;
3107 struct cli_connect_sock_state {
3108 const char **called_names;
3109 const char **calling_names;
3110 int *called_types;
3111 int fd;
3112 uint16_t port;
3115 static void cli_connect_sock_done(struct tevent_req *subreq);
3118 * Async only if we don't have to look up the name, i.e. "pss" is set with a
3119 * nonzero address.
3122 static struct tevent_req *cli_connect_sock_send(
3123 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3124 const char *host, int name_type, const struct sockaddr_storage *pss,
3125 const char *myname, uint16_t port)
3127 struct tevent_req *req, *subreq;
3128 struct cli_connect_sock_state *state;
3129 const char *prog;
3130 struct sockaddr_storage *addrs;
3131 unsigned i, num_addrs;
3132 NTSTATUS status;
3134 req = tevent_req_create(mem_ctx, &state,
3135 struct cli_connect_sock_state);
3136 if (req == NULL) {
3137 return NULL;
3140 prog = getenv("LIBSMB_PROG");
3141 if (prog != NULL) {
3142 state->fd = sock_exec(prog);
3143 if (state->fd == -1) {
3144 status = map_nt_error_from_unix(errno);
3145 tevent_req_nterror(req, status);
3146 } else {
3147 state->port = 0;
3148 tevent_req_done(req);
3150 return tevent_req_post(req, ev);
3153 if ((pss == NULL) || is_zero_addr(pss)) {
3156 * Here we cheat. resolve_name_list is not async at all. So
3157 * this call will only be really async if the name lookup has
3158 * been done externally.
3161 status = resolve_name_list(state, host, name_type,
3162 &addrs, &num_addrs);
3163 if (!NT_STATUS_IS_OK(status)) {
3164 tevent_req_nterror(req, status);
3165 return tevent_req_post(req, ev);
3167 } else {
3168 addrs = talloc_array(state, struct sockaddr_storage, 1);
3169 if (tevent_req_nomem(addrs, req)) {
3170 return tevent_req_post(req, ev);
3172 addrs[0] = *pss;
3173 num_addrs = 1;
3176 state->called_names = talloc_array(state, const char *, num_addrs);
3177 if (tevent_req_nomem(state->called_names, req)) {
3178 return tevent_req_post(req, ev);
3180 state->called_types = talloc_array(state, int, num_addrs);
3181 if (tevent_req_nomem(state->called_types, req)) {
3182 return tevent_req_post(req, ev);
3184 state->calling_names = talloc_array(state, const char *, num_addrs);
3185 if (tevent_req_nomem(state->calling_names, req)) {
3186 return tevent_req_post(req, ev);
3188 for (i=0; i<num_addrs; i++) {
3189 state->called_names[i] = host;
3190 state->called_types[i] = name_type;
3191 state->calling_names[i] = myname;
3194 subreq = smbsock_any_connect_send(
3195 state, ev, addrs, state->called_names, state->called_types,
3196 state->calling_names, NULL, num_addrs, port);
3197 if (tevent_req_nomem(subreq, req)) {
3198 return tevent_req_post(req, ev);
3200 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
3201 return req;
3204 static void cli_connect_sock_done(struct tevent_req *subreq)
3206 struct tevent_req *req = tevent_req_callback_data(
3207 subreq, struct tevent_req);
3208 struct cli_connect_sock_state *state = tevent_req_data(
3209 req, struct cli_connect_sock_state);
3210 NTSTATUS status;
3212 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3213 &state->port);
3214 TALLOC_FREE(subreq);
3215 if (tevent_req_nterror(req, status)) {
3216 return;
3218 set_socket_options(state->fd, lp_socket_options());
3219 tevent_req_done(req);
3222 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3223 int *pfd, uint16_t *pport)
3225 struct cli_connect_sock_state *state = tevent_req_data(
3226 req, struct cli_connect_sock_state);
3227 NTSTATUS status;
3229 if (tevent_req_is_nterror(req, &status)) {
3230 return status;
3232 *pfd = state->fd;
3233 *pport = state->port;
3234 return NT_STATUS_OK;
3237 struct cli_connect_nb_state {
3238 const char *desthost;
3239 int signing_state;
3240 int flags;
3241 struct cli_state *cli;
3244 static void cli_connect_nb_done(struct tevent_req *subreq);
3246 static struct tevent_req *cli_connect_nb_send(
3247 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3248 const char *host, const struct sockaddr_storage *dest_ss,
3249 uint16_t port, int name_type, const char *myname,
3250 int signing_state, int flags)
3252 struct tevent_req *req, *subreq;
3253 struct cli_connect_nb_state *state;
3255 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3256 if (req == NULL) {
3257 return NULL;
3259 state->signing_state = signing_state;
3260 state->flags = flags;
3262 if (host != NULL) {
3263 char *p = strchr(host, '#');
3265 if (p != NULL) {
3266 name_type = strtol(p+1, NULL, 16);
3267 host = talloc_strndup(state, host, p - host);
3268 if (tevent_req_nomem(host, req)) {
3269 return tevent_req_post(req, ev);
3273 state->desthost = host;
3274 } else if (dest_ss != NULL) {
3275 state->desthost = print_canonical_sockaddr(state, dest_ss);
3276 if (tevent_req_nomem(state->desthost, req)) {
3277 return tevent_req_post(req, ev);
3279 } else {
3280 /* No host or dest_ss given. Error out. */
3281 tevent_req_error(req, EINVAL);
3282 return tevent_req_post(req, ev);
3285 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3286 myname, port);
3287 if (tevent_req_nomem(subreq, req)) {
3288 return tevent_req_post(req, ev);
3290 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3291 return req;
3294 static void cli_connect_nb_done(struct tevent_req *subreq)
3296 struct tevent_req *req = tevent_req_callback_data(
3297 subreq, struct tevent_req);
3298 struct cli_connect_nb_state *state = tevent_req_data(
3299 req, struct cli_connect_nb_state);
3300 NTSTATUS status;
3301 int fd = 0;
3302 uint16_t port;
3304 status = cli_connect_sock_recv(subreq, &fd, &port);
3305 TALLOC_FREE(subreq);
3306 if (tevent_req_nterror(req, status)) {
3307 return;
3310 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3311 state->signing_state, state->flags);
3312 if (tevent_req_nomem(state->cli, req)) {
3313 close(fd);
3314 return;
3316 tevent_req_done(req);
3319 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3320 struct cli_state **pcli)
3322 struct cli_connect_nb_state *state = tevent_req_data(
3323 req, struct cli_connect_nb_state);
3324 NTSTATUS status;
3326 if (tevent_req_is_nterror(req, &status)) {
3327 return status;
3329 *pcli = talloc_move(NULL, &state->cli);
3330 return NT_STATUS_OK;
3333 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3334 uint16_t port, int name_type, const char *myname,
3335 int signing_state, int flags, struct cli_state **pcli)
3337 struct tevent_context *ev;
3338 struct tevent_req *req;
3339 NTSTATUS status = NT_STATUS_NO_MEMORY;
3341 ev = samba_tevent_context_init(talloc_tos());
3342 if (ev == NULL) {
3343 goto fail;
3345 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3346 myname, signing_state, flags);
3347 if (req == NULL) {
3348 goto fail;
3350 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3351 goto fail;
3353 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3354 goto fail;
3356 status = cli_connect_nb_recv(req, pcli);
3357 fail:
3358 TALLOC_FREE(ev);
3359 return status;
3362 struct cli_start_connection_state {
3363 struct tevent_context *ev;
3364 struct cli_state *cli;
3365 int min_protocol;
3366 int max_protocol;
3369 static void cli_start_connection_connected(struct tevent_req *subreq);
3370 static void cli_start_connection_done(struct tevent_req *subreq);
3373 establishes a connection to after the negprot.
3374 @param output_cli A fully initialised cli structure, non-null only on success
3375 @param dest_host The netbios name of the remote host
3376 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3377 @param port (optional) The destination port (0 for default)
3380 static struct tevent_req *cli_start_connection_send(
3381 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3382 const char *my_name, const char *dest_host,
3383 const struct sockaddr_storage *dest_ss, int port,
3384 int signing_state, int flags)
3386 struct tevent_req *req, *subreq;
3387 struct cli_start_connection_state *state;
3389 req = tevent_req_create(mem_ctx, &state,
3390 struct cli_start_connection_state);
3391 if (req == NULL) {
3392 return NULL;
3394 state->ev = ev;
3396 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3397 state->min_protocol = lp_client_ipc_min_protocol();
3398 state->max_protocol = lp_client_ipc_max_protocol();
3399 } else {
3400 state->min_protocol = lp_client_min_protocol();
3401 state->max_protocol = lp_client_max_protocol();
3404 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3405 0x20, my_name, signing_state, flags);
3406 if (tevent_req_nomem(subreq, req)) {
3407 return tevent_req_post(req, ev);
3409 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3410 return req;
3413 static void cli_start_connection_connected(struct tevent_req *subreq)
3415 struct tevent_req *req = tevent_req_callback_data(
3416 subreq, struct tevent_req);
3417 struct cli_start_connection_state *state = tevent_req_data(
3418 req, struct cli_start_connection_state);
3419 NTSTATUS status;
3421 status = cli_connect_nb_recv(subreq, &state->cli);
3422 TALLOC_FREE(subreq);
3423 if (tevent_req_nterror(req, status)) {
3424 return;
3427 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3428 state->cli->timeout,
3429 state->min_protocol,
3430 state->max_protocol);
3431 if (tevent_req_nomem(subreq, req)) {
3432 return;
3434 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3437 static void cli_start_connection_done(struct tevent_req *subreq)
3439 struct tevent_req *req = tevent_req_callback_data(
3440 subreq, struct tevent_req);
3441 struct cli_start_connection_state *state = tevent_req_data(
3442 req, struct cli_start_connection_state);
3443 NTSTATUS status;
3445 status = smbXcli_negprot_recv(subreq);
3446 TALLOC_FREE(subreq);
3447 if (tevent_req_nterror(req, status)) {
3448 return;
3451 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3452 /* Ensure we ask for some initial credits. */
3453 smb2cli_conn_set_max_credits(state->cli->conn,
3454 DEFAULT_SMB2_MAX_CREDITS);
3457 tevent_req_done(req);
3460 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3461 struct cli_state **output_cli)
3463 struct cli_start_connection_state *state = tevent_req_data(
3464 req, struct cli_start_connection_state);
3465 NTSTATUS status;
3467 if (tevent_req_is_nterror(req, &status)) {
3468 return status;
3470 *output_cli = state->cli;
3472 return NT_STATUS_OK;
3475 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3476 const char *my_name,
3477 const char *dest_host,
3478 const struct sockaddr_storage *dest_ss, int port,
3479 int signing_state, int flags)
3481 struct tevent_context *ev;
3482 struct tevent_req *req;
3483 NTSTATUS status = NT_STATUS_NO_MEMORY;
3485 ev = samba_tevent_context_init(talloc_tos());
3486 if (ev == NULL) {
3487 goto fail;
3489 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3490 port, signing_state, flags);
3491 if (req == NULL) {
3492 goto fail;
3494 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3495 goto fail;
3497 status = cli_start_connection_recv(req, output_cli);
3498 fail:
3499 TALLOC_FREE(ev);
3500 return status;
3504 establishes a connection right up to doing tconX, password specified.
3505 @param output_cli A fully initialised cli structure, non-null only on success
3506 @param dest_host The netbios name of the remote host
3507 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3508 @param port (optional) The destination port (0 for default)
3509 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3510 @param service_type The 'type' of serivice.
3511 @param user Username, unix string
3512 @param domain User's domain
3513 @param password User's password, unencrypted unix string.
3516 struct cli_full_connection_state {
3517 struct tevent_context *ev;
3518 const char *service;
3519 const char *service_type;
3520 const char *user;
3521 const char *domain;
3522 const char *password;
3523 int pw_len;
3524 int flags;
3525 struct cli_state *cli;
3528 static int cli_full_connection_state_destructor(
3529 struct cli_full_connection_state *s);
3530 static void cli_full_connection_started(struct tevent_req *subreq);
3531 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3532 static void cli_full_connection_done(struct tevent_req *subreq);
3534 struct tevent_req *cli_full_connection_send(
3535 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3536 const char *my_name, const char *dest_host,
3537 const struct sockaddr_storage *dest_ss, int port,
3538 const char *service, const char *service_type,
3539 const char *user, const char *domain,
3540 const char *password, int flags, int signing_state)
3542 struct tevent_req *req, *subreq;
3543 struct cli_full_connection_state *state;
3545 req = tevent_req_create(mem_ctx, &state,
3546 struct cli_full_connection_state);
3547 if (req == NULL) {
3548 return NULL;
3550 talloc_set_destructor(state, cli_full_connection_state_destructor);
3552 state->ev = ev;
3553 state->service = service;
3554 state->service_type = service_type;
3555 state->user = user;
3556 state->domain = domain;
3557 state->password = password;
3558 state->flags = flags;
3560 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3561 if (state->password == NULL) {
3562 state->password = "";
3565 subreq = cli_start_connection_send(
3566 state, ev, my_name, dest_host, dest_ss, port,
3567 signing_state, flags);
3568 if (tevent_req_nomem(subreq, req)) {
3569 return tevent_req_post(req, ev);
3571 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3572 return req;
3575 static int cli_full_connection_state_destructor(
3576 struct cli_full_connection_state *s)
3578 if (s->cli != NULL) {
3579 cli_shutdown(s->cli);
3580 s->cli = NULL;
3582 return 0;
3585 static void cli_full_connection_started(struct tevent_req *subreq)
3587 struct tevent_req *req = tevent_req_callback_data(
3588 subreq, struct tevent_req);
3589 struct cli_full_connection_state *state = tevent_req_data(
3590 req, struct cli_full_connection_state);
3591 NTSTATUS status;
3593 status = cli_start_connection_recv(subreq, &state->cli);
3594 TALLOC_FREE(subreq);
3595 if (tevent_req_nterror(req, status)) {
3596 return;
3598 subreq = cli_session_setup_send(
3599 state, state->ev, state->cli, state->user,
3600 state->password, state->domain);
3601 if (tevent_req_nomem(subreq, req)) {
3602 return;
3604 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3607 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3609 struct tevent_req *req = tevent_req_callback_data(
3610 subreq, struct tevent_req);
3611 struct cli_full_connection_state *state = tevent_req_data(
3612 req, struct cli_full_connection_state);
3613 NTSTATUS status;
3615 status = cli_session_setup_recv(subreq);
3616 TALLOC_FREE(subreq);
3618 if (!NT_STATUS_IS_OK(status) &&
3619 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3621 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3623 subreq = cli_session_setup_send(
3624 state, state->ev, state->cli, "", "",
3625 state->domain);
3626 if (tevent_req_nomem(subreq, req)) {
3627 return;
3629 tevent_req_set_callback(
3630 subreq, cli_full_connection_sess_set_up, req);
3631 return;
3634 if (tevent_req_nterror(req, status)) {
3635 return;
3638 if (state->service != NULL) {
3639 subreq = cli_tree_connect_send(
3640 state, state->ev, state->cli,
3641 state->service, state->service_type,
3642 state->password, state->pw_len);
3643 if (tevent_req_nomem(subreq, req)) {
3644 return;
3646 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3647 return;
3650 tevent_req_done(req);
3653 static void cli_full_connection_done(struct tevent_req *subreq)
3655 struct tevent_req *req = tevent_req_callback_data(
3656 subreq, struct tevent_req);
3657 NTSTATUS status;
3659 status = cli_tree_connect_recv(subreq);
3660 TALLOC_FREE(subreq);
3661 if (tevent_req_nterror(req, status)) {
3662 return;
3665 tevent_req_done(req);
3668 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3669 struct cli_state **output_cli)
3671 struct cli_full_connection_state *state = tevent_req_data(
3672 req, struct cli_full_connection_state);
3673 NTSTATUS status;
3675 if (tevent_req_is_nterror(req, &status)) {
3676 return status;
3678 *output_cli = state->cli;
3679 talloc_set_destructor(state, NULL);
3680 return NT_STATUS_OK;
3683 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3684 const char *my_name,
3685 const char *dest_host,
3686 const struct sockaddr_storage *dest_ss, int port,
3687 const char *service, const char *service_type,
3688 const char *user, const char *domain,
3689 const char *password, int flags,
3690 int signing_state)
3692 struct tevent_context *ev;
3693 struct tevent_req *req;
3694 NTSTATUS status = NT_STATUS_NO_MEMORY;
3696 ev = samba_tevent_context_init(talloc_tos());
3697 if (ev == NULL) {
3698 goto fail;
3700 req = cli_full_connection_send(
3701 ev, ev, my_name, dest_host, dest_ss, port, service,
3702 service_type, user, domain, password, flags, signing_state);
3703 if (req == NULL) {
3704 goto fail;
3706 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3707 goto fail;
3709 status = cli_full_connection_recv(req, output_cli);
3710 fail:
3711 TALLOC_FREE(ev);
3712 return status;
3715 /****************************************************************************
3716 Send an old style tcon.
3717 ****************************************************************************/
3718 struct cli_raw_tcon_state {
3719 uint16_t *ret_vwv;
3722 static void cli_raw_tcon_done(struct tevent_req *subreq);
3724 static struct tevent_req *cli_raw_tcon_send(
3725 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3726 const char *service, const char *pass, const char *dev)
3728 struct tevent_req *req, *subreq;
3729 struct cli_raw_tcon_state *state;
3730 uint8_t *bytes;
3732 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3733 if (req == NULL) {
3734 return NULL;
3737 if (!lp_client_plaintext_auth() && (*pass)) {
3738 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3739 " or 'client ntlmv2 auth = yes'\n"));
3740 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3741 return tevent_req_post(req, ev);
3744 bytes = talloc_array(state, uint8_t, 0);
3745 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3746 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3747 service, strlen(service)+1, NULL);
3748 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3749 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3750 pass, strlen(pass)+1, NULL);
3751 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3752 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3753 dev, strlen(dev)+1, NULL);
3755 if (tevent_req_nomem(bytes, req)) {
3756 return tevent_req_post(req, ev);
3759 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3760 talloc_get_size(bytes), bytes);
3761 if (tevent_req_nomem(subreq, req)) {
3762 return tevent_req_post(req, ev);
3764 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3765 return req;
3768 static void cli_raw_tcon_done(struct tevent_req *subreq)
3770 struct tevent_req *req = tevent_req_callback_data(
3771 subreq, struct tevent_req);
3772 struct cli_raw_tcon_state *state = tevent_req_data(
3773 req, struct cli_raw_tcon_state);
3774 NTSTATUS status;
3776 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3777 NULL, NULL);
3778 TALLOC_FREE(subreq);
3779 if (tevent_req_nterror(req, status)) {
3780 return;
3782 tevent_req_done(req);
3785 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3786 uint16_t *max_xmit, uint16_t *tid)
3788 struct cli_raw_tcon_state *state = tevent_req_data(
3789 req, struct cli_raw_tcon_state);
3790 NTSTATUS status;
3792 if (tevent_req_is_nterror(req, &status)) {
3793 return status;
3795 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3796 *tid = SVAL(state->ret_vwv + 1, 0);
3797 return NT_STATUS_OK;
3800 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3801 const char *service, const char *pass, const char *dev,
3802 uint16_t *max_xmit, uint16_t *tid)
3804 struct tevent_context *ev;
3805 struct tevent_req *req;
3806 NTSTATUS status = NT_STATUS_NO_MEMORY;
3808 ev = samba_tevent_context_init(talloc_tos());
3809 if (ev == NULL) {
3810 goto fail;
3812 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3813 if (req == NULL) {
3814 goto fail;
3816 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3817 goto fail;
3819 status = cli_raw_tcon_recv(req, max_xmit, tid);
3820 fail:
3821 TALLOC_FREE(ev);
3822 return status;
3825 /* Return a cli_state pointing at the IPC$ share for the given server */
3827 struct cli_state *get_ipc_connect(char *server,
3828 struct sockaddr_storage *server_ss,
3829 const struct user_auth_info *user_info)
3831 struct cli_state *cli;
3832 NTSTATUS nt_status;
3833 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3835 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3836 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3839 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3840 get_cmdline_auth_info_username(user_info),
3841 lp_workgroup(),
3842 get_cmdline_auth_info_password(user_info),
3843 flags,
3844 SMB_SIGNING_DEFAULT);
3846 if (NT_STATUS_IS_OK(nt_status)) {
3847 return cli;
3848 } else if (is_ipaddress(server)) {
3849 /* windows 9* needs a correct NMB name for connections */
3850 fstring remote_name;
3852 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3853 cli = get_ipc_connect(remote_name, server_ss, user_info);
3854 if (cli)
3855 return cli;
3858 return NULL;
3862 * Given the IP address of a master browser on the network, return its
3863 * workgroup and connect to it.
3865 * This function is provided to allow additional processing beyond what
3866 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3867 * browsers and obtain each master browsers' list of domains (in case the
3868 * first master browser is recently on the network and has not yet
3869 * synchronized with other master browsers and therefore does not yet have the
3870 * entire network browse list)
3873 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3874 struct sockaddr_storage *mb_ip,
3875 const struct user_auth_info *user_info,
3876 char **pp_workgroup_out)
3878 char addr[INET6_ADDRSTRLEN];
3879 fstring name;
3880 struct cli_state *cli;
3881 struct sockaddr_storage server_ss;
3883 *pp_workgroup_out = NULL;
3885 print_sockaddr(addr, sizeof(addr), mb_ip);
3886 DEBUG(99, ("Looking up name of master browser %s\n",
3887 addr));
3890 * Do a name status query to find out the name of the master browser.
3891 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3892 * master browser will not respond to a wildcard query (or, at least,
3893 * an NT4 server acting as the domain master browser will not).
3895 * We might be able to use ONLY the query on MSBROWSE, but that's not
3896 * yet been tested with all Windows versions, so until it is, leave
3897 * the original wildcard query as the first choice and fall back to
3898 * MSBROWSE if the wildcard query fails.
3900 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3901 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3903 DEBUG(99, ("Could not retrieve name status for %s\n",
3904 addr));
3905 return NULL;
3908 if (!find_master_ip(name, &server_ss)) {
3909 DEBUG(99, ("Could not find master ip for %s\n", name));
3910 return NULL;
3913 *pp_workgroup_out = talloc_strdup(ctx, name);
3915 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3917 print_sockaddr(addr, sizeof(addr), &server_ss);
3918 cli = get_ipc_connect(addr, &server_ss, user_info);
3920 return cli;
3924 * Return the IP address and workgroup of a master browser on the network, and
3925 * connect to it.
3928 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3929 const struct user_auth_info *user_info,
3930 char **pp_workgroup_out)
3932 struct sockaddr_storage *ip_list;
3933 struct cli_state *cli;
3934 int i, count;
3935 NTSTATUS status;
3937 *pp_workgroup_out = NULL;
3939 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3941 /* Go looking for workgroups by broadcasting on the local network */
3943 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3944 &ip_list, &count);
3945 if (!NT_STATUS_IS_OK(status)) {
3946 DEBUG(99, ("No master browsers responded: %s\n",
3947 nt_errstr(status)));
3948 return NULL;
3951 for (i = 0; i < count; i++) {
3952 char addr[INET6_ADDRSTRLEN];
3953 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3954 DEBUG(99, ("Found master browser %s\n", addr));
3956 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3957 user_info, pp_workgroup_out);
3958 if (cli)
3959 return(cli);
3962 return NULL;