libcli/smb: reformat wscript
[Samba.git] / source3 / libsmb / cliconnect.c
blob57e51b3c2e3a5237da9ef9914bf134c8ed9197ed
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 /****************************************************************************
78 Do an old lanman2 style session setup.
79 ****************************************************************************/
81 struct cli_session_setup_lanman2_state {
82 struct cli_state *cli;
83 uint16_t vwv[10];
84 const char *user;
87 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
89 static struct tevent_req *cli_session_setup_lanman2_send(
90 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
91 struct cli_state *cli, const char *user,
92 const char *pass, size_t passlen,
93 const char *workgroup)
95 struct tevent_req *req, *subreq;
96 struct cli_session_setup_lanman2_state *state;
97 DATA_BLOB lm_response = data_blob_null;
98 uint16_t *vwv;
99 uint8_t *bytes;
100 char *tmp;
101 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
103 req = tevent_req_create(mem_ctx, &state,
104 struct cli_session_setup_lanman2_state);
105 if (req == NULL) {
106 return NULL;
108 state->cli = cli;
109 state->user = user;
110 vwv = state->vwv;
113 * if in share level security then don't send a password now
115 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
116 passlen = 0;
119 if (passlen > 0
120 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
121 && passlen != 24) {
123 * Encrypted mode needed, and non encrypted password
124 * supplied.
126 lm_response = data_blob(NULL, 24);
127 if (tevent_req_nomem(lm_response.data, req)) {
128 return tevent_req_post(req, ev);
131 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
132 (uint8_t *)lm_response.data)) {
133 DEBUG(1, ("Password is > 14 chars in length, and is "
134 "therefore incompatible with Lanman "
135 "authentication\n"));
136 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
137 return tevent_req_post(req, ev);
139 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
140 && passlen == 24) {
142 * Encrypted mode needed, and encrypted password
143 * supplied.
145 lm_response = data_blob(pass, passlen);
146 if (tevent_req_nomem(lm_response.data, req)) {
147 return tevent_req_post(req, ev);
149 } else if (passlen > 0) {
150 uint8_t *buf;
151 size_t converted_size;
153 * Plaintext mode needed, assume plaintext supplied.
155 buf = talloc_array(talloc_tos(), uint8_t, 0);
156 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
157 &converted_size);
158 if (tevent_req_nomem(buf, req)) {
159 return tevent_req_post(req, ev);
161 lm_response = data_blob(pass, passlen);
162 TALLOC_FREE(buf);
163 if (tevent_req_nomem(lm_response.data, req)) {
164 return tevent_req_post(req, ev);
168 SCVAL(vwv+0, 0, 0xff);
169 SCVAL(vwv+0, 1, 0);
170 SSVAL(vwv+1, 0, 0);
171 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
172 SSVAL(vwv+3, 0, 2);
173 SSVAL(vwv+4, 0, 1);
174 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
175 SSVAL(vwv+7, 0, lm_response.length);
177 bytes = talloc_array(state, uint8_t, lm_response.length);
178 if (tevent_req_nomem(bytes, req)) {
179 return tevent_req_post(req, ev);
181 if (lm_response.length != 0) {
182 memcpy(bytes, lm_response.data, lm_response.length);
184 data_blob_free(&lm_response);
186 tmp = talloc_strdup_upper(talloc_tos(), user);
187 if (tevent_req_nomem(tmp, req)) {
188 return tevent_req_post(req, ev);
190 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
191 NULL);
192 TALLOC_FREE(tmp);
194 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
195 if (tevent_req_nomem(tmp, req)) {
196 return tevent_req_post(req, ev);
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
199 NULL);
200 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
201 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
203 if (tevent_req_nomem(bytes, req)) {
204 return tevent_req_post(req, ev);
207 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 0, 10, vwv,
208 talloc_get_size(bytes), bytes);
209 if (tevent_req_nomem(subreq, req)) {
210 return tevent_req_post(req, ev);
212 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
213 return req;
216 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
218 struct tevent_req *req = tevent_req_callback_data(
219 subreq, struct tevent_req);
220 struct cli_session_setup_lanman2_state *state = tevent_req_data(
221 req, struct cli_session_setup_lanman2_state);
222 struct cli_state *cli = state->cli;
223 uint32_t num_bytes;
224 uint8_t *in;
225 uint8_t *inhdr;
226 uint8_t *bytes;
227 uint8_t *p;
228 NTSTATUS status;
229 ssize_t ret;
230 uint8_t wct;
231 uint16_t *vwv;
233 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
234 &num_bytes, &bytes);
235 TALLOC_FREE(subreq);
236 if (!NT_STATUS_IS_OK(status)) {
237 tevent_req_nterror(req, status);
238 return;
241 inhdr = in + NBT_HDR_SIZE;
242 p = bytes;
244 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
245 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
247 status = smb_bytes_talloc_string(cli,
248 inhdr,
249 &cli->server_os,
251 bytes+num_bytes-p,
252 &ret);
254 if (!NT_STATUS_IS_OK(status)) {
255 tevent_req_nterror(req, status);
256 return;
258 p += ret;
260 status = smb_bytes_talloc_string(cli,
261 inhdr,
262 &cli->server_type,
264 bytes+num_bytes-p,
265 &ret);
267 if (!NT_STATUS_IS_OK(status)) {
268 tevent_req_nterror(req, status);
269 return;
271 p += ret;
273 status = smb_bytes_talloc_string(cli,
274 inhdr,
275 &cli->server_domain,
277 bytes+num_bytes-p,
278 &ret);
280 if (!NT_STATUS_IS_OK(status)) {
281 tevent_req_nterror(req, status);
282 return;
284 p += ret;
286 tevent_req_done(req);
289 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
291 return tevent_req_simple_recv_ntstatus(req);
294 /****************************************************************************
295 Work out suitable capabilities to offer the server.
296 ****************************************************************************/
298 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
299 uint32_t sesssetup_capabilities)
301 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
304 * We only send capabilities based on the mask for:
305 * - client only flags
306 * - flags used in both directions
308 * We do not echo the server only flags, except some legacy flags.
310 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
311 * CAP_LARGE_WRITEX in order to allow us to do large reads
312 * against old Samba releases (<= 3.6.x).
314 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
317 * Session Setup specific flags CAP_DYNAMIC_REAUTH
318 * and CAP_EXTENDED_SECURITY are passed by the caller.
319 * We need that in order to do guest logins even if
320 * CAP_EXTENDED_SECURITY is negotiated.
322 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
323 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
324 client_capabilities |= sesssetup_capabilities;
326 return client_capabilities;
329 /****************************************************************************
330 Do a NT1 guest session setup.
331 ****************************************************************************/
333 struct cli_session_setup_guest_state {
334 struct cli_state *cli;
335 uint16_t vwv[13];
336 struct iovec bytes;
339 static void cli_session_setup_guest_done(struct tevent_req *subreq);
341 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
342 struct tevent_context *ev,
343 struct cli_state *cli,
344 struct tevent_req **psmbreq)
346 struct tevent_req *req, *subreq;
347 struct cli_session_setup_guest_state *state;
348 uint16_t *vwv;
349 uint8_t *bytes;
351 req = tevent_req_create(mem_ctx, &state,
352 struct cli_session_setup_guest_state);
353 if (req == NULL) {
354 return NULL;
356 state->cli = cli;
357 vwv = state->vwv;
359 SCVAL(vwv+0, 0, 0xFF);
360 SCVAL(vwv+0, 1, 0);
361 SSVAL(vwv+1, 0, 0);
362 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
363 SSVAL(vwv+3, 0, 2);
364 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
365 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
366 SSVAL(vwv+7, 0, 0);
367 SSVAL(vwv+8, 0, 0);
368 SSVAL(vwv+9, 0, 0);
369 SSVAL(vwv+10, 0, 0);
370 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
372 bytes = talloc_array(state, uint8_t, 0);
374 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
375 NULL);
376 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
377 NULL);
378 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
379 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
381 if (bytes == NULL) {
382 TALLOC_FREE(req);
383 return NULL;
386 state->bytes.iov_base = (void *)bytes;
387 state->bytes.iov_len = talloc_get_size(bytes);
389 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
390 vwv, 1, &state->bytes);
391 if (subreq == NULL) {
392 TALLOC_FREE(req);
393 return NULL;
395 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
396 *psmbreq = subreq;
397 return req;
400 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
401 struct tevent_context *ev,
402 struct cli_state *cli)
404 struct tevent_req *req, *subreq;
405 NTSTATUS status;
407 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
408 if (req == NULL) {
409 return NULL;
412 status = smb1cli_req_chain_submit(&subreq, 1);
413 if (!NT_STATUS_IS_OK(status)) {
414 tevent_req_nterror(req, status);
415 return tevent_req_post(req, ev);
417 return req;
420 static void cli_session_setup_guest_done(struct tevent_req *subreq)
422 struct tevent_req *req = tevent_req_callback_data(
423 subreq, struct tevent_req);
424 struct cli_session_setup_guest_state *state = tevent_req_data(
425 req, struct cli_session_setup_guest_state);
426 struct cli_state *cli = state->cli;
427 uint32_t num_bytes;
428 uint8_t *in;
429 uint8_t *inhdr;
430 uint8_t *bytes;
431 uint8_t *p;
432 NTSTATUS status;
433 ssize_t ret;
434 uint8_t wct;
435 uint16_t *vwv;
437 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
438 &num_bytes, &bytes);
439 TALLOC_FREE(subreq);
440 if (!NT_STATUS_IS_OK(status)) {
441 tevent_req_nterror(req, status);
442 return;
445 inhdr = in + NBT_HDR_SIZE;
446 p = bytes;
448 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
449 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
451 status = smb_bytes_talloc_string(cli,
452 inhdr,
453 &cli->server_os,
455 bytes+num_bytes-p,
456 &ret);
458 if (!NT_STATUS_IS_OK(status)) {
459 tevent_req_nterror(req, status);
460 return;
462 p += ret;
464 status = smb_bytes_talloc_string(cli,
465 inhdr,
466 &cli->server_type,
468 bytes+num_bytes-p,
469 &ret);
471 if (!NT_STATUS_IS_OK(status)) {
472 tevent_req_nterror(req, status);
473 return;
475 p += ret;
477 status = smb_bytes_talloc_string(cli,
478 inhdr,
479 &cli->server_domain,
481 bytes+num_bytes-p,
482 &ret);
484 if (!NT_STATUS_IS_OK(status)) {
485 tevent_req_nterror(req, status);
486 return;
488 p += ret;
490 tevent_req_done(req);
493 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
495 return tevent_req_simple_recv_ntstatus(req);
498 /****************************************************************************
499 Do a NT1 plaintext session setup.
500 ****************************************************************************/
502 struct cli_session_setup_plain_state {
503 struct cli_state *cli;
504 uint16_t vwv[13];
505 const char *user;
508 static void cli_session_setup_plain_done(struct tevent_req *subreq);
510 static struct tevent_req *cli_session_setup_plain_send(
511 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
512 struct cli_state *cli,
513 const char *user, const char *pass, const char *workgroup)
515 struct tevent_req *req, *subreq;
516 struct cli_session_setup_plain_state *state;
517 uint16_t *vwv;
518 uint8_t *bytes;
519 size_t passlen;
520 char *version;
522 req = tevent_req_create(mem_ctx, &state,
523 struct cli_session_setup_plain_state);
524 if (req == NULL) {
525 return NULL;
527 state->cli = cli;
528 state->user = user;
529 vwv = state->vwv;
531 SCVAL(vwv+0, 0, 0xff);
532 SCVAL(vwv+0, 1, 0);
533 SSVAL(vwv+1, 0, 0);
534 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
535 SSVAL(vwv+3, 0, 2);
536 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
537 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
538 SSVAL(vwv+7, 0, 0);
539 SSVAL(vwv+8, 0, 0);
540 SSVAL(vwv+9, 0, 0);
541 SSVAL(vwv+10, 0, 0);
542 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
544 bytes = talloc_array(state, uint8_t, 0);
545 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
546 &passlen);
547 if (tevent_req_nomem(bytes, req)) {
548 return tevent_req_post(req, ev);
550 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
552 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
553 user, strlen(user)+1, NULL);
554 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
555 workgroup, strlen(workgroup)+1, NULL);
556 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
557 "Unix", 5, NULL);
559 version = talloc_asprintf(talloc_tos(), "Samba %s",
560 samba_version_string());
561 if (tevent_req_nomem(version, req)){
562 return tevent_req_post(req, ev);
564 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
565 version, strlen(version)+1, NULL);
566 TALLOC_FREE(version);
568 if (tevent_req_nomem(bytes, req)) {
569 return tevent_req_post(req, ev);
572 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 0, 13, vwv,
573 talloc_get_size(bytes), bytes);
574 if (tevent_req_nomem(subreq, req)) {
575 return tevent_req_post(req, ev);
577 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
578 return req;
581 static void cli_session_setup_plain_done(struct tevent_req *subreq)
583 struct tevent_req *req = tevent_req_callback_data(
584 subreq, struct tevent_req);
585 struct cli_session_setup_plain_state *state = tevent_req_data(
586 req, struct cli_session_setup_plain_state);
587 struct cli_state *cli = state->cli;
588 uint32_t num_bytes;
589 uint8_t *in;
590 uint8_t *inhdr;
591 uint8_t *bytes;
592 uint8_t *p;
593 NTSTATUS status;
594 ssize_t ret;
595 uint8_t wct;
596 uint16_t *vwv;
598 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
599 &num_bytes, &bytes);
600 TALLOC_FREE(subreq);
601 if (tevent_req_nterror(req, status)) {
602 return;
605 inhdr = in + NBT_HDR_SIZE;
606 p = bytes;
608 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
609 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
611 status = smb_bytes_talloc_string(cli,
612 inhdr,
613 &cli->server_os,
615 bytes+num_bytes-p,
616 &ret);
618 if (!NT_STATUS_IS_OK(status)) {
619 tevent_req_nterror(req, status);
620 return;
622 p += ret;
624 status = smb_bytes_talloc_string(cli,
625 inhdr,
626 &cli->server_type,
628 bytes+num_bytes-p,
629 &ret);
631 if (!NT_STATUS_IS_OK(status)) {
632 tevent_req_nterror(req, status);
633 return;
635 p += ret;
637 status = smb_bytes_talloc_string(cli,
638 inhdr,
639 &cli->server_domain,
641 bytes+num_bytes-p,
642 &ret);
644 if (!NT_STATUS_IS_OK(status)) {
645 tevent_req_nterror(req, status);
646 return;
648 p += ret;
650 tevent_req_done(req);
653 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
655 return tevent_req_simple_recv_ntstatus(req);
658 /****************************************************************************
659 do a NT1 NTLM/LM encrypted session setup - for when extended security
660 is not negotiated.
661 @param cli client state to create do session setup on
662 @param user username
663 @param pass *either* cleartext password (passlen !=24) or LM response.
664 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
665 @param workgroup The user's domain.
666 ****************************************************************************/
668 struct cli_session_setup_nt1_state {
669 struct cli_state *cli;
670 uint16_t vwv[13];
671 DATA_BLOB response;
672 DATA_BLOB session_key;
673 const char *user;
676 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
678 static struct tevent_req *cli_session_setup_nt1_send(
679 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
680 struct cli_state *cli, const char *user,
681 const char *pass, size_t passlen,
682 const char *ntpass, size_t ntpasslen,
683 const char *workgroup)
685 struct tevent_req *req, *subreq;
686 struct cli_session_setup_nt1_state *state;
687 DATA_BLOB lm_response = data_blob_null;
688 DATA_BLOB nt_response = data_blob_null;
689 DATA_BLOB session_key = data_blob_null;
690 uint16_t *vwv;
691 uint8_t *bytes;
692 char *workgroup_upper;
694 req = tevent_req_create(mem_ctx, &state,
695 struct cli_session_setup_nt1_state);
696 if (req == NULL) {
697 return NULL;
699 state->cli = cli;
700 state->user = user;
701 vwv = state->vwv;
703 if (passlen == 0) {
704 /* do nothing - guest login */
705 } else if (passlen != 24) {
706 if (lp_client_ntlmv2_auth()) {
707 DATA_BLOB server_chal;
708 DATA_BLOB names_blob;
710 server_chal =
711 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
715 * note that the 'workgroup' here is a best
716 * guess - we don't know the server's domain
717 * at this point. Windows clients also don't
718 * use hostname...
720 names_blob = NTLMv2_generate_names_blob(
721 NULL, NULL, workgroup);
723 if (tevent_req_nomem(names_blob.data, req)) {
724 return tevent_req_post(req, ev);
727 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
728 &server_chal, &names_blob,
729 &lm_response, &nt_response,
730 NULL, &session_key)) {
731 data_blob_free(&names_blob);
732 tevent_req_nterror(
733 req, NT_STATUS_ACCESS_DENIED);
734 return tevent_req_post(req, ev);
736 data_blob_free(&names_blob);
738 } else {
739 uchar nt_hash[16];
740 E_md4hash(pass, nt_hash);
742 #ifdef LANMAN_ONLY
743 nt_response = data_blob_null;
744 #else
745 nt_response = data_blob(NULL, 24);
746 if (tevent_req_nomem(nt_response.data, req)) {
747 return tevent_req_post(req, ev);
750 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
751 nt_response.data);
752 #endif
753 /* non encrypted password supplied. Ignore ntpass. */
754 if (lp_client_lanman_auth()) {
756 lm_response = data_blob(NULL, 24);
757 if (tevent_req_nomem(lm_response.data, req)) {
758 return tevent_req_post(req, ev);
761 if (!SMBencrypt(pass,
762 smb1cli_conn_server_challenge(cli->conn),
763 lm_response.data)) {
765 * Oops, the LM response is
766 * invalid, just put the NT
767 * response there instead
769 data_blob_free(&lm_response);
770 lm_response = data_blob(
771 nt_response.data,
772 nt_response.length);
774 } else {
776 * LM disabled, place NT# in LM field
777 * instead
779 lm_response = data_blob(
780 nt_response.data, nt_response.length);
783 if (tevent_req_nomem(lm_response.data, req)) {
784 return tevent_req_post(req, ev);
787 session_key = data_blob(NULL, 16);
788 if (tevent_req_nomem(session_key.data, req)) {
789 return tevent_req_post(req, ev);
791 #ifdef LANMAN_ONLY
792 E_deshash(pass, session_key.data);
793 memset(&session_key.data[8], '\0', 8);
794 #else
795 SMBsesskeygen_ntv1(nt_hash, session_key.data);
796 #endif
798 } else {
799 /* pre-encrypted password supplied. Only used for
800 security=server, can't do
801 signing because we don't have original key */
803 lm_response = data_blob(pass, passlen);
804 if (tevent_req_nomem(lm_response.data, req)) {
805 return tevent_req_post(req, ev);
808 nt_response = data_blob(ntpass, ntpasslen);
809 if (tevent_req_nomem(nt_response.data, req)) {
810 return tevent_req_post(req, ev);
814 #ifdef LANMAN_ONLY
815 state->response = data_blob_talloc(
816 state, lm_response.data, lm_response.length);
817 #else
818 state->response = data_blob_talloc(
819 state, nt_response.data, nt_response.length);
820 #endif
821 if (tevent_req_nomem(state->response.data, req)) {
822 return tevent_req_post(req, ev);
825 if (session_key.data) {
826 state->session_key = data_blob_talloc(
827 state, session_key.data, session_key.length);
828 if (tevent_req_nomem(state->session_key.data, req)) {
829 return tevent_req_post(req, ev);
832 data_blob_free(&session_key);
834 SCVAL(vwv+0, 0, 0xff);
835 SCVAL(vwv+0, 1, 0);
836 SSVAL(vwv+1, 0, 0);
837 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
838 SSVAL(vwv+3, 0, 2);
839 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
840 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
841 SSVAL(vwv+7, 0, lm_response.length);
842 SSVAL(vwv+8, 0, nt_response.length);
843 SSVAL(vwv+9, 0, 0);
844 SSVAL(vwv+10, 0, 0);
845 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
847 bytes = talloc_array(state, uint8_t,
848 lm_response.length + nt_response.length);
849 if (tevent_req_nomem(bytes, req)) {
850 return tevent_req_post(req, ev);
852 if (lm_response.length != 0) {
853 memcpy(bytes, lm_response.data, lm_response.length);
855 if (nt_response.length != 0) {
856 memcpy(bytes + lm_response.length,
857 nt_response.data, nt_response.length);
859 data_blob_free(&lm_response);
860 data_blob_free(&nt_response);
862 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
863 user, strlen(user)+1, NULL);
866 * Upper case here might help some NTLMv2 implementations
868 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
869 if (tevent_req_nomem(workgroup_upper, req)) {
870 return tevent_req_post(req, ev);
872 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
873 workgroup_upper, strlen(workgroup_upper)+1,
874 NULL);
875 TALLOC_FREE(workgroup_upper);
877 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
878 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
879 if (tevent_req_nomem(bytes, req)) {
880 return tevent_req_post(req, ev);
883 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 0, 13, vwv,
884 talloc_get_size(bytes), bytes);
885 if (tevent_req_nomem(subreq, req)) {
886 return tevent_req_post(req, ev);
888 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
889 return req;
892 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
894 struct tevent_req *req = tevent_req_callback_data(
895 subreq, struct tevent_req);
896 struct cli_session_setup_nt1_state *state = tevent_req_data(
897 req, struct cli_session_setup_nt1_state);
898 struct cli_state *cli = state->cli;
899 uint32_t num_bytes;
900 uint8_t *in;
901 uint8_t *inhdr;
902 uint8_t *bytes;
903 uint8_t *p;
904 NTSTATUS status;
905 ssize_t ret;
906 uint8_t wct;
907 uint16_t *vwv;
909 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
910 &num_bytes, &bytes);
911 TALLOC_FREE(subreq);
912 if (!NT_STATUS_IS_OK(status)) {
913 tevent_req_nterror(req, status);
914 return;
917 inhdr = in + NBT_HDR_SIZE;
918 p = bytes;
920 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
921 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
923 status = smb_bytes_talloc_string(cli,
924 inhdr,
925 &cli->server_os,
927 bytes+num_bytes-p,
928 &ret);
929 if (!NT_STATUS_IS_OK(status)) {
930 tevent_req_nterror(req, status);
931 return;
933 p += ret;
935 status = smb_bytes_talloc_string(cli,
936 inhdr,
937 &cli->server_type,
939 bytes+num_bytes-p,
940 &ret);
941 if (!NT_STATUS_IS_OK(status)) {
942 tevent_req_nterror(req, status);
943 return;
945 p += ret;
947 status = smb_bytes_talloc_string(cli,
948 inhdr,
949 &cli->server_domain,
951 bytes+num_bytes-p,
952 &ret);
953 if (!NT_STATUS_IS_OK(status)) {
954 tevent_req_nterror(req, status);
955 return;
957 p += ret;
959 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
960 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
961 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
962 return;
964 if (state->session_key.data) {
965 struct smbXcli_session *session = state->cli->smb1.session;
967 status = smb1cli_session_set_session_key(session,
968 state->session_key);
969 if (tevent_req_nterror(req, status)) {
970 return;
973 tevent_req_done(req);
976 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
978 return tevent_req_simple_recv_ntstatus(req);
981 /* The following is calculated from :
982 * (smb_size-4) = 35
983 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
984 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
985 * end of packet.
988 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
990 struct cli_sesssetup_blob_state {
991 struct tevent_context *ev;
992 struct cli_state *cli;
993 DATA_BLOB blob;
994 uint16_t max_blob_size;
995 uint16_t vwv[12];
996 uint8_t *buf;
998 DATA_BLOB smb2_blob;
999 struct iovec *recv_iov;
1001 NTSTATUS status;
1002 uint8_t *inbuf;
1003 DATA_BLOB ret_blob;
1006 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1007 struct tevent_req **psubreq);
1008 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1010 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1011 struct tevent_context *ev,
1012 struct cli_state *cli,
1013 DATA_BLOB blob)
1015 struct tevent_req *req, *subreq;
1016 struct cli_sesssetup_blob_state *state;
1017 uint32_t usable_space;
1019 req = tevent_req_create(mem_ctx, &state,
1020 struct cli_sesssetup_blob_state);
1021 if (req == NULL) {
1022 return NULL;
1024 state->ev = ev;
1025 state->blob = blob;
1026 state->cli = cli;
1028 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1029 usable_space = UINT16_MAX;
1030 } else {
1031 usable_space = cli_state_available_size(cli,
1032 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1035 if (usable_space == 0) {
1036 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1037 "(not possible to send %u bytes)\n",
1038 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1039 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1040 return tevent_req_post(req, ev);
1042 state->max_blob_size = MIN(usable_space, 0xFFFF);
1044 if (!cli_sesssetup_blob_next(state, &subreq)) {
1045 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1046 return tevent_req_post(req, ev);
1048 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1049 return req;
1052 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1053 struct tevent_req **psubreq)
1055 struct tevent_req *subreq;
1056 uint16_t thistime;
1058 thistime = MIN(state->blob.length, state->max_blob_size);
1060 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1062 state->smb2_blob.data = state->blob.data;
1063 state->smb2_blob.length = thistime;
1065 state->blob.data += thistime;
1066 state->blob.length -= thistime;
1068 subreq = smb2cli_session_setup_send(state, state->ev,
1069 state->cli->conn,
1070 state->cli->timeout,
1071 state->cli->smb2.session,
1072 0, /* in_flags */
1073 SMB2_CAP_DFS, /* in_capabilities */
1074 0, /* in_channel */
1075 0, /* in_previous_session_id */
1076 &state->smb2_blob);
1077 if (subreq == NULL) {
1078 return false;
1080 *psubreq = subreq;
1081 return true;
1084 SCVAL(state->vwv+0, 0, 0xFF);
1085 SCVAL(state->vwv+0, 1, 0);
1086 SSVAL(state->vwv+1, 0, 0);
1087 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1088 SSVAL(state->vwv+3, 0, 2);
1089 SSVAL(state->vwv+4, 0, 1);
1090 SIVAL(state->vwv+5, 0, 0);
1092 SSVAL(state->vwv+7, 0, thistime);
1094 SSVAL(state->vwv+8, 0, 0);
1095 SSVAL(state->vwv+9, 0, 0);
1096 SIVAL(state->vwv+10, 0,
1097 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1099 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1100 thistime);
1101 if (state->buf == NULL) {
1102 return false;
1104 state->blob.data += thistime;
1105 state->blob.length -= thistime;
1107 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1108 "Unix", 5, NULL);
1109 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1110 "Samba", 6, NULL);
1111 if (state->buf == NULL) {
1112 return false;
1114 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0, 0,
1115 12, state->vwv,
1116 talloc_get_size(state->buf), state->buf);
1117 if (subreq == NULL) {
1118 return false;
1120 *psubreq = subreq;
1121 return true;
1124 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1126 struct tevent_req *req = tevent_req_callback_data(
1127 subreq, struct tevent_req);
1128 struct cli_sesssetup_blob_state *state = tevent_req_data(
1129 req, struct cli_sesssetup_blob_state);
1130 struct cli_state *cli = state->cli;
1131 uint8_t wct;
1132 uint16_t *vwv;
1133 uint32_t num_bytes;
1134 uint8_t *bytes;
1135 NTSTATUS status;
1136 uint8_t *p;
1137 uint16_t blob_length;
1138 uint8_t *in;
1139 uint8_t *inhdr;
1140 ssize_t ret;
1142 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1143 status = smb2cli_session_setup_recv(subreq, state,
1144 &state->recv_iov,
1145 &state->ret_blob);
1146 } else {
1147 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1148 &num_bytes, &bytes);
1149 TALLOC_FREE(state->buf);
1151 TALLOC_FREE(subreq);
1152 if (!NT_STATUS_IS_OK(status)
1153 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1154 tevent_req_nterror(req, status);
1155 return;
1158 state->status = status;
1160 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1161 goto next;
1164 state->inbuf = in;
1165 inhdr = in + NBT_HDR_SIZE;
1166 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1167 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
1169 blob_length = SVAL(vwv+3, 0);
1170 if (blob_length > num_bytes) {
1171 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1172 return;
1174 state->ret_blob = data_blob_const(bytes, blob_length);
1176 p = bytes + blob_length;
1178 status = smb_bytes_talloc_string(cli,
1179 inhdr,
1180 &cli->server_os,
1182 bytes+num_bytes-p,
1183 &ret);
1185 if (!NT_STATUS_IS_OK(status)) {
1186 tevent_req_nterror(req, status);
1187 return;
1189 p += ret;
1191 status = smb_bytes_talloc_string(cli,
1192 inhdr,
1193 &cli->server_type,
1195 bytes+num_bytes-p,
1196 &ret);
1198 if (!NT_STATUS_IS_OK(status)) {
1199 tevent_req_nterror(req, status);
1200 return;
1202 p += ret;
1204 status = smb_bytes_talloc_string(cli,
1205 inhdr,
1206 &cli->server_domain,
1208 bytes+num_bytes-p,
1209 &ret);
1211 if (!NT_STATUS_IS_OK(status)) {
1212 tevent_req_nterror(req, status);
1213 return;
1215 p += ret;
1217 next:
1218 if (state->blob.length != 0) {
1220 * More to send
1222 if (!cli_sesssetup_blob_next(state, &subreq)) {
1223 tevent_req_oom(req);
1224 return;
1226 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1227 return;
1229 tevent_req_done(req);
1232 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1233 TALLOC_CTX *mem_ctx,
1234 DATA_BLOB *pblob,
1235 uint8_t **pinbuf,
1236 struct iovec **precv_iov)
1238 struct cli_sesssetup_blob_state *state = tevent_req_data(
1239 req, struct cli_sesssetup_blob_state);
1240 NTSTATUS status;
1241 uint8_t *inbuf;
1242 struct iovec *recv_iov;
1244 if (tevent_req_is_nterror(req, &status)) {
1245 TALLOC_FREE(state->cli->smb2.session);
1246 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1247 return status;
1250 inbuf = talloc_move(mem_ctx, &state->inbuf);
1251 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1252 if (pblob != NULL) {
1253 *pblob = state->ret_blob;
1255 if (pinbuf != NULL) {
1256 *pinbuf = inbuf;
1258 if (precv_iov != NULL) {
1259 *precv_iov = recv_iov;
1261 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1262 return state->status;
1265 #ifdef HAVE_KRB5
1267 /****************************************************************************
1268 Use in-memory credentials cache
1269 ****************************************************************************/
1271 static void use_in_memory_ccache(void) {
1272 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1275 #endif /* HAVE_KRB5 */
1277 /****************************************************************************
1278 Do a spnego/NTLMSSP encrypted session setup.
1279 ****************************************************************************/
1281 struct cli_session_setup_gensec_state {
1282 struct tevent_context *ev;
1283 struct cli_state *cli;
1284 struct auth_generic_state *auth_generic;
1285 bool is_anonymous;
1286 DATA_BLOB blob_in;
1287 uint8_t *inbuf;
1288 struct iovec *recv_iov;
1289 DATA_BLOB blob_out;
1290 bool local_ready;
1291 bool remote_ready;
1292 DATA_BLOB session_key;
1295 static int cli_session_setup_gensec_state_destructor(
1296 struct cli_session_setup_gensec_state *state)
1298 TALLOC_FREE(state->auth_generic);
1299 data_blob_clear_free(&state->session_key);
1300 return 0;
1303 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
1304 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
1305 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
1306 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
1307 static void cli_session_setup_gensec_ready(struct tevent_req *req);
1309 static struct tevent_req *cli_session_setup_gensec_send(
1310 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1311 const char *user, const char *pass, const char *domain,
1312 enum credentials_use_kerberos krb5_state,
1313 const char *target_service,
1314 const char *target_hostname,
1315 const char *target_principal)
1317 struct tevent_req *req;
1318 struct cli_session_setup_gensec_state *state;
1319 NTSTATUS status;
1320 bool use_spnego_principal = lp_client_use_spnego_principal();
1322 req = tevent_req_create(mem_ctx, &state,
1323 struct cli_session_setup_gensec_state);
1324 if (req == NULL) {
1325 return NULL;
1327 state->ev = ev;
1328 state->cli = cli;
1330 talloc_set_destructor(
1331 state, cli_session_setup_gensec_state_destructor);
1333 if (user == NULL || strlen(user) == 0) {
1334 if (pass != NULL && strlen(pass) == 0) {
1336 * some callers pass "" as no password
1338 * gensec only handles NULL as no password.
1340 pass = NULL;
1344 status = auth_generic_client_prepare(state, &state->auth_generic);
1345 if (tevent_req_nterror(req, status)) {
1346 return tevent_req_post(req, ev);
1349 gensec_want_feature(state->auth_generic->gensec_security,
1350 GENSEC_FEATURE_SESSION_KEY);
1351 if (cli->use_ccache) {
1352 gensec_want_feature(state->auth_generic->gensec_security,
1353 GENSEC_FEATURE_NTLM_CCACHE);
1354 if (pass != NULL && strlen(pass) == 0) {
1356 * some callers pass "" as no password
1358 * GENSEC_FEATURE_NTLM_CCACHE only handles
1359 * NULL as no password.
1361 pass = NULL;
1365 status = auth_generic_set_username(state->auth_generic, user);
1366 if (tevent_req_nterror(req, status)) {
1367 return tevent_req_post(req, ev);
1370 status = auth_generic_set_domain(state->auth_generic, domain);
1371 if (tevent_req_nterror(req, status)) {
1372 return tevent_req_post(req, ev);
1375 if (cli->pw_nt_hash) {
1376 struct samr_Password nt_hash;
1377 size_t converted;
1378 bool ok;
1380 if (pass == NULL) {
1381 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1382 return tevent_req_post(req, ev);
1385 converted = strhex_to_str((char *)nt_hash.hash,
1386 sizeof(nt_hash.hash),
1387 pass, strlen(pass));
1388 if (converted != sizeof(nt_hash.hash)) {
1389 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1390 return tevent_req_post(req, ev);
1393 ok = cli_credentials_set_nt_hash(state->auth_generic->credentials,
1394 &nt_hash, CRED_SPECIFIED);
1395 if (!ok) {
1396 tevent_req_oom(req);
1397 return tevent_req_post(req, ev);
1399 } else {
1400 status = auth_generic_set_password(state->auth_generic, pass);
1401 if (tevent_req_nterror(req, status)) {
1402 return tevent_req_post(req, ev);
1406 cli_credentials_set_kerberos_state(state->auth_generic->credentials,
1407 krb5_state);
1409 if (krb5_state == CRED_DONT_USE_KERBEROS) {
1410 use_spnego_principal = false;
1413 if (target_service != NULL) {
1414 status = gensec_set_target_service(
1415 state->auth_generic->gensec_security,
1416 target_service);
1417 if (tevent_req_nterror(req, status)) {
1418 return tevent_req_post(req, ev);
1422 if (target_hostname != NULL) {
1423 status = gensec_set_target_hostname(
1424 state->auth_generic->gensec_security,
1425 target_hostname);
1426 if (tevent_req_nterror(req, status)) {
1427 return tevent_req_post(req, ev);
1431 if (target_principal != NULL) {
1432 status = gensec_set_target_principal(
1433 state->auth_generic->gensec_security,
1434 target_principal);
1435 if (tevent_req_nterror(req, status)) {
1436 return tevent_req_post(req, ev);
1438 use_spnego_principal = false;
1439 } else if (target_service != NULL && target_hostname != NULL) {
1440 use_spnego_principal = false;
1443 if (use_spnego_principal) {
1444 const DATA_BLOB *b;
1445 b = smbXcli_conn_server_gss_blob(cli->conn);
1446 if (b != NULL) {
1447 state->blob_in = *b;
1451 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
1453 status = auth_generic_client_start(state->auth_generic,
1454 GENSEC_OID_SPNEGO);
1455 if (tevent_req_nterror(req, status)) {
1456 return tevent_req_post(req, ev);
1459 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1460 state->cli->smb2.session = smbXcli_session_create(cli,
1461 cli->conn);
1462 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1463 return tevent_req_post(req, ev);
1467 cli_session_setup_gensec_local_next(req);
1468 if (!tevent_req_is_in_progress(req)) {
1469 return tevent_req_post(req, ev);
1472 return req;
1475 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
1477 struct cli_session_setup_gensec_state *state =
1478 tevent_req_data(req,
1479 struct cli_session_setup_gensec_state);
1480 struct tevent_req *subreq = NULL;
1482 if (state->local_ready) {
1483 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1484 return;
1487 subreq = gensec_update_send(state, state->ev,
1488 state->auth_generic->gensec_security,
1489 state->blob_in);
1490 if (tevent_req_nomem(subreq, req)) {
1491 return;
1493 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1496 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1498 struct tevent_req *req =
1499 tevent_req_callback_data(subreq,
1500 struct tevent_req);
1501 struct cli_session_setup_gensec_state *state =
1502 tevent_req_data(req,
1503 struct cli_session_setup_gensec_state);
1504 NTSTATUS status;
1506 status = gensec_update_recv(subreq, state, &state->blob_out);
1507 TALLOC_FREE(subreq);
1508 state->blob_in = data_blob_null;
1509 if (!NT_STATUS_IS_OK(status) &&
1510 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1512 tevent_req_nterror(req, status);
1513 return;
1516 if (NT_STATUS_IS_OK(status)) {
1517 state->local_ready = true;
1520 if (state->local_ready && state->remote_ready) {
1521 cli_session_setup_gensec_ready(req);
1522 return;
1525 cli_session_setup_gensec_remote_next(req);
1528 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1530 struct cli_session_setup_gensec_state *state =
1531 tevent_req_data(req,
1532 struct cli_session_setup_gensec_state);
1533 struct tevent_req *subreq = NULL;
1535 if (state->remote_ready) {
1536 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1537 return;
1540 subreq = cli_sesssetup_blob_send(state, state->ev,
1541 state->cli, state->blob_out);
1542 if (tevent_req_nomem(subreq, req)) {
1543 return;
1545 tevent_req_set_callback(subreq,
1546 cli_session_setup_gensec_remote_done,
1547 req);
1550 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1552 struct tevent_req *req =
1553 tevent_req_callback_data(subreq,
1554 struct tevent_req);
1555 struct cli_session_setup_gensec_state *state =
1556 tevent_req_data(req,
1557 struct cli_session_setup_gensec_state);
1558 NTSTATUS status;
1560 TALLOC_FREE(state->inbuf);
1561 TALLOC_FREE(state->recv_iov);
1563 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1564 &state->inbuf, &state->recv_iov);
1565 TALLOC_FREE(subreq);
1566 data_blob_free(&state->blob_out);
1567 if (!NT_STATUS_IS_OK(status) &&
1568 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1570 tevent_req_nterror(req, status);
1571 return;
1574 if (NT_STATUS_IS_OK(status)) {
1575 struct smbXcli_session *session = NULL;
1576 bool is_guest = false;
1578 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1579 session = state->cli->smb2.session;
1580 } else {
1581 session = state->cli->smb1.session;
1584 is_guest = smbXcli_session_is_guest(session);
1585 if (is_guest) {
1587 * We can't finish the gensec handshake, we don't
1588 * have a negotiated session key.
1590 * So just pretend we are completely done.
1592 * Note that smbXcli_session_is_guest()
1593 * always returns false if we require signing.
1595 state->blob_in = data_blob_null;
1596 state->local_ready = true;
1599 state->remote_ready = true;
1602 if (state->local_ready && state->remote_ready) {
1603 cli_session_setup_gensec_ready(req);
1604 return;
1607 cli_session_setup_gensec_local_next(req);
1610 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1612 struct cli_session_setup_gensec_state *state =
1613 tevent_req_data(req,
1614 struct cli_session_setup_gensec_state);
1615 const char *server_domain = NULL;
1616 NTSTATUS status;
1618 if (state->blob_in.length != 0) {
1619 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1620 return;
1623 if (state->blob_out.length != 0) {
1624 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1625 return;
1629 * gensec_ntlmssp_server_domain() returns NULL
1630 * if NTLMSSP is not used.
1632 * We can remove this later
1633 * and leave the server domain empty for SMB2 and above
1634 * in future releases.
1636 server_domain = gensec_ntlmssp_server_domain(
1637 state->auth_generic->gensec_security);
1639 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1640 TALLOC_FREE(state->cli->server_domain);
1641 state->cli->server_domain = talloc_strdup(state->cli,
1642 server_domain);
1643 if (state->cli->server_domain == NULL) {
1644 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1645 return;
1649 if (state->is_anonymous) {
1651 * Windows server does not set the
1652 * SMB2_SESSION_FLAG_IS_NULL flag.
1654 * This fix makes sure we do not try
1655 * to verify a signature on the final
1656 * session setup response.
1658 tevent_req_done(req);
1659 return;
1662 status = gensec_session_key(state->auth_generic->gensec_security,
1663 state, &state->session_key);
1664 if (tevent_req_nterror(req, status)) {
1665 return;
1668 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1669 struct smbXcli_session *session = state->cli->smb2.session;
1671 status = smb2cli_session_set_session_key(session,
1672 state->session_key,
1673 state->recv_iov);
1674 if (tevent_req_nterror(req, status)) {
1675 return;
1677 } else {
1678 struct smbXcli_session *session = state->cli->smb1.session;
1679 bool active;
1681 status = smb1cli_session_set_session_key(session,
1682 state->session_key);
1683 if (tevent_req_nterror(req, status)) {
1684 return;
1687 active = smb1cli_conn_activate_signing(state->cli->conn,
1688 state->session_key,
1689 data_blob_null);
1690 if (active) {
1691 bool ok;
1693 ok = smb1cli_conn_check_signing(state->cli->conn,
1694 state->inbuf, 1);
1695 if (!ok) {
1696 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1697 return;
1702 tevent_req_done(req);
1705 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1707 struct cli_session_setup_gensec_state *state =
1708 tevent_req_data(req,
1709 struct cli_session_setup_gensec_state);
1710 NTSTATUS status;
1712 if (tevent_req_is_nterror(req, &status)) {
1713 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1714 return status;
1716 return NT_STATUS_OK;
1719 #ifdef HAVE_KRB5
1721 static char *cli_session_setup_get_principal(
1722 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1723 const char *remote_name, const char *dest_realm)
1725 char *principal = NULL;
1727 if (!lp_client_use_spnego_principal() ||
1728 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
1729 spnego_principal = NULL;
1731 if (spnego_principal != NULL) {
1732 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1733 "principal %s\n", spnego_principal));
1734 return talloc_strdup(mem_ctx, spnego_principal);
1736 if (is_ipaddress(remote_name) ||
1737 strequal(remote_name, STAR_SMBSERVER)) {
1738 return NULL;
1741 DEBUG(3, ("cli_session_setup_spnego: using target "
1742 "hostname not SPNEGO principal\n"));
1744 if (dest_realm) {
1745 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1746 if (realm == NULL) {
1747 return NULL;
1749 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1750 remote_name, realm);
1751 TALLOC_FREE(realm);
1752 } else {
1753 principal =
1754 smb_krb5_get_principal_from_service_hostname(talloc_tos(),
1755 "cifs",
1756 remote_name,
1757 lp_realm());
1759 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1760 principal ? principal : "<null>"));
1762 return principal;
1764 #endif
1766 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1767 const char *principal)
1769 char *account, *p;
1771 account = talloc_strdup(mem_ctx, principal);
1772 if (account == NULL) {
1773 return NULL;
1775 p = strchr_m(account, '@');
1776 if (p != NULL) {
1777 *p = '\0';
1779 return account;
1782 /****************************************************************************
1783 Do a spnego encrypted session setup.
1785 user_domain: The shortname of the domain the user/machine is a member of.
1786 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1787 ****************************************************************************/
1789 struct cli_session_setup_spnego_state {
1790 struct tevent_context *ev;
1791 struct cli_state *cli;
1792 const char *target_hostname;
1793 const char *user;
1794 const char *account;
1795 const char *pass;
1796 const char *user_domain;
1797 const char *dest_realm;
1798 ADS_STATUS result;
1801 #ifdef HAVE_KRB5
1802 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1803 #endif
1805 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1807 static struct tevent_req *cli_session_setup_spnego_send(
1808 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1809 const char *user, const char *pass, const char *user_domain)
1811 struct tevent_req *req, *subreq;
1812 struct cli_session_setup_spnego_state *state;
1813 char *principal = NULL;
1814 char *OIDs[ASN1_MAX_OIDS];
1815 int i;
1816 const char *dest_realm = cli_state_remote_realm(cli);
1817 const DATA_BLOB *server_blob;
1819 req = tevent_req_create(mem_ctx, &state,
1820 struct cli_session_setup_spnego_state);
1821 if (req == NULL) {
1822 return NULL;
1824 state->ev = ev;
1825 state->cli = cli;
1826 state->user = user;
1827 state->pass = pass;
1828 state->user_domain = user_domain;
1829 state->dest_realm = dest_realm;
1831 state->account = cli_session_setup_get_account(state, user);
1832 if (tevent_req_nomem(state->account, req)) {
1833 return tevent_req_post(req, ev);
1836 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1837 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1839 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1840 (unsigned long)server_blob->length));
1842 /* the server might not even do spnego */
1843 if (server_blob->length == 0) {
1844 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1845 goto ntlmssp;
1848 #if 0
1849 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1850 #endif
1852 /* The server sent us the first part of the SPNEGO exchange in the
1853 * negprot reply. It is WRONG to depend on the principal sent in the
1854 * negprot reply, but right now we do it. If we don't receive one,
1855 * we try to best guess, then fall back to NTLM. */
1856 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1857 &principal, NULL) ||
1858 OIDs[0] == NULL) {
1859 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1860 tevent_req_done(req);
1861 return tevent_req_post(req, ev);
1864 /* make sure the server understands kerberos */
1865 for (i=0;OIDs[i];i++) {
1866 if (i == 0)
1867 DEBUG(3,("got OID=%s\n", OIDs[i]));
1868 else
1869 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1870 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1871 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1872 cli->got_kerberos_mechanism = True;
1874 talloc_free(OIDs[i]);
1877 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1879 #ifdef HAVE_KRB5
1880 /* If password is set we reauthenticate to kerberos server
1881 * and do not store results */
1883 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1884 char *tmp;
1886 tmp = cli_session_setup_get_principal(
1887 talloc_tos(), principal, state->target_hostname, dest_realm);
1888 TALLOC_FREE(principal);
1889 principal = tmp;
1891 if (pass && *pass) {
1892 int ret;
1894 use_in_memory_ccache();
1895 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1897 if (ret){
1898 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1899 TALLOC_FREE(principal);
1900 if (cli->fallback_after_kerberos)
1901 goto ntlmssp;
1902 state->result = ADS_ERROR_KRB5(ret);
1903 tevent_req_done(req);
1904 return tevent_req_post(req, ev);
1908 if (principal) {
1909 subreq = cli_session_setup_gensec_send(
1910 state, ev, cli,
1911 state->account, pass, user_domain,
1912 CRED_MUST_USE_KERBEROS,
1913 "cifs", state->target_hostname, principal);
1914 if (tevent_req_nomem(subreq, req)) {
1915 return tevent_req_post(req, ev);
1917 tevent_req_set_callback(
1918 subreq, cli_session_setup_spnego_done_krb,
1919 req);
1920 return req;
1923 #endif
1925 ntlmssp:
1926 subreq = cli_session_setup_gensec_send(
1927 state, state->ev, state->cli,
1928 state->account, state->pass, state->user_domain,
1929 CRED_DONT_USE_KERBEROS,
1930 "cifs", state->target_hostname, NULL);
1931 if (tevent_req_nomem(subreq, req)) {
1932 return tevent_req_post(req, ev);
1934 tevent_req_set_callback(
1935 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1936 return req;
1939 #ifdef HAVE_KRB5
1940 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1942 struct tevent_req *req = tevent_req_callback_data(
1943 subreq, struct tevent_req);
1944 struct cli_session_setup_spnego_state *state = tevent_req_data(
1945 req, struct cli_session_setup_spnego_state);
1946 NTSTATUS status;
1948 status = cli_session_setup_gensec_recv(subreq);
1949 TALLOC_FREE(subreq);
1950 state->result = ADS_ERROR_NT(status);
1952 if (ADS_ERR_OK(state->result) ||
1953 !state->cli->fallback_after_kerberos) {
1954 tevent_req_done(req);
1955 return;
1958 subreq = cli_session_setup_gensec_send(
1959 state, state->ev, state->cli,
1960 state->account, state->pass, state->user_domain,
1961 CRED_DONT_USE_KERBEROS,
1962 "cifs", state->target_hostname, NULL);
1963 if (tevent_req_nomem(subreq, req)) {
1964 return;
1966 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1967 req);
1969 #endif
1971 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1973 struct tevent_req *req = tevent_req_callback_data(
1974 subreq, struct tevent_req);
1975 struct cli_session_setup_spnego_state *state = tevent_req_data(
1976 req, struct cli_session_setup_spnego_state);
1977 NTSTATUS status;
1979 status = cli_session_setup_gensec_recv(subreq);
1980 TALLOC_FREE(subreq);
1981 state->result = ADS_ERROR_NT(status);
1982 tevent_req_done(req);
1985 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1987 struct cli_session_setup_spnego_state *state = tevent_req_data(
1988 req, struct cli_session_setup_spnego_state);
1990 return state->result;
1993 struct cli_session_setup_state {
1994 uint8_t dummy;
1997 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1998 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1999 static void cli_session_setup_done_guest(struct tevent_req *subreq);
2000 static void cli_session_setup_done_plain(struct tevent_req *subreq);
2001 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
2003 /****************************************************************************
2004 Send a session setup. The username and workgroup is in UNIX character
2005 format and must be converted to DOS codepage format before sending. If the
2006 password is in plaintext, the same should be done.
2007 ****************************************************************************/
2009 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
2010 struct tevent_context *ev,
2011 struct cli_state *cli,
2012 const char *user,
2013 const char *pass,
2014 const char *workgroup)
2016 struct tevent_req *req, *subreq;
2017 struct cli_session_setup_state *state;
2018 char *p;
2019 char *user2;
2020 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2021 int passlen = 0;
2023 if (pass != NULL) {
2024 passlen = strlen(pass);
2025 if (passlen > 0) {
2027 * If we have a realm password
2028 * we include the terminating '\0'
2030 passlen += 1;
2034 req = tevent_req_create(mem_ctx, &state,
2035 struct cli_session_setup_state);
2036 if (req == NULL) {
2037 return NULL;
2040 if (user) {
2041 user2 = talloc_strdup(state, user);
2042 } else {
2043 user2 = talloc_strdup(state, "");
2045 if (user2 == NULL) {
2046 tevent_req_oom(req);
2047 return tevent_req_post(req, ev);
2050 if (!workgroup) {
2051 workgroup = "";
2054 /* allow for workgroups as part of the username */
2055 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2056 (p=strchr_m(user2,*lp_winbind_separator()))) {
2057 *p = 0;
2058 user = p+1;
2059 if (!strupper_m(user2)) {
2060 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2061 return tevent_req_post(req, ev);
2063 workgroup = user2;
2066 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2067 tevent_req_done(req);
2068 return tevent_req_post(req, ev);
2071 /* now work out what sort of session setup we are going to
2072 do. I have split this into separate functions to make the
2073 flow a bit easier to understand (tridge) */
2075 /* if its an older server then we have to use the older request format */
2077 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2078 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2079 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2080 " or 'client ntlmv2 auth = yes'\n"));
2081 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2082 return tevent_req_post(req, ev);
2085 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2086 !lp_client_plaintext_auth() && (*pass)) {
2087 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2088 " or 'client ntlmv2 auth = yes'\n"));
2089 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2090 return tevent_req_post(req, ev);
2093 subreq = cli_session_setup_lanman2_send(
2094 state, ev, cli, user, pass, passlen, workgroup);
2095 if (tevent_req_nomem(subreq, req)) {
2096 return tevent_req_post(req, ev);
2098 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2099 req);
2100 return req;
2103 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2104 subreq = cli_session_setup_spnego_send(
2105 state, ev, cli, user, pass, workgroup);
2106 if (tevent_req_nomem(subreq, req)) {
2107 return tevent_req_post(req, ev);
2109 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2110 req);
2111 return req;
2115 * if the server supports extended security then use SPNEGO
2116 * even for anonymous connections.
2118 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2119 subreq = cli_session_setup_spnego_send(
2120 state, ev, cli, user, pass, workgroup);
2121 if (tevent_req_nomem(subreq, req)) {
2122 return tevent_req_post(req, ev);
2124 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2125 req);
2126 return req;
2129 /* if no user is supplied then we have to do an anonymous connection.
2130 passwords are ignored */
2132 if (!user || !*user) {
2133 subreq = cli_session_setup_guest_send(state, ev, cli);
2134 if (tevent_req_nomem(subreq, req)) {
2135 return tevent_req_post(req, ev);
2137 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2138 req);
2139 return req;
2142 /* if the server is share level then send a plaintext null
2143 password at this point. The password is sent in the tree
2144 connect */
2146 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2147 subreq = cli_session_setup_plain_send(
2148 state, ev, cli, user, "", workgroup);
2149 if (tevent_req_nomem(subreq, req)) {
2150 return tevent_req_post(req, ev);
2152 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2153 req);
2154 return req;
2157 /* if the server doesn't support encryption then we have to use
2158 plaintext. The second password is ignored */
2160 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2161 if (!lp_client_plaintext_auth() && (*pass)) {
2162 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2163 " or 'client ntlmv2 auth = yes'\n"));
2164 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2165 return tevent_req_post(req, ev);
2167 subreq = cli_session_setup_plain_send(
2168 state, ev, cli, user, pass, workgroup);
2169 if (tevent_req_nomem(subreq, req)) {
2170 return tevent_req_post(req, ev);
2172 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2173 req);
2174 return req;
2178 /* otherwise do a NT1 style session setup */
2179 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2181 * Don't send an NTLMv2 response without NTLMSSP
2182 * if we want to use spnego support
2184 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2185 " but 'client use spnego = yes"
2186 " and 'client ntlmv2 auth = yes'\n"));
2187 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2188 return tevent_req_post(req, ev);
2191 subreq = cli_session_setup_nt1_send(
2192 state, ev, cli, user, pass, passlen, pass, passlen,
2193 workgroup);
2194 if (tevent_req_nomem(subreq, req)) {
2195 return tevent_req_post(req, ev);
2197 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2198 req);
2199 return req;
2202 tevent_req_done(req);
2203 return tevent_req_post(req, ev);
2206 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2208 struct tevent_req *req = tevent_req_callback_data(
2209 subreq, struct tevent_req);
2210 NTSTATUS status;
2212 status = cli_session_setup_lanman2_recv(subreq);
2213 TALLOC_FREE(subreq);
2214 if (!NT_STATUS_IS_OK(status)) {
2215 tevent_req_nterror(req, status);
2216 return;
2218 tevent_req_done(req);
2221 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2223 struct tevent_req *req = tevent_req_callback_data(
2224 subreq, struct tevent_req);
2225 ADS_STATUS status;
2227 status = cli_session_setup_spnego_recv(subreq);
2228 TALLOC_FREE(subreq);
2229 if (!ADS_ERR_OK(status)) {
2230 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2231 tevent_req_nterror(req, ads_ntstatus(status));
2232 return;
2234 tevent_req_done(req);
2237 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2239 struct tevent_req *req = tevent_req_callback_data(
2240 subreq, struct tevent_req);
2241 NTSTATUS status;
2243 status = cli_session_setup_guest_recv(subreq);
2244 TALLOC_FREE(subreq);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 tevent_req_nterror(req, status);
2247 return;
2249 tevent_req_done(req);
2252 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2254 struct tevent_req *req = tevent_req_callback_data(
2255 subreq, struct tevent_req);
2256 NTSTATUS status;
2258 status = cli_session_setup_plain_recv(subreq);
2259 TALLOC_FREE(subreq);
2260 if (!NT_STATUS_IS_OK(status)) {
2261 tevent_req_nterror(req, status);
2262 return;
2264 tevent_req_done(req);
2267 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2269 struct tevent_req *req = tevent_req_callback_data(
2270 subreq, struct tevent_req);
2271 NTSTATUS status;
2273 status = cli_session_setup_nt1_recv(subreq);
2274 TALLOC_FREE(subreq);
2275 if (!NT_STATUS_IS_OK(status)) {
2276 DEBUG(3, ("cli_session_setup: NT1 session setup "
2277 "failed: %s\n", nt_errstr(status)));
2278 tevent_req_nterror(req, status);
2279 return;
2281 tevent_req_done(req);
2284 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2286 return tevent_req_simple_recv_ntstatus(req);
2289 NTSTATUS cli_session_setup(struct cli_state *cli,
2290 const char *user,
2291 const char *pass,
2292 const char *workgroup)
2294 struct tevent_context *ev;
2295 struct tevent_req *req;
2296 NTSTATUS status = NT_STATUS_NO_MEMORY;
2298 if (smbXcli_conn_has_async_calls(cli->conn)) {
2299 return NT_STATUS_INVALID_PARAMETER;
2301 ev = samba_tevent_context_init(talloc_tos());
2302 if (ev == NULL) {
2303 goto fail;
2305 req = cli_session_setup_send(ev, ev, cli, user, pass, workgroup);
2306 if (req == NULL) {
2307 goto fail;
2309 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2310 goto fail;
2312 status = cli_session_setup_recv(req);
2313 fail:
2314 TALLOC_FREE(ev);
2315 return status;
2318 /****************************************************************************
2319 Send a uloggoff.
2320 *****************************************************************************/
2322 struct cli_ulogoff_state {
2323 struct cli_state *cli;
2324 uint16_t vwv[3];
2327 static void cli_ulogoff_done(struct tevent_req *subreq);
2329 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2330 struct tevent_context *ev,
2331 struct cli_state *cli)
2333 struct tevent_req *req, *subreq;
2334 struct cli_ulogoff_state *state;
2336 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2337 if (req == NULL) {
2338 return NULL;
2340 state->cli = cli;
2342 SCVAL(state->vwv+0, 0, 0xFF);
2343 SCVAL(state->vwv+1, 0, 0);
2344 SSVAL(state->vwv+2, 0, 0);
2346 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
2347 0, NULL);
2348 if (tevent_req_nomem(subreq, req)) {
2349 return tevent_req_post(req, ev);
2351 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2352 return req;
2355 static void cli_ulogoff_done(struct tevent_req *subreq)
2357 struct tevent_req *req = tevent_req_callback_data(
2358 subreq, struct tevent_req);
2359 struct cli_ulogoff_state *state = tevent_req_data(
2360 req, struct cli_ulogoff_state);
2361 NTSTATUS status;
2363 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2364 if (!NT_STATUS_IS_OK(status)) {
2365 tevent_req_nterror(req, status);
2366 return;
2368 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2369 tevent_req_done(req);
2372 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2374 return tevent_req_simple_recv_ntstatus(req);
2377 NTSTATUS cli_ulogoff(struct cli_state *cli)
2379 struct tevent_context *ev;
2380 struct tevent_req *req;
2381 NTSTATUS status = NT_STATUS_NO_MEMORY;
2383 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2384 status = smb2cli_logoff(cli->conn,
2385 cli->timeout,
2386 cli->smb2.session);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 return status;
2390 smb2cli_session_set_id_and_flags(cli->smb2.session,
2391 UINT64_MAX, 0);
2392 return NT_STATUS_OK;
2395 if (smbXcli_conn_has_async_calls(cli->conn)) {
2396 return NT_STATUS_INVALID_PARAMETER;
2398 ev = samba_tevent_context_init(talloc_tos());
2399 if (ev == NULL) {
2400 goto fail;
2402 req = cli_ulogoff_send(ev, ev, cli);
2403 if (req == NULL) {
2404 goto fail;
2406 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2407 goto fail;
2409 status = cli_ulogoff_recv(req);
2410 fail:
2411 TALLOC_FREE(ev);
2412 return status;
2415 /****************************************************************************
2416 Send a tconX.
2417 ****************************************************************************/
2419 struct cli_tcon_andx_state {
2420 struct cli_state *cli;
2421 uint16_t vwv[4];
2422 struct iovec bytes;
2425 static void cli_tcon_andx_done(struct tevent_req *subreq);
2427 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2428 struct tevent_context *ev,
2429 struct cli_state *cli,
2430 const char *share, const char *dev,
2431 const char *pass, int passlen,
2432 struct tevent_req **psmbreq)
2434 struct tevent_req *req, *subreq;
2435 struct cli_tcon_andx_state *state;
2436 uint8_t p24[24];
2437 uint16_t *vwv;
2438 char *tmp = NULL;
2439 uint8_t *bytes;
2440 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2441 uint16_t tcon_flags = 0;
2443 *psmbreq = NULL;
2445 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2446 if (req == NULL) {
2447 return NULL;
2449 state->cli = cli;
2450 vwv = state->vwv;
2452 cli->share = talloc_strdup(cli, share);
2453 if (!cli->share) {
2454 return NULL;
2457 /* in user level security don't send a password now */
2458 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2459 passlen = 1;
2460 pass = "";
2461 } else if (pass == NULL) {
2462 DEBUG(1, ("Server not using user level security and no "
2463 "password supplied.\n"));
2464 goto access_denied;
2467 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2468 *pass && passlen != 24) {
2469 if (!lp_client_lanman_auth()) {
2470 DEBUG(1, ("Server requested LANMAN password "
2471 "(share-level security) but "
2472 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2473 goto access_denied;
2477 * Non-encrypted passwords - convert to DOS codepage before
2478 * encryption.
2480 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2481 passlen = 24;
2482 pass = (const char *)p24;
2483 } else {
2484 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2485 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2486 == 0) {
2487 uint8_t *tmp_pass;
2489 if (!lp_client_plaintext_auth() && (*pass)) {
2490 DEBUG(1, ("Server requested PLAINTEXT "
2491 "password but "
2492 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2493 goto access_denied;
2497 * Non-encrypted passwords - convert to DOS codepage
2498 * before using.
2500 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2501 if (tevent_req_nomem(tmp_pass, req)) {
2502 return tevent_req_post(req, ev);
2504 tmp_pass = trans2_bytes_push_str(tmp_pass,
2505 false, /* always DOS */
2506 pass,
2507 passlen,
2508 NULL);
2509 if (tevent_req_nomem(tmp_pass, req)) {
2510 return tevent_req_post(req, ev);
2512 pass = (const char *)tmp_pass;
2513 passlen = talloc_get_size(tmp_pass);
2517 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2518 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2520 SCVAL(vwv+0, 0, 0xFF);
2521 SCVAL(vwv+0, 1, 0);
2522 SSVAL(vwv+1, 0, 0);
2523 SSVAL(vwv+2, 0, tcon_flags);
2524 SSVAL(vwv+3, 0, passlen);
2526 if (passlen && pass) {
2527 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2528 } else {
2529 bytes = talloc_array(state, uint8_t, 0);
2533 * Add the sharename
2535 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2536 smbXcli_conn_remote_name(cli->conn), share);
2537 if (tmp == NULL) {
2538 TALLOC_FREE(req);
2539 return NULL;
2541 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2542 NULL);
2543 TALLOC_FREE(tmp);
2546 * Add the devicetype
2548 tmp = talloc_strdup_upper(talloc_tos(), dev);
2549 if (tmp == NULL) {
2550 TALLOC_FREE(req);
2551 return NULL;
2553 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2554 TALLOC_FREE(tmp);
2556 if (bytes == NULL) {
2557 TALLOC_FREE(req);
2558 return NULL;
2561 state->bytes.iov_base = (void *)bytes;
2562 state->bytes.iov_len = talloc_get_size(bytes);
2564 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2565 1, &state->bytes);
2566 if (subreq == NULL) {
2567 TALLOC_FREE(req);
2568 return NULL;
2570 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2571 *psmbreq = subreq;
2572 return req;
2574 access_denied:
2575 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2576 return tevent_req_post(req, ev);
2579 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2580 struct tevent_context *ev,
2581 struct cli_state *cli,
2582 const char *share, const char *dev,
2583 const char *pass, int passlen)
2585 struct tevent_req *req, *subreq;
2586 NTSTATUS status;
2588 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2589 &subreq);
2590 if (req == NULL) {
2591 return NULL;
2593 if (subreq == NULL) {
2594 return req;
2596 status = smb1cli_req_chain_submit(&subreq, 1);
2597 if (!NT_STATUS_IS_OK(status)) {
2598 tevent_req_nterror(req, status);
2599 return tevent_req_post(req, ev);
2601 return req;
2604 static void cli_tcon_andx_done(struct tevent_req *subreq)
2606 struct tevent_req *req = tevent_req_callback_data(
2607 subreq, struct tevent_req);
2608 struct cli_tcon_andx_state *state = tevent_req_data(
2609 req, struct cli_tcon_andx_state);
2610 struct cli_state *cli = state->cli;
2611 uint8_t *in;
2612 uint8_t *inhdr;
2613 uint8_t wct;
2614 uint16_t *vwv;
2615 uint32_t num_bytes;
2616 uint8_t *bytes;
2617 NTSTATUS status;
2618 uint16_t optional_support = 0;
2620 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2621 &num_bytes, &bytes);
2622 TALLOC_FREE(subreq);
2623 if (!NT_STATUS_IS_OK(status)) {
2624 tevent_req_nterror(req, status);
2625 return;
2628 inhdr = in + NBT_HDR_SIZE;
2630 if (num_bytes) {
2631 if (clistr_pull_talloc(cli,
2632 (const char *)inhdr,
2633 SVAL(inhdr, HDR_FLG2),
2634 &cli->dev,
2635 bytes,
2636 num_bytes,
2637 STR_TERMINATE|STR_ASCII) == -1) {
2638 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2639 return;
2641 } else {
2642 cli->dev = talloc_strdup(cli, "");
2643 if (cli->dev == NULL) {
2644 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2645 return;
2649 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2650 /* almost certainly win95 - enable bug fixes */
2651 cli->win95 = True;
2655 * Make sure that we have the optional support 16-bit field. WCT > 2.
2656 * Avoids issues when connecting to Win9x boxes sharing files
2659 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2660 optional_support = SVAL(vwv+2, 0);
2663 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2664 smb1cli_session_protect_session_key(cli->smb1.session);
2667 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2668 SVAL(inhdr, HDR_TID),
2669 optional_support,
2670 0, /* maximal_access */
2671 0, /* guest_maximal_access */
2672 NULL, /* service */
2673 NULL); /* fs_type */
2675 tevent_req_done(req);
2678 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2680 return tevent_req_simple_recv_ntstatus(req);
2683 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2684 const char *dev, const char *pass, int passlen)
2686 TALLOC_CTX *frame = talloc_stackframe();
2687 struct tevent_context *ev;
2688 struct tevent_req *req;
2689 NTSTATUS status = NT_STATUS_NO_MEMORY;
2691 if (smbXcli_conn_has_async_calls(cli->conn)) {
2693 * Can't use sync call while an async call is in flight
2695 status = NT_STATUS_INVALID_PARAMETER;
2696 goto fail;
2699 ev = samba_tevent_context_init(frame);
2700 if (ev == NULL) {
2701 goto fail;
2704 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2705 if (req == NULL) {
2706 goto fail;
2709 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2710 goto fail;
2713 status = cli_tcon_andx_recv(req);
2714 fail:
2715 TALLOC_FREE(frame);
2716 return status;
2719 struct cli_tree_connect_state {
2720 struct cli_state *cli;
2723 static struct tevent_req *cli_raw_tcon_send(
2724 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2725 const char *service, const char *pass, const char *dev);
2726 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2727 uint16_t *max_xmit, uint16_t *tid);
2729 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2730 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2731 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2733 static struct tevent_req *cli_tree_connect_send(
2734 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2735 const char *share, const char *dev, const char *pass, int passlen)
2737 struct tevent_req *req, *subreq;
2738 struct cli_tree_connect_state *state;
2740 req = tevent_req_create(mem_ctx, &state,
2741 struct cli_tree_connect_state);
2742 if (req == NULL) {
2743 return NULL;
2745 state->cli = cli;
2747 cli->share = talloc_strdup(cli, share);
2748 if (tevent_req_nomem(cli->share, req)) {
2749 return tevent_req_post(req, ev);
2752 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2753 char *unc;
2755 cli->smb2.tcon = smbXcli_tcon_create(cli);
2756 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2757 return tevent_req_post(req, ev);
2760 unc = talloc_asprintf(state, "\\\\%s\\%s",
2761 smbXcli_conn_remote_name(cli->conn),
2762 share);
2763 if (tevent_req_nomem(unc, req)) {
2764 return tevent_req_post(req, ev);
2767 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2768 cli->smb2.session, cli->smb2.tcon,
2769 0, /* flags */
2770 unc);
2771 if (tevent_req_nomem(subreq, req)) {
2772 return tevent_req_post(req, ev);
2774 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2775 req);
2776 return req;
2779 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2780 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2781 pass, passlen);
2782 if (tevent_req_nomem(subreq, req)) {
2783 return tevent_req_post(req, ev);
2785 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2786 req);
2787 return req;
2790 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2791 if (tevent_req_nomem(subreq, req)) {
2792 return tevent_req_post(req, ev);
2794 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2796 return req;
2799 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2801 tevent_req_simple_finish_ntstatus(
2802 subreq, smb2cli_tcon_recv(subreq));
2805 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2807 tevent_req_simple_finish_ntstatus(
2808 subreq, cli_tcon_andx_recv(subreq));
2811 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2813 struct tevent_req *req = tevent_req_callback_data(
2814 subreq, struct tevent_req);
2815 struct cli_tree_connect_state *state = tevent_req_data(
2816 req, struct cli_tree_connect_state);
2817 NTSTATUS status;
2818 uint16_t max_xmit = 0;
2819 uint16_t tid = 0;
2821 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2822 if (tevent_req_nterror(req, status)) {
2823 return;
2826 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2827 tid,
2828 0, /* optional_support */
2829 0, /* maximal_access */
2830 0, /* guest_maximal_access */
2831 NULL, /* service */
2832 NULL); /* fs_type */
2834 tevent_req_done(req);
2837 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2839 return tevent_req_simple_recv_ntstatus(req);
2842 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2843 const char *dev, const char *pass, int passlen)
2845 struct tevent_context *ev;
2846 struct tevent_req *req;
2847 NTSTATUS status = NT_STATUS_NO_MEMORY;
2849 if (smbXcli_conn_has_async_calls(cli->conn)) {
2850 return NT_STATUS_INVALID_PARAMETER;
2852 ev = samba_tevent_context_init(talloc_tos());
2853 if (ev == NULL) {
2854 goto fail;
2856 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2857 if (req == NULL) {
2858 goto fail;
2860 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2861 goto fail;
2863 status = cli_tree_connect_recv(req);
2864 fail:
2865 TALLOC_FREE(ev);
2866 return status;
2869 /****************************************************************************
2870 Send a tree disconnect.
2871 ****************************************************************************/
2873 struct cli_tdis_state {
2874 struct cli_state *cli;
2877 static void cli_tdis_done(struct tevent_req *subreq);
2879 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2880 struct tevent_context *ev,
2881 struct cli_state *cli)
2883 struct tevent_req *req, *subreq;
2884 struct cli_tdis_state *state;
2886 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2887 if (req == NULL) {
2888 return NULL;
2890 state->cli = cli;
2892 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2893 if (tevent_req_nomem(subreq, req)) {
2894 return tevent_req_post(req, ev);
2896 tevent_req_set_callback(subreq, cli_tdis_done, req);
2897 return req;
2900 static void cli_tdis_done(struct tevent_req *subreq)
2902 struct tevent_req *req = tevent_req_callback_data(
2903 subreq, struct tevent_req);
2904 struct cli_tdis_state *state = tevent_req_data(
2905 req, struct cli_tdis_state);
2906 NTSTATUS status;
2908 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2909 TALLOC_FREE(subreq);
2910 if (!NT_STATUS_IS_OK(status)) {
2911 tevent_req_nterror(req, status);
2912 return;
2914 cli_state_set_tid(state->cli, UINT16_MAX);
2915 tevent_req_done(req);
2918 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2920 return tevent_req_simple_recv_ntstatus(req);
2923 NTSTATUS cli_tdis(struct cli_state *cli)
2925 struct tevent_context *ev;
2926 struct tevent_req *req;
2927 NTSTATUS status = NT_STATUS_NO_MEMORY;
2929 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2930 return smb2cli_tdis(cli->conn,
2931 cli->timeout,
2932 cli->smb2.session,
2933 cli->smb2.tcon);
2936 if (smbXcli_conn_has_async_calls(cli->conn)) {
2937 return NT_STATUS_INVALID_PARAMETER;
2939 ev = samba_tevent_context_init(talloc_tos());
2940 if (ev == NULL) {
2941 goto fail;
2943 req = cli_tdis_send(ev, ev, cli);
2944 if (req == NULL) {
2945 goto fail;
2947 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2948 goto fail;
2950 status = cli_tdis_recv(req);
2951 fail:
2952 TALLOC_FREE(ev);
2953 return status;
2956 struct cli_connect_sock_state {
2957 const char **called_names;
2958 const char **calling_names;
2959 int *called_types;
2960 int fd;
2961 uint16_t port;
2964 static void cli_connect_sock_done(struct tevent_req *subreq);
2967 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2968 * nonzero address.
2971 static struct tevent_req *cli_connect_sock_send(
2972 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2973 const char *host, int name_type, const struct sockaddr_storage *pss,
2974 const char *myname, uint16_t port)
2976 struct tevent_req *req, *subreq;
2977 struct cli_connect_sock_state *state;
2978 const char *prog;
2979 struct sockaddr_storage *addrs;
2980 unsigned i, num_addrs;
2981 NTSTATUS status;
2983 req = tevent_req_create(mem_ctx, &state,
2984 struct cli_connect_sock_state);
2985 if (req == NULL) {
2986 return NULL;
2989 prog = getenv("LIBSMB_PROG");
2990 if (prog != NULL) {
2991 state->fd = sock_exec(prog);
2992 if (state->fd == -1) {
2993 status = map_nt_error_from_unix(errno);
2994 tevent_req_nterror(req, status);
2995 } else {
2996 state->port = 0;
2997 tevent_req_done(req);
2999 return tevent_req_post(req, ev);
3002 if ((pss == NULL) || is_zero_addr(pss)) {
3005 * Here we cheat. resolve_name_list is not async at all. So
3006 * this call will only be really async if the name lookup has
3007 * been done externally.
3010 status = resolve_name_list(state, host, name_type,
3011 &addrs, &num_addrs);
3012 if (!NT_STATUS_IS_OK(status)) {
3013 tevent_req_nterror(req, status);
3014 return tevent_req_post(req, ev);
3016 } else {
3017 addrs = talloc_array(state, struct sockaddr_storage, 1);
3018 if (tevent_req_nomem(addrs, req)) {
3019 return tevent_req_post(req, ev);
3021 addrs[0] = *pss;
3022 num_addrs = 1;
3025 state->called_names = talloc_array(state, const char *, num_addrs);
3026 if (tevent_req_nomem(state->called_names, req)) {
3027 return tevent_req_post(req, ev);
3029 state->called_types = talloc_array(state, int, num_addrs);
3030 if (tevent_req_nomem(state->called_types, req)) {
3031 return tevent_req_post(req, ev);
3033 state->calling_names = talloc_array(state, const char *, num_addrs);
3034 if (tevent_req_nomem(state->calling_names, req)) {
3035 return tevent_req_post(req, ev);
3037 for (i=0; i<num_addrs; i++) {
3038 state->called_names[i] = host;
3039 state->called_types[i] = name_type;
3040 state->calling_names[i] = myname;
3043 subreq = smbsock_any_connect_send(
3044 state, ev, addrs, state->called_names, state->called_types,
3045 state->calling_names, NULL, num_addrs, port);
3046 if (tevent_req_nomem(subreq, req)) {
3047 return tevent_req_post(req, ev);
3049 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
3050 return req;
3053 static void cli_connect_sock_done(struct tevent_req *subreq)
3055 struct tevent_req *req = tevent_req_callback_data(
3056 subreq, struct tevent_req);
3057 struct cli_connect_sock_state *state = tevent_req_data(
3058 req, struct cli_connect_sock_state);
3059 NTSTATUS status;
3061 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3062 &state->port);
3063 TALLOC_FREE(subreq);
3064 if (tevent_req_nterror(req, status)) {
3065 return;
3067 set_socket_options(state->fd, lp_socket_options());
3068 tevent_req_done(req);
3071 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3072 int *pfd, uint16_t *pport)
3074 struct cli_connect_sock_state *state = tevent_req_data(
3075 req, struct cli_connect_sock_state);
3076 NTSTATUS status;
3078 if (tevent_req_is_nterror(req, &status)) {
3079 return status;
3081 *pfd = state->fd;
3082 *pport = state->port;
3083 return NT_STATUS_OK;
3086 struct cli_connect_nb_state {
3087 const char *desthost;
3088 int signing_state;
3089 int flags;
3090 struct cli_state *cli;
3093 static void cli_connect_nb_done(struct tevent_req *subreq);
3095 static struct tevent_req *cli_connect_nb_send(
3096 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3097 const char *host, const struct sockaddr_storage *dest_ss,
3098 uint16_t port, int name_type, const char *myname,
3099 int signing_state, int flags)
3101 struct tevent_req *req, *subreq;
3102 struct cli_connect_nb_state *state;
3104 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3105 if (req == NULL) {
3106 return NULL;
3108 state->signing_state = signing_state;
3109 state->flags = flags;
3111 if (host != NULL) {
3112 char *p = strchr(host, '#');
3114 if (p != NULL) {
3115 name_type = strtol(p+1, NULL, 16);
3116 host = talloc_strndup(state, host, p - host);
3117 if (tevent_req_nomem(host, req)) {
3118 return tevent_req_post(req, ev);
3122 state->desthost = host;
3123 } else if (dest_ss != NULL) {
3124 state->desthost = print_canonical_sockaddr(state, dest_ss);
3125 if (tevent_req_nomem(state->desthost, req)) {
3126 return tevent_req_post(req, ev);
3128 } else {
3129 /* No host or dest_ss given. Error out. */
3130 tevent_req_error(req, EINVAL);
3131 return tevent_req_post(req, ev);
3134 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3135 myname, port);
3136 if (tevent_req_nomem(subreq, req)) {
3137 return tevent_req_post(req, ev);
3139 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3140 return req;
3143 static void cli_connect_nb_done(struct tevent_req *subreq)
3145 struct tevent_req *req = tevent_req_callback_data(
3146 subreq, struct tevent_req);
3147 struct cli_connect_nb_state *state = tevent_req_data(
3148 req, struct cli_connect_nb_state);
3149 NTSTATUS status;
3150 int fd = 0;
3151 uint16_t port;
3153 status = cli_connect_sock_recv(subreq, &fd, &port);
3154 TALLOC_FREE(subreq);
3155 if (tevent_req_nterror(req, status)) {
3156 return;
3159 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3160 state->signing_state, state->flags);
3161 if (tevent_req_nomem(state->cli, req)) {
3162 close(fd);
3163 return;
3165 tevent_req_done(req);
3168 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3169 struct cli_state **pcli)
3171 struct cli_connect_nb_state *state = tevent_req_data(
3172 req, struct cli_connect_nb_state);
3173 NTSTATUS status;
3175 if (tevent_req_is_nterror(req, &status)) {
3176 return status;
3178 *pcli = talloc_move(NULL, &state->cli);
3179 return NT_STATUS_OK;
3182 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3183 uint16_t port, int name_type, const char *myname,
3184 int signing_state, int flags, struct cli_state **pcli)
3186 struct tevent_context *ev;
3187 struct tevent_req *req;
3188 NTSTATUS status = NT_STATUS_NO_MEMORY;
3190 ev = samba_tevent_context_init(talloc_tos());
3191 if (ev == NULL) {
3192 goto fail;
3194 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3195 myname, signing_state, flags);
3196 if (req == NULL) {
3197 goto fail;
3199 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3200 goto fail;
3202 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3203 goto fail;
3205 status = cli_connect_nb_recv(req, pcli);
3206 fail:
3207 TALLOC_FREE(ev);
3208 return status;
3211 struct cli_start_connection_state {
3212 struct tevent_context *ev;
3213 struct cli_state *cli;
3214 int min_protocol;
3215 int max_protocol;
3218 static void cli_start_connection_connected(struct tevent_req *subreq);
3219 static void cli_start_connection_done(struct tevent_req *subreq);
3222 establishes a connection to after the negprot.
3223 @param output_cli A fully initialised cli structure, non-null only on success
3224 @param dest_host The netbios name of the remote host
3225 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3226 @param port (optional) The destination port (0 for default)
3229 static struct tevent_req *cli_start_connection_send(
3230 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3231 const char *my_name, const char *dest_host,
3232 const struct sockaddr_storage *dest_ss, int port,
3233 int signing_state, int flags)
3235 struct tevent_req *req, *subreq;
3236 struct cli_start_connection_state *state;
3238 req = tevent_req_create(mem_ctx, &state,
3239 struct cli_start_connection_state);
3240 if (req == NULL) {
3241 return NULL;
3243 state->ev = ev;
3245 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3246 state->min_protocol = lp_client_ipc_min_protocol();
3247 state->max_protocol = lp_client_ipc_max_protocol();
3248 } else {
3249 state->min_protocol = lp_client_min_protocol();
3250 state->max_protocol = lp_client_max_protocol();
3253 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3254 0x20, my_name, signing_state, flags);
3255 if (tevent_req_nomem(subreq, req)) {
3256 return tevent_req_post(req, ev);
3258 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3259 return req;
3262 static void cli_start_connection_connected(struct tevent_req *subreq)
3264 struct tevent_req *req = tevent_req_callback_data(
3265 subreq, struct tevent_req);
3266 struct cli_start_connection_state *state = tevent_req_data(
3267 req, struct cli_start_connection_state);
3268 NTSTATUS status;
3270 status = cli_connect_nb_recv(subreq, &state->cli);
3271 TALLOC_FREE(subreq);
3272 if (tevent_req_nterror(req, status)) {
3273 return;
3276 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3277 state->cli->timeout,
3278 state->min_protocol,
3279 state->max_protocol);
3280 if (tevent_req_nomem(subreq, req)) {
3281 return;
3283 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3286 static void cli_start_connection_done(struct tevent_req *subreq)
3288 struct tevent_req *req = tevent_req_callback_data(
3289 subreq, struct tevent_req);
3290 struct cli_start_connection_state *state = tevent_req_data(
3291 req, struct cli_start_connection_state);
3292 NTSTATUS status;
3294 status = smbXcli_negprot_recv(subreq);
3295 TALLOC_FREE(subreq);
3296 if (tevent_req_nterror(req, status)) {
3297 return;
3300 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3301 /* Ensure we ask for some initial credits. */
3302 smb2cli_conn_set_max_credits(state->cli->conn,
3303 DEFAULT_SMB2_MAX_CREDITS);
3306 tevent_req_done(req);
3309 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3310 struct cli_state **output_cli)
3312 struct cli_start_connection_state *state = tevent_req_data(
3313 req, struct cli_start_connection_state);
3314 NTSTATUS status;
3316 if (tevent_req_is_nterror(req, &status)) {
3317 return status;
3319 *output_cli = state->cli;
3321 return NT_STATUS_OK;
3324 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3325 const char *my_name,
3326 const char *dest_host,
3327 const struct sockaddr_storage *dest_ss, int port,
3328 int signing_state, int flags)
3330 struct tevent_context *ev;
3331 struct tevent_req *req;
3332 NTSTATUS status = NT_STATUS_NO_MEMORY;
3334 ev = samba_tevent_context_init(talloc_tos());
3335 if (ev == NULL) {
3336 goto fail;
3338 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3339 port, signing_state, flags);
3340 if (req == NULL) {
3341 goto fail;
3343 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3344 goto fail;
3346 status = cli_start_connection_recv(req, output_cli);
3347 fail:
3348 TALLOC_FREE(ev);
3349 return status;
3353 establishes a connection right up to doing tconX, password specified.
3354 @param output_cli A fully initialised cli structure, non-null only on success
3355 @param dest_host The netbios name of the remote host
3356 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3357 @param port (optional) The destination port (0 for default)
3358 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3359 @param service_type The 'type' of serivice.
3360 @param user Username, unix string
3361 @param domain User's domain
3362 @param password User's password, unencrypted unix string.
3365 struct cli_full_connection_state {
3366 struct tevent_context *ev;
3367 const char *service;
3368 const char *service_type;
3369 const char *user;
3370 const char *domain;
3371 const char *password;
3372 int pw_len;
3373 int flags;
3374 struct cli_state *cli;
3377 static int cli_full_connection_state_destructor(
3378 struct cli_full_connection_state *s);
3379 static void cli_full_connection_started(struct tevent_req *subreq);
3380 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3381 static void cli_full_connection_done(struct tevent_req *subreq);
3383 struct tevent_req *cli_full_connection_send(
3384 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3385 const char *my_name, const char *dest_host,
3386 const struct sockaddr_storage *dest_ss, int port,
3387 const char *service, const char *service_type,
3388 const char *user, const char *domain,
3389 const char *password, int flags, int signing_state)
3391 struct tevent_req *req, *subreq;
3392 struct cli_full_connection_state *state;
3394 req = tevent_req_create(mem_ctx, &state,
3395 struct cli_full_connection_state);
3396 if (req == NULL) {
3397 return NULL;
3399 talloc_set_destructor(state, cli_full_connection_state_destructor);
3401 state->ev = ev;
3402 state->service = service;
3403 state->service_type = service_type;
3404 state->user = user;
3405 state->domain = domain;
3406 state->password = password;
3407 state->flags = flags;
3409 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3410 if (state->password == NULL) {
3411 state->password = "";
3414 subreq = cli_start_connection_send(
3415 state, ev, my_name, dest_host, dest_ss, port,
3416 signing_state, flags);
3417 if (tevent_req_nomem(subreq, req)) {
3418 return tevent_req_post(req, ev);
3420 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3421 return req;
3424 static int cli_full_connection_state_destructor(
3425 struct cli_full_connection_state *s)
3427 if (s->cli != NULL) {
3428 cli_shutdown(s->cli);
3429 s->cli = NULL;
3431 return 0;
3434 static void cli_full_connection_started(struct tevent_req *subreq)
3436 struct tevent_req *req = tevent_req_callback_data(
3437 subreq, struct tevent_req);
3438 struct cli_full_connection_state *state = tevent_req_data(
3439 req, struct cli_full_connection_state);
3440 NTSTATUS status;
3442 status = cli_start_connection_recv(subreq, &state->cli);
3443 TALLOC_FREE(subreq);
3444 if (tevent_req_nterror(req, status)) {
3445 return;
3447 subreq = cli_session_setup_send(
3448 state, state->ev, state->cli, state->user,
3449 state->password, state->domain);
3450 if (tevent_req_nomem(subreq, req)) {
3451 return;
3453 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3456 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3458 struct tevent_req *req = tevent_req_callback_data(
3459 subreq, struct tevent_req);
3460 struct cli_full_connection_state *state = tevent_req_data(
3461 req, struct cli_full_connection_state);
3462 NTSTATUS status;
3464 status = cli_session_setup_recv(subreq);
3465 TALLOC_FREE(subreq);
3467 if (!NT_STATUS_IS_OK(status) &&
3468 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3470 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3472 subreq = cli_session_setup_send(
3473 state, state->ev, state->cli, "", "",
3474 state->domain);
3475 if (tevent_req_nomem(subreq, req)) {
3476 return;
3478 tevent_req_set_callback(
3479 subreq, cli_full_connection_sess_set_up, req);
3480 return;
3483 if (tevent_req_nterror(req, status)) {
3484 return;
3487 if (state->service != NULL) {
3488 subreq = cli_tree_connect_send(
3489 state, state->ev, state->cli,
3490 state->service, state->service_type,
3491 state->password, state->pw_len);
3492 if (tevent_req_nomem(subreq, req)) {
3493 return;
3495 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3496 return;
3499 tevent_req_done(req);
3502 static void cli_full_connection_done(struct tevent_req *subreq)
3504 struct tevent_req *req = tevent_req_callback_data(
3505 subreq, struct tevent_req);
3506 NTSTATUS status;
3508 status = cli_tree_connect_recv(subreq);
3509 TALLOC_FREE(subreq);
3510 if (tevent_req_nterror(req, status)) {
3511 return;
3514 tevent_req_done(req);
3517 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3518 struct cli_state **output_cli)
3520 struct cli_full_connection_state *state = tevent_req_data(
3521 req, struct cli_full_connection_state);
3522 NTSTATUS status;
3524 if (tevent_req_is_nterror(req, &status)) {
3525 return status;
3527 *output_cli = state->cli;
3528 talloc_set_destructor(state, NULL);
3529 return NT_STATUS_OK;
3532 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3533 const char *my_name,
3534 const char *dest_host,
3535 const struct sockaddr_storage *dest_ss, int port,
3536 const char *service, const char *service_type,
3537 const char *user, const char *domain,
3538 const char *password, int flags,
3539 int signing_state)
3541 struct tevent_context *ev;
3542 struct tevent_req *req;
3543 NTSTATUS status = NT_STATUS_NO_MEMORY;
3545 ev = samba_tevent_context_init(talloc_tos());
3546 if (ev == NULL) {
3547 goto fail;
3549 req = cli_full_connection_send(
3550 ev, ev, my_name, dest_host, dest_ss, port, service,
3551 service_type, user, domain, password, flags, signing_state);
3552 if (req == NULL) {
3553 goto fail;
3555 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3556 goto fail;
3558 status = cli_full_connection_recv(req, output_cli);
3559 fail:
3560 TALLOC_FREE(ev);
3561 return status;
3564 /****************************************************************************
3565 Send an old style tcon.
3566 ****************************************************************************/
3567 struct cli_raw_tcon_state {
3568 uint16_t *ret_vwv;
3571 static void cli_raw_tcon_done(struct tevent_req *subreq);
3573 static struct tevent_req *cli_raw_tcon_send(
3574 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3575 const char *service, const char *pass, const char *dev)
3577 struct tevent_req *req, *subreq;
3578 struct cli_raw_tcon_state *state;
3579 uint8_t *bytes;
3581 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3582 if (req == NULL) {
3583 return NULL;
3586 if (!lp_client_plaintext_auth() && (*pass)) {
3587 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3588 " or 'client ntlmv2 auth = yes'\n"));
3589 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3590 return tevent_req_post(req, ev);
3593 bytes = talloc_array(state, uint8_t, 0);
3594 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3595 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3596 service, strlen(service)+1, NULL);
3597 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3598 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3599 pass, strlen(pass)+1, NULL);
3600 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3601 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3602 dev, strlen(dev)+1, NULL);
3604 if (tevent_req_nomem(bytes, req)) {
3605 return tevent_req_post(req, ev);
3608 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3609 talloc_get_size(bytes), bytes);
3610 if (tevent_req_nomem(subreq, req)) {
3611 return tevent_req_post(req, ev);
3613 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3614 return req;
3617 static void cli_raw_tcon_done(struct tevent_req *subreq)
3619 struct tevent_req *req = tevent_req_callback_data(
3620 subreq, struct tevent_req);
3621 struct cli_raw_tcon_state *state = tevent_req_data(
3622 req, struct cli_raw_tcon_state);
3623 NTSTATUS status;
3625 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3626 NULL, NULL);
3627 TALLOC_FREE(subreq);
3628 if (tevent_req_nterror(req, status)) {
3629 return;
3631 tevent_req_done(req);
3634 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3635 uint16_t *max_xmit, uint16_t *tid)
3637 struct cli_raw_tcon_state *state = tevent_req_data(
3638 req, struct cli_raw_tcon_state);
3639 NTSTATUS status;
3641 if (tevent_req_is_nterror(req, &status)) {
3642 return status;
3644 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3645 *tid = SVAL(state->ret_vwv + 1, 0);
3646 return NT_STATUS_OK;
3649 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3650 const char *service, const char *pass, const char *dev,
3651 uint16_t *max_xmit, uint16_t *tid)
3653 struct tevent_context *ev;
3654 struct tevent_req *req;
3655 NTSTATUS status = NT_STATUS_NO_MEMORY;
3657 ev = samba_tevent_context_init(talloc_tos());
3658 if (ev == NULL) {
3659 goto fail;
3661 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3662 if (req == NULL) {
3663 goto fail;
3665 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3666 goto fail;
3668 status = cli_raw_tcon_recv(req, max_xmit, tid);
3669 fail:
3670 TALLOC_FREE(ev);
3671 return status;
3674 /* Return a cli_state pointing at the IPC$ share for the given server */
3676 struct cli_state *get_ipc_connect(char *server,
3677 struct sockaddr_storage *server_ss,
3678 const struct user_auth_info *user_info)
3680 struct cli_state *cli;
3681 NTSTATUS nt_status;
3682 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3684 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3685 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3688 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3689 get_cmdline_auth_info_username(user_info),
3690 lp_workgroup(),
3691 get_cmdline_auth_info_password(user_info),
3692 flags,
3693 SMB_SIGNING_DEFAULT);
3695 if (NT_STATUS_IS_OK(nt_status)) {
3696 return cli;
3697 } else if (is_ipaddress(server)) {
3698 /* windows 9* needs a correct NMB name for connections */
3699 fstring remote_name;
3701 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3702 cli = get_ipc_connect(remote_name, server_ss, user_info);
3703 if (cli)
3704 return cli;
3707 return NULL;
3711 * Given the IP address of a master browser on the network, return its
3712 * workgroup and connect to it.
3714 * This function is provided to allow additional processing beyond what
3715 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3716 * browsers and obtain each master browsers' list of domains (in case the
3717 * first master browser is recently on the network and has not yet
3718 * synchronized with other master browsers and therefore does not yet have the
3719 * entire network browse list)
3722 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3723 struct sockaddr_storage *mb_ip,
3724 const struct user_auth_info *user_info,
3725 char **pp_workgroup_out)
3727 char addr[INET6_ADDRSTRLEN];
3728 fstring name;
3729 struct cli_state *cli;
3730 struct sockaddr_storage server_ss;
3732 *pp_workgroup_out = NULL;
3734 print_sockaddr(addr, sizeof(addr), mb_ip);
3735 DEBUG(99, ("Looking up name of master browser %s\n",
3736 addr));
3739 * Do a name status query to find out the name of the master browser.
3740 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3741 * master browser will not respond to a wildcard query (or, at least,
3742 * an NT4 server acting as the domain master browser will not).
3744 * We might be able to use ONLY the query on MSBROWSE, but that's not
3745 * yet been tested with all Windows versions, so until it is, leave
3746 * the original wildcard query as the first choice and fall back to
3747 * MSBROWSE if the wildcard query fails.
3749 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3750 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3752 DEBUG(99, ("Could not retrieve name status for %s\n",
3753 addr));
3754 return NULL;
3757 if (!find_master_ip(name, &server_ss)) {
3758 DEBUG(99, ("Could not find master ip for %s\n", name));
3759 return NULL;
3762 *pp_workgroup_out = talloc_strdup(ctx, name);
3764 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3766 print_sockaddr(addr, sizeof(addr), &server_ss);
3767 cli = get_ipc_connect(addr, &server_ss, user_info);
3769 return cli;
3773 * Return the IP address and workgroup of a master browser on the network, and
3774 * connect to it.
3777 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3778 const struct user_auth_info *user_info,
3779 char **pp_workgroup_out)
3781 struct sockaddr_storage *ip_list;
3782 struct cli_state *cli;
3783 int i, count;
3784 NTSTATUS status;
3786 *pp_workgroup_out = NULL;
3788 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3790 /* Go looking for workgroups by broadcasting on the local network */
3792 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3793 &ip_list, &count);
3794 if (!NT_STATUS_IS_OK(status)) {
3795 DEBUG(99, ("No master browsers responded: %s\n",
3796 nt_errstr(status)));
3797 return NULL;
3800 for (i = 0; i < count; i++) {
3801 char addr[INET6_ADDRSTRLEN];
3802 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3803 DEBUG(99, ("Found master browser %s\n", addr));
3805 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3806 user_info, pp_workgroup_out);
3807 if (cli)
3808 return(cli);
3811 return NULL;