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/>.
24 #include "libsmb/libsmb.h"
25 #include "popt_common.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
29 #include "../libcli/auth/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
41 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
42 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
43 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
44 {PROTOCOL_LANMAN1, "LANMAN1.0"},
45 {PROTOCOL_LANMAN2, "LM1.2X002"},
46 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
47 {PROTOCOL_LANMAN2, "LANMAN2.1"},
48 {PROTOCOL_LANMAN2, "Samba"},
49 {PROTOCOL_NT1, "NT LANMAN 1.0"},
50 {PROTOCOL_NT1, "NT LM 0.12"},
53 #define STAR_SMBSERVER "*SMBSERVER"
55 /********************************************************
56 Utility function to ensure we always return at least
57 a valid char * pointer to an empty string for the
58 cli->server_os, cli->server_type and cli->server_domain
60 *******************************************************/
62 static NTSTATUS smb_bytes_talloc_string(struct cli_state *cli,
69 *destlen = clistr_pull_talloc(cli,
71 SVAL(inbuf, smb_flg2),
77 return NT_STATUS_NO_MEMORY;
81 *dest = talloc_strdup(cli, "");
83 return NT_STATUS_NO_MEMORY;
90 * Set the user session key for a connection
91 * @param cli The cli structure to add it too
92 * @param session_key The session key used. (A copy of this is taken for the cli struct)
96 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
98 cli->user_session_key = data_blob(session_key.data, session_key.length);
101 /****************************************************************************
102 Do an old lanman2 style session setup.
103 ****************************************************************************/
105 struct cli_session_setup_lanman2_state {
106 struct cli_state *cli;
111 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
113 static struct tevent_req *cli_session_setup_lanman2_send(
114 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
115 struct cli_state *cli, const char *user,
116 const char *pass, size_t passlen,
117 const char *workgroup)
119 struct tevent_req *req, *subreq;
120 struct cli_session_setup_lanman2_state *state;
121 DATA_BLOB lm_response = data_blob_null;
126 req = tevent_req_create(mem_ctx, &state,
127 struct cli_session_setup_lanman2_state);
136 * LANMAN servers predate NT status codes and Unicode and
137 * ignore those smb flags so we must disable the corresponding
138 * default capabilities that would otherwise cause the Unicode
139 * and NT Status flags to be set (and even returned by the
143 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
146 * if in share level security then don't send a password now
148 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
153 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
156 * Encrypted mode needed, and non encrypted password
159 lm_response = data_blob(NULL, 24);
160 if (tevent_req_nomem(lm_response.data, req)) {
161 return tevent_req_post(req, ev);
164 if (!SMBencrypt(pass, cli->secblob.data,
165 (uint8_t *)lm_response.data)) {
166 DEBUG(1, ("Password is > 14 chars in length, and is "
167 "therefore incompatible with Lanman "
168 "authentication\n"));
169 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
170 return tevent_req_post(req, ev);
172 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
175 * Encrypted mode needed, and encrypted password
178 lm_response = data_blob(pass, passlen);
179 if (tevent_req_nomem(lm_response.data, req)) {
180 return tevent_req_post(req, ev);
182 } else if (passlen > 0) {
184 size_t converted_size;
186 * Plaintext mode needed, assume plaintext supplied.
188 buf = talloc_array(talloc_tos(), uint8_t, 0);
189 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
191 if (tevent_req_nomem(buf, req)) {
192 return tevent_req_post(req, ev);
194 lm_response = data_blob(pass, passlen);
196 if (tevent_req_nomem(lm_response.data, req)) {
197 return tevent_req_post(req, ev);
201 SCVAL(vwv+0, 0, 0xff);
204 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
207 SIVAL(vwv+5, 0, cli->sesskey);
208 SSVAL(vwv+7, 0, lm_response.length);
210 bytes = talloc_array(state, uint8_t, lm_response.length);
211 if (tevent_req_nomem(bytes, req)) {
212 return tevent_req_post(req, ev);
214 if (lm_response.length != 0) {
215 memcpy(bytes, lm_response.data, lm_response.length);
217 data_blob_free(&lm_response);
219 tmp = talloc_strdup_upper(talloc_tos(), user);
220 if (tevent_req_nomem(tmp, req)) {
221 return tevent_req_post(req, ev);
223 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
227 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
228 if (tevent_req_nomem(tmp, req)) {
229 return tevent_req_post(req, ev);
231 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
233 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
234 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
236 if (tevent_req_nomem(bytes, req)) {
237 return tevent_req_post(req, ev);
240 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
241 talloc_get_size(bytes), bytes);
242 if (tevent_req_nomem(subreq, req)) {
243 return tevent_req_post(req, ev);
245 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
249 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
251 struct tevent_req *req = tevent_req_callback_data(
252 subreq, struct tevent_req);
253 struct cli_session_setup_lanman2_state *state = tevent_req_data(
254 req, struct cli_session_setup_lanman2_state);
255 struct cli_state *cli = state->cli;
266 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
269 if (!NT_STATUS_IS_OK(status)) {
270 tevent_req_nterror(req, status);
277 cli->vuid = SVAL(inbuf, smb_uid);
278 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
280 status = smb_bytes_talloc_string(cli,
287 if (!NT_STATUS_IS_OK(status)) {
288 tevent_req_nterror(req, status);
293 status = smb_bytes_talloc_string(cli,
300 if (!NT_STATUS_IS_OK(status)) {
301 tevent_req_nterror(req, status);
306 status = smb_bytes_talloc_string(cli,
313 if (!NT_STATUS_IS_OK(status)) {
314 tevent_req_nterror(req, status);
319 if (strstr(cli->server_type, "Samba")) {
320 cli->is_samba = True;
322 status = cli_set_username(cli, state->user);
323 if (tevent_req_nterror(req, status)) {
326 tevent_req_done(req);
329 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
331 return tevent_req_simple_recv_ntstatus(req);
334 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
335 const char *pass, size_t passlen,
336 const char *workgroup)
338 TALLOC_CTX *frame = talloc_stackframe();
339 struct event_context *ev;
340 struct tevent_req *req;
341 NTSTATUS status = NT_STATUS_NO_MEMORY;
343 if (cli_has_async_calls(cli)) {
345 * Can't use sync call while an async call is in flight
347 status = NT_STATUS_INVALID_PARAMETER;
350 ev = event_context_init(frame);
354 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
359 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
362 status = cli_session_setup_lanman2_recv(req);
368 /****************************************************************************
369 Work out suitable capabilities to offer the server.
370 ****************************************************************************/
372 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
374 uint32 capabilities = CAP_NT_SMBS;
376 if (!cli->force_dos_errors)
377 capabilities |= CAP_STATUS32;
379 if (cli->use_level_II_oplocks)
380 capabilities |= CAP_LEVEL_II_OPLOCKS;
382 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
386 /****************************************************************************
387 Do a NT1 guest session setup.
388 ****************************************************************************/
390 struct cli_session_setup_guest_state {
391 struct cli_state *cli;
396 static void cli_session_setup_guest_done(struct tevent_req *subreq);
398 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
399 struct event_context *ev,
400 struct cli_state *cli,
401 struct tevent_req **psmbreq)
403 struct tevent_req *req, *subreq;
404 struct cli_session_setup_guest_state *state;
408 req = tevent_req_create(mem_ctx, &state,
409 struct cli_session_setup_guest_state);
416 SCVAL(vwv+0, 0, 0xFF);
419 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
421 SSVAL(vwv+4, 0, cli->pid);
422 SIVAL(vwv+5, 0, cli->sesskey);
427 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
429 bytes = talloc_array(state, uint8_t, 0);
431 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
433 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
435 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
436 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
443 state->bytes.iov_base = (void *)bytes;
444 state->bytes.iov_len = talloc_get_size(bytes);
446 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
448 if (subreq == NULL) {
452 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
457 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
458 struct event_context *ev,
459 struct cli_state *cli)
461 struct tevent_req *req, *subreq;
464 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
469 status = cli_smb_req_send(subreq);
470 if (NT_STATUS_IS_OK(status)) {
471 tevent_req_nterror(req, status);
472 return tevent_req_post(req, ev);
477 static void cli_session_setup_guest_done(struct tevent_req *subreq)
479 struct tevent_req *req = tevent_req_callback_data(
480 subreq, struct tevent_req);
481 struct cli_session_setup_guest_state *state = tevent_req_data(
482 req, struct cli_session_setup_guest_state);
483 struct cli_state *cli = state->cli;
494 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
497 if (!NT_STATUS_IS_OK(status)) {
498 tevent_req_nterror(req, status);
505 cli->vuid = SVAL(inbuf, smb_uid);
506 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
508 status = smb_bytes_talloc_string(cli,
515 if (!NT_STATUS_IS_OK(status)) {
516 tevent_req_nterror(req, status);
521 status = smb_bytes_talloc_string(cli,
528 if (!NT_STATUS_IS_OK(status)) {
529 tevent_req_nterror(req, status);
534 status = smb_bytes_talloc_string(cli,
541 if (!NT_STATUS_IS_OK(status)) {
542 tevent_req_nterror(req, status);
547 if (strstr(cli->server_type, "Samba")) {
548 cli->is_samba = True;
551 status = cli_set_username(cli, "");
552 if (!NT_STATUS_IS_OK(status)) {
553 tevent_req_nterror(req, status);
556 tevent_req_done(req);
559 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
561 return tevent_req_simple_recv_ntstatus(req);
564 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
566 TALLOC_CTX *frame = talloc_stackframe();
567 struct event_context *ev;
568 struct tevent_req *req;
569 NTSTATUS status = NT_STATUS_OK;
571 if (cli_has_async_calls(cli)) {
573 * Can't use sync call while an async call is in flight
575 status = NT_STATUS_INVALID_PARAMETER;
579 ev = event_context_init(frame);
581 status = NT_STATUS_NO_MEMORY;
585 req = cli_session_setup_guest_send(frame, ev, cli);
587 status = NT_STATUS_NO_MEMORY;
591 if (!tevent_req_poll(req, ev)) {
592 status = map_nt_error_from_unix(errno);
596 status = cli_session_setup_guest_recv(req);
602 /****************************************************************************
603 Do a NT1 plaintext session setup.
604 ****************************************************************************/
606 struct cli_session_setup_plain_state {
607 struct cli_state *cli;
612 static void cli_session_setup_plain_done(struct tevent_req *subreq);
614 static struct tevent_req *cli_session_setup_plain_send(
615 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
616 struct cli_state *cli,
617 const char *user, const char *pass, const char *workgroup)
619 struct tevent_req *req, *subreq;
620 struct cli_session_setup_plain_state *state;
626 req = tevent_req_create(mem_ctx, &state,
627 struct cli_session_setup_plain_state);
635 SCVAL(vwv+0, 0, 0xff);
638 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
640 SSVAL(vwv+4, 0, cli->pid);
641 SIVAL(vwv+5, 0, cli->sesskey);
646 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
648 bytes = talloc_array(state, uint8_t, 0);
649 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
651 if (tevent_req_nomem(bytes, req)) {
652 return tevent_req_post(req, ev);
654 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
656 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
657 user, strlen(user)+1, NULL);
658 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
659 workgroup, strlen(workgroup)+1, NULL);
660 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
663 version = talloc_asprintf(talloc_tos(), "Samba %s",
664 samba_version_string());
665 if (tevent_req_nomem(version, req)){
666 return tevent_req_post(req, ev);
668 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
669 version, strlen(version)+1, NULL);
670 TALLOC_FREE(version);
672 if (tevent_req_nomem(bytes, req)) {
673 return tevent_req_post(req, ev);
676 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
677 talloc_get_size(bytes), bytes);
678 if (tevent_req_nomem(subreq, req)) {
679 return tevent_req_post(req, ev);
681 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
685 static void cli_session_setup_plain_done(struct tevent_req *subreq)
687 struct tevent_req *req = tevent_req_callback_data(
688 subreq, struct tevent_req);
689 struct cli_session_setup_plain_state *state = tevent_req_data(
690 req, struct cli_session_setup_plain_state);
691 struct cli_state *cli = state->cli;
702 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
705 if (tevent_req_nterror(req, status)) {
712 cli->vuid = SVAL(inbuf, smb_uid);
713 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
715 status = smb_bytes_talloc_string(cli,
722 if (!NT_STATUS_IS_OK(status)) {
723 tevent_req_nterror(req, status);
728 status = smb_bytes_talloc_string(cli,
735 if (!NT_STATUS_IS_OK(status)) {
736 tevent_req_nterror(req, status);
741 status = smb_bytes_talloc_string(cli,
748 if (!NT_STATUS_IS_OK(status)) {
749 tevent_req_nterror(req, status);
754 status = cli_set_username(cli, state->user);
755 if (tevent_req_nterror(req, status)) {
758 if (strstr(cli->server_type, "Samba")) {
759 cli->is_samba = True;
761 tevent_req_done(req);
764 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
766 return tevent_req_simple_recv_ntstatus(req);
769 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
770 const char *user, const char *pass,
771 const char *workgroup)
773 TALLOC_CTX *frame = talloc_stackframe();
774 struct event_context *ev;
775 struct tevent_req *req;
776 NTSTATUS status = NT_STATUS_NO_MEMORY;
778 if (cli_has_async_calls(cli)) {
780 * Can't use sync call while an async call is in flight
782 status = NT_STATUS_INVALID_PARAMETER;
785 ev = event_context_init(frame);
789 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
794 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
797 status = cli_session_setup_plain_recv(req);
803 /****************************************************************************
804 do a NT1 NTLM/LM encrypted session setup - for when extended security
806 @param cli client state to create do session setup on
808 @param pass *either* cleartext password (passlen !=24) or LM response.
809 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
810 @param workgroup The user's domain.
811 ****************************************************************************/
813 struct cli_session_setup_nt1_state {
814 struct cli_state *cli;
817 DATA_BLOB session_key;
821 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
823 static struct tevent_req *cli_session_setup_nt1_send(
824 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
825 struct cli_state *cli, const char *user,
826 const char *pass, size_t passlen,
827 const char *ntpass, size_t ntpasslen,
828 const char *workgroup)
830 struct tevent_req *req, *subreq;
831 struct cli_session_setup_nt1_state *state;
832 DATA_BLOB lm_response = data_blob_null;
833 DATA_BLOB nt_response = data_blob_null;
834 DATA_BLOB session_key = data_blob_null;
837 char *workgroup_upper;
839 req = tevent_req_create(mem_ctx, &state,
840 struct cli_session_setup_nt1_state);
849 /* do nothing - guest login */
850 } else if (passlen != 24) {
851 if (lp_client_ntlmv2_auth()) {
852 DATA_BLOB server_chal;
853 DATA_BLOB names_blob;
855 server_chal = data_blob(cli->secblob.data,
856 MIN(cli->secblob.length, 8));
857 if (tevent_req_nomem(server_chal.data, req)) {
858 return tevent_req_post(req, ev);
862 * note that the 'workgroup' here is a best
863 * guess - we don't know the server's domain
864 * at this point. The 'server name' is also
867 names_blob = NTLMv2_generate_names_blob(
868 NULL, cli->called.name, workgroup);
870 if (tevent_req_nomem(names_blob.data, req)) {
871 return tevent_req_post(req, ev);
874 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
875 &server_chal, &names_blob,
876 &lm_response, &nt_response,
877 NULL, &session_key)) {
878 data_blob_free(&names_blob);
879 data_blob_free(&server_chal);
881 req, NT_STATUS_ACCESS_DENIED);
882 return tevent_req_post(req, ev);
884 data_blob_free(&names_blob);
885 data_blob_free(&server_chal);
889 E_md4hash(pass, nt_hash);
892 nt_response = data_blob_null;
894 nt_response = data_blob(NULL, 24);
895 if (tevent_req_nomem(nt_response.data, req)) {
896 return tevent_req_post(req, ev);
899 SMBNTencrypt(pass, cli->secblob.data,
902 /* non encrypted password supplied. Ignore ntpass. */
903 if (lp_client_lanman_auth()) {
905 lm_response = data_blob(NULL, 24);
906 if (tevent_req_nomem(lm_response.data, req)) {
907 return tevent_req_post(req, ev);
910 if (!SMBencrypt(pass,cli->secblob.data,
913 * Oops, the LM response is
914 * invalid, just put the NT
915 * response there instead
917 data_blob_free(&lm_response);
918 lm_response = data_blob(
924 * LM disabled, place NT# in LM field
927 lm_response = data_blob(
928 nt_response.data, nt_response.length);
931 if (tevent_req_nomem(lm_response.data, req)) {
932 return tevent_req_post(req, ev);
935 session_key = data_blob(NULL, 16);
936 if (tevent_req_nomem(session_key.data, req)) {
937 return tevent_req_post(req, ev);
940 E_deshash(pass, session_key.data);
941 memset(&session_key.data[8], '\0', 8);
943 SMBsesskeygen_ntv1(nt_hash, session_key.data);
946 cli_temp_set_signing(cli);
948 /* pre-encrypted password supplied. Only used for
949 security=server, can't do
950 signing because we don't have original key */
952 lm_response = data_blob(pass, passlen);
953 if (tevent_req_nomem(lm_response.data, req)) {
954 return tevent_req_post(req, ev);
957 nt_response = data_blob(ntpass, ntpasslen);
958 if (tevent_req_nomem(nt_response.data, req)) {
959 return tevent_req_post(req, ev);
964 state->response = data_blob_talloc(
965 state, lm_response.data, lm_response.length);
967 state->response = data_blob_talloc(
968 state, nt_response.data, nt_response.length);
970 if (tevent_req_nomem(state->response.data, req)) {
971 return tevent_req_post(req, ev);
974 if (session_key.data) {
975 state->session_key = data_blob_talloc(
976 state, session_key.data, session_key.length);
977 if (tevent_req_nomem(state->session_key.data, req)) {
978 return tevent_req_post(req, ev);
981 data_blob_free(&session_key);
983 SCVAL(vwv+0, 0, 0xff);
986 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
988 SSVAL(vwv+4, 0, cli->pid);
989 SIVAL(vwv+5, 0, cli->sesskey);
990 SSVAL(vwv+7, 0, lm_response.length);
991 SSVAL(vwv+8, 0, nt_response.length);
994 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
996 bytes = talloc_array(state, uint8_t,
997 lm_response.length + nt_response.length);
998 if (tevent_req_nomem(bytes, req)) {
999 return tevent_req_post(req, ev);
1001 if (lm_response.length != 0) {
1002 memcpy(bytes, lm_response.data, lm_response.length);
1004 if (nt_response.length != 0) {
1005 memcpy(bytes + lm_response.length,
1006 nt_response.data, nt_response.length);
1008 data_blob_free(&lm_response);
1009 data_blob_free(&nt_response);
1011 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1012 user, strlen(user)+1, NULL);
1015 * Upper case here might help some NTLMv2 implementations
1017 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1018 if (tevent_req_nomem(workgroup_upper, req)) {
1019 return tevent_req_post(req, ev);
1021 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1022 workgroup_upper, strlen(workgroup_upper)+1,
1024 TALLOC_FREE(workgroup_upper);
1026 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1027 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1028 if (tevent_req_nomem(bytes, req)) {
1029 return tevent_req_post(req, ev);
1032 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1033 talloc_get_size(bytes), bytes);
1034 if (tevent_req_nomem(subreq, req)) {
1035 return tevent_req_post(req, ev);
1037 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1041 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1043 struct tevent_req *req = tevent_req_callback_data(
1044 subreq, struct tevent_req);
1045 struct cli_session_setup_nt1_state *state = tevent_req_data(
1046 req, struct cli_session_setup_nt1_state);
1047 struct cli_state *cli = state->cli;
1058 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1059 &num_bytes, &bytes);
1060 TALLOC_FREE(subreq);
1061 if (!NT_STATUS_IS_OK(status)) {
1062 tevent_req_nterror(req, status);
1069 cli->vuid = SVAL(inbuf, smb_uid);
1070 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1072 status = smb_bytes_talloc_string(cli,
1078 if (!NT_STATUS_IS_OK(status)) {
1079 tevent_req_nterror(req, status);
1084 status = smb_bytes_talloc_string(cli,
1090 if (!NT_STATUS_IS_OK(status)) {
1091 tevent_req_nterror(req, status);
1096 status = smb_bytes_talloc_string(cli,
1098 &cli->server_domain,
1102 if (!NT_STATUS_IS_OK(status)) {
1103 tevent_req_nterror(req, status);
1108 if (strstr(cli->server_type, "Samba")) {
1109 cli->is_samba = True;
1112 status = cli_set_username(cli, state->user);
1113 if (tevent_req_nterror(req, status)) {
1116 if (cli_simple_set_signing(cli, state->session_key, state->response)
1117 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1118 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1121 if (state->session_key.data) {
1122 /* Have plaintext orginal */
1123 cli_set_session_key(cli, state->session_key);
1125 tevent_req_done(req);
1128 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1130 return tevent_req_simple_recv_ntstatus(req);
1133 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1134 const char *pass, size_t passlen,
1135 const char *ntpass, size_t ntpasslen,
1136 const char *workgroup)
1138 TALLOC_CTX *frame = talloc_stackframe();
1139 struct event_context *ev;
1140 struct tevent_req *req;
1141 NTSTATUS status = NT_STATUS_NO_MEMORY;
1143 if (cli_has_async_calls(cli)) {
1145 * Can't use sync call while an async call is in flight
1147 status = NT_STATUS_INVALID_PARAMETER;
1150 ev = event_context_init(frame);
1154 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1155 ntpass, ntpasslen, workgroup);
1159 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1162 status = cli_session_setup_nt1_recv(req);
1168 /* The following is calculated from :
1170 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1171 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1175 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1177 struct cli_sesssetup_blob_state {
1178 struct tevent_context *ev;
1179 struct cli_state *cli;
1181 uint16_t max_blob_size;
1190 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1191 struct tevent_req **psubreq);
1192 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1194 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1195 struct tevent_context *ev,
1196 struct cli_state *cli,
1199 struct tevent_req *req, *subreq;
1200 struct cli_sesssetup_blob_state *state;
1202 req = tevent_req_create(mem_ctx, &state,
1203 struct cli_sesssetup_blob_state);
1211 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
1212 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1213 "(was %u, need minimum %u)\n",
1214 (unsigned int)cli->max_xmit,
1215 BASE_SESSSETUP_BLOB_PACKET_SIZE));
1216 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1217 return tevent_req_post(req, ev);
1219 state->max_blob_size =
1220 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
1222 if (!cli_sesssetup_blob_next(state, &subreq)) {
1223 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1224 return tevent_req_post(req, ev);
1226 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1230 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1231 struct tevent_req **psubreq)
1233 struct tevent_req *subreq;
1236 SCVAL(state->vwv+0, 0, 0xFF);
1237 SCVAL(state->vwv+0, 1, 0);
1238 SSVAL(state->vwv+1, 0, 0);
1239 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1240 SSVAL(state->vwv+3, 0, 2);
1241 SSVAL(state->vwv+4, 0, 1);
1242 SIVAL(state->vwv+5, 0, 0);
1244 thistime = MIN(state->blob.length, state->max_blob_size);
1245 SSVAL(state->vwv+7, 0, thistime);
1247 SSVAL(state->vwv+8, 0, 0);
1248 SSVAL(state->vwv+9, 0, 0);
1249 SIVAL(state->vwv+10, 0,
1250 cli_session_setup_capabilities(state->cli)
1251 | CAP_EXTENDED_SECURITY);
1253 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1255 if (state->buf == NULL) {
1258 state->blob.data += thistime;
1259 state->blob.length -= thistime;
1261 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1263 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1265 if (state->buf == NULL) {
1268 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1270 talloc_get_size(state->buf), state->buf);
1271 if (subreq == NULL) {
1278 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1280 struct tevent_req *req = tevent_req_callback_data(
1281 subreq, struct tevent_req);
1282 struct cli_sesssetup_blob_state *state = tevent_req_data(
1283 req, struct cli_sesssetup_blob_state);
1284 struct cli_state *cli = state->cli;
1291 uint16_t blob_length;
1295 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
1296 &num_bytes, &bytes);
1297 TALLOC_FREE(subreq);
1298 if (!NT_STATUS_IS_OK(status)
1299 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1300 tevent_req_nterror(req, status);
1304 state->status = status;
1305 TALLOC_FREE(state->buf);
1307 state->inbuf = (char *)inbuf;
1308 cli->vuid = SVAL(state->inbuf, smb_uid);
1309 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1311 blob_length = SVAL(vwv+3, 0);
1312 if (blob_length > num_bytes) {
1313 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1316 state->ret_blob = data_blob_const(bytes, blob_length);
1318 p = bytes + blob_length;
1320 status = smb_bytes_talloc_string(cli,
1327 if (!NT_STATUS_IS_OK(status)) {
1328 tevent_req_nterror(req, status);
1333 status = smb_bytes_talloc_string(cli,
1340 if (!NT_STATUS_IS_OK(status)) {
1341 tevent_req_nterror(req, status);
1346 status = smb_bytes_talloc_string(cli,
1348 &cli->server_domain,
1353 if (!NT_STATUS_IS_OK(status)) {
1354 tevent_req_nterror(req, status);
1359 if (strstr(cli->server_type, "Samba")) {
1360 cli->is_samba = True;
1363 if (state->blob.length != 0) {
1367 if (!cli_sesssetup_blob_next(state, &subreq)) {
1368 tevent_req_oom(req);
1371 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1374 tevent_req_done(req);
1377 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1378 TALLOC_CTX *mem_ctx,
1382 struct cli_sesssetup_blob_state *state = tevent_req_data(
1383 req, struct cli_sesssetup_blob_state);
1387 if (tevent_req_is_nterror(req, &status)) {
1388 state->cli->vuid = 0;
1392 inbuf = talloc_move(mem_ctx, &state->inbuf);
1393 if (pblob != NULL) {
1394 *pblob = state->ret_blob;
1396 if (pinbuf != NULL) {
1399 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1400 return state->status;
1405 /****************************************************************************
1406 Use in-memory credentials cache
1407 ****************************************************************************/
1409 static void use_in_memory_ccache(void) {
1410 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1413 /****************************************************************************
1414 Do a spnego/kerberos encrypted session setup.
1415 ****************************************************************************/
1417 struct cli_session_setup_kerberos_state {
1418 struct cli_state *cli;
1419 DATA_BLOB negTokenTarg;
1420 DATA_BLOB session_key_krb5;
1421 ADS_STATUS ads_status;
1424 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1426 static struct tevent_req *cli_session_setup_kerberos_send(
1427 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1428 const char *principal)
1430 struct tevent_req *req, *subreq;
1431 struct cli_session_setup_kerberos_state *state;
1434 DEBUG(2,("Doing kerberos session setup\n"));
1436 req = tevent_req_create(mem_ctx, &state,
1437 struct cli_session_setup_kerberos_state);
1442 state->ads_status = ADS_SUCCESS;
1444 cli_temp_set_signing(cli);
1447 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1448 * we have to acquire a ticket. To be fixed later :-)
1450 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1451 &state->session_key_krb5, 0, NULL);
1453 DEBUG(1, ("cli_session_setup_kerberos: "
1454 "spnego_gen_krb5_negTokenInit failed: %s\n",
1455 error_message(rc)));
1456 state->ads_status = ADS_ERROR_KRB5(rc);
1457 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1458 return tevent_req_post(req, ev);
1462 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1463 state->negTokenTarg.length);
1466 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1467 if (tevent_req_nomem(subreq, req)) {
1468 return tevent_req_post(req, ev);
1470 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1474 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1476 struct tevent_req *req = tevent_req_callback_data(
1477 subreq, struct tevent_req);
1478 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1479 req, struct cli_session_setup_kerberos_state);
1483 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1484 if (!NT_STATUS_IS_OK(status)) {
1485 TALLOC_FREE(subreq);
1486 tevent_req_nterror(req, status);
1490 cli_set_session_key(state->cli, state->session_key_krb5);
1492 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1494 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1495 TALLOC_FREE(subreq);
1496 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1499 TALLOC_FREE(subreq);
1500 tevent_req_done(req);
1503 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1505 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1506 req, struct cli_session_setup_kerberos_state);
1509 if (tevent_req_is_nterror(req, &status)) {
1510 return ADS_ERROR_NT(status);
1512 return state->ads_status;
1515 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1516 const char *principal)
1518 struct tevent_context *ev;
1519 struct tevent_req *req;
1520 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1522 if (cli_has_async_calls(cli)) {
1523 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1525 ev = tevent_context_init(talloc_tos());
1529 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1533 if (!tevent_req_poll(req, ev)) {
1534 status = ADS_ERROR_SYSTEM(errno);
1537 status = cli_session_setup_kerberos_recv(req);
1542 #endif /* HAVE_KRB5 */
1544 /****************************************************************************
1545 Do a spnego/NTLMSSP encrypted session setup.
1546 ****************************************************************************/
1548 struct cli_session_setup_ntlmssp_state {
1549 struct tevent_context *ev;
1550 struct cli_state *cli;
1551 struct ntlmssp_state *ntlmssp_state;
1556 static int cli_session_setup_ntlmssp_state_destructor(
1557 struct cli_session_setup_ntlmssp_state *state)
1559 if (state->ntlmssp_state != NULL) {
1560 TALLOC_FREE(state->ntlmssp_state);
1565 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1567 static struct tevent_req *cli_session_setup_ntlmssp_send(
1568 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1569 const char *user, const char *pass, const char *domain)
1571 struct tevent_req *req, *subreq;
1572 struct cli_session_setup_ntlmssp_state *state;
1575 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1577 req = tevent_req_create(mem_ctx, &state,
1578 struct cli_session_setup_ntlmssp_state);
1586 state->ntlmssp_state = NULL;
1587 talloc_set_destructor(
1588 state, cli_session_setup_ntlmssp_state_destructor);
1590 cli_temp_set_signing(cli);
1592 status = ntlmssp_client_start(state,
1595 lp_client_ntlmv2_auth(),
1596 &state->ntlmssp_state);
1597 if (!NT_STATUS_IS_OK(status)) {
1600 ntlmssp_want_feature(state->ntlmssp_state,
1601 NTLMSSP_FEATURE_SESSION_KEY);
1602 if (cli->use_ccache) {
1603 ntlmssp_want_feature(state->ntlmssp_state,
1604 NTLMSSP_FEATURE_CCACHE);
1606 status = ntlmssp_set_username(state->ntlmssp_state, user);
1607 if (!NT_STATUS_IS_OK(status)) {
1610 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1611 if (!NT_STATUS_IS_OK(status)) {
1614 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1615 if (!NT_STATUS_IS_OK(status)) {
1618 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1620 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1624 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1625 data_blob_free(&blob_out);
1627 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1628 if (tevent_req_nomem(subreq, req)) {
1629 return tevent_req_post(req, ev);
1631 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1634 tevent_req_nterror(req, status);
1635 return tevent_req_post(req, ev);
1638 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1640 struct tevent_req *req = tevent_req_callback_data(
1641 subreq, struct tevent_req);
1642 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1643 req, struct cli_session_setup_ntlmssp_state);
1644 DATA_BLOB blob_in, msg_in, blob_out;
1649 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1651 TALLOC_FREE(subreq);
1652 data_blob_free(&state->blob_out);
1654 if (NT_STATUS_IS_OK(status)) {
1655 if (state->cli->server_domain[0] == '\0') {
1656 TALLOC_FREE(state->cli->server_domain);
1657 state->cli->server_domain = talloc_strdup(state->cli,
1658 state->ntlmssp_state->server.netbios_domain);
1659 if (state->cli->server_domain == NULL) {
1660 TALLOC_FREE(subreq);
1661 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1665 cli_set_session_key(
1666 state->cli, state->ntlmssp_state->session_key);
1668 if (cli_simple_set_signing(
1669 state->cli, state->ntlmssp_state->session_key,
1671 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1672 TALLOC_FREE(subreq);
1673 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1676 TALLOC_FREE(subreq);
1677 TALLOC_FREE(state->ntlmssp_state);
1678 tevent_req_done(req);
1681 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1682 tevent_req_nterror(req, status);
1686 if (blob_in.length == 0) {
1687 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1691 if ((state->turn == 1)
1692 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1693 DATA_BLOB tmp_blob = data_blob_null;
1694 /* the server might give us back two challenges */
1695 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1697 data_blob_free(&tmp_blob);
1699 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1700 OID_NTLMSSP, &msg_in);
1705 DEBUG(3,("Failed to parse auth response\n"));
1706 if (NT_STATUS_IS_OK(status)
1707 || NT_STATUS_EQUAL(status,
1708 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1710 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1715 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1717 if (!NT_STATUS_IS_OK(status)
1718 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1719 TALLOC_FREE(subreq);
1720 TALLOC_FREE(state->ntlmssp_state);
1721 tevent_req_nterror(req, status);
1725 state->blob_out = spnego_gen_auth(state, blob_out);
1726 TALLOC_FREE(subreq);
1727 if (tevent_req_nomem(state->blob_out.data, req)) {
1731 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1733 if (tevent_req_nomem(subreq, req)) {
1736 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1739 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1741 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1742 req, struct cli_session_setup_ntlmssp_state);
1745 if (tevent_req_is_nterror(req, &status)) {
1746 state->cli->vuid = 0;
1749 return NT_STATUS_OK;
1752 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1757 struct tevent_context *ev;
1758 struct tevent_req *req;
1759 NTSTATUS status = NT_STATUS_NO_MEMORY;
1761 if (cli_has_async_calls(cli)) {
1762 return NT_STATUS_INVALID_PARAMETER;
1764 ev = tevent_context_init(talloc_tos());
1768 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1772 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1775 status = cli_session_setup_ntlmssp_recv(req);
1781 /****************************************************************************
1782 Do a spnego encrypted session setup.
1784 user_domain: The shortname of the domain the user/machine is a member of.
1785 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1786 ****************************************************************************/
1788 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1789 const char *pass, const char *user_domain,
1790 const char * dest_realm)
1792 char *principal = NULL;
1793 char *OIDs[ASN1_MAX_OIDS];
1796 const char *p = NULL;
1797 char *account = NULL;
1800 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1802 /* the server might not even do spnego */
1803 if (cli->secblob.length <= 16) {
1804 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1809 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1812 /* there is 16 bytes of GUID before the real spnego packet starts */
1813 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1815 /* The server sent us the first part of the SPNEGO exchange in the
1816 * negprot reply. It is WRONG to depend on the principal sent in the
1817 * negprot reply, but right now we do it. If we don't receive one,
1818 * we try to best guess, then fall back to NTLM. */
1819 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1821 data_blob_free(&blob);
1822 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1824 data_blob_free(&blob);
1826 /* make sure the server understands kerberos */
1827 for (i=0;OIDs[i];i++) {
1829 DEBUG(3,("got OID=%s\n", OIDs[i]));
1831 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1832 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1833 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1834 cli->got_kerberos_mechanism = True;
1836 talloc_free(OIDs[i]);
1839 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1841 status = cli_set_username(cli, user);
1842 if (!NT_STATUS_IS_OK(status)) {
1843 TALLOC_FREE(principal);
1844 return ADS_ERROR_NT(status);
1848 /* If password is set we reauthenticate to kerberos server
1849 * and do not store results */
1851 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1854 if (pass && *pass) {
1857 use_in_memory_ccache();
1858 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1861 TALLOC_FREE(principal);
1862 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1863 if (cli->fallback_after_kerberos)
1865 return ADS_ERROR_KRB5(ret);
1869 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1871 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1872 TALLOC_FREE(principal);
1875 if (principal == NULL &&
1876 !is_ipaddress(cli->desthost) &&
1877 !strequal(STAR_SMBSERVER,
1881 DEBUG(3,("cli_session_setup_spnego: using target "
1882 "hostname not SPNEGO principal\n"));
1884 host = strchr_m(cli->desthost, '.');
1886 realm = SMB_STRDUP(dest_realm);
1888 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1894 realm = kerberos_get_realm_from_hostname(cli->desthost);
1896 /* NetBIOS name - use our realm. */
1897 realm = kerberos_get_default_realm_from_ccache();
1901 if (realm == NULL || *realm == '\0') {
1902 realm = SMB_STRDUP(lp_realm());
1904 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1907 DEBUG(3,("cli_session_setup_spnego: cannot "
1908 "get realm from dest_realm %s, "
1909 "desthost %s. Using default "
1910 "smb.conf realm %s\n",
1911 dest_realm ? dest_realm : "<null>",
1916 principal = talloc_asprintf(talloc_tos(),
1922 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1924 DEBUG(3,("cli_session_setup_spnego: guessed "
1925 "server principal=%s\n",
1926 principal ? principal : "<null>"));
1932 rc = cli_session_setup_kerberos(cli, principal);
1933 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1934 TALLOC_FREE(principal);
1941 TALLOC_FREE(principal);
1945 account = talloc_strdup(talloc_tos(), user);
1947 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1950 /* when falling back to ntlmssp while authenticating with a machine
1951 * account strip off the realm - gd */
1953 if ((p = strchr_m(user, '@')) != NULL) {
1954 account[PTR_DIFF(p,user)] = '\0';
1957 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1960 /****************************************************************************
1961 Send a session setup. The username and workgroup is in UNIX character
1962 format and must be converted to DOS codepage format before sending. If the
1963 password is in plaintext, the same should be done.
1964 ****************************************************************************/
1966 NTSTATUS cli_session_setup(struct cli_state *cli,
1968 const char *pass, int passlen,
1969 const char *ntpass, int ntpasslen,
1970 const char *workgroup)
1976 user2 = talloc_strdup(talloc_tos(), user);
1978 user2 = talloc_strdup(talloc_tos(), "");
1980 if (user2 == NULL) {
1981 return NT_STATUS_NO_MEMORY;
1988 /* allow for workgroups as part of the username */
1989 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1990 (p=strchr_m(user2,*lp_winbind_separator()))) {
1997 if (cli->protocol < PROTOCOL_LANMAN1) {
1998 return NT_STATUS_OK;
2001 /* now work out what sort of session setup we are going to
2002 do. I have split this into separate functions to make the
2003 flow a bit easier to understand (tridge) */
2005 /* if its an older server then we have to use the older request format */
2007 if (cli->protocol < PROTOCOL_NT1) {
2008 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2009 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2010 " or 'client ntlmv2 auth = yes'\n"));
2011 return NT_STATUS_ACCESS_DENIED;
2014 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2015 !lp_client_plaintext_auth() && (*pass)) {
2016 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2017 " or 'client ntlmv2 auth = yes'\n"));
2018 return NT_STATUS_ACCESS_DENIED;
2021 return cli_session_setup_lanman2(cli, user, pass, passlen,
2025 /* if no user is supplied then we have to do an anonymous connection.
2026 passwords are ignored */
2028 if (!user || !*user)
2029 return cli_session_setup_guest(cli);
2031 /* if the server is share level then send a plaintext null
2032 password at this point. The password is sent in the tree
2035 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2036 return cli_session_setup_plain(cli, user, "", workgroup);
2038 /* if the server doesn't support encryption then we have to use
2039 plaintext. The second password is ignored */
2041 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2042 if (!lp_client_plaintext_auth() && (*pass)) {
2043 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2044 " or 'client ntlmv2 auth = yes'\n"));
2045 return NT_STATUS_ACCESS_DENIED;
2047 return cli_session_setup_plain(cli, user, pass, workgroup);
2050 /* if the server supports extended security then use SPNEGO */
2052 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
2053 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2055 if (!ADS_ERR_OK(status)) {
2056 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2057 return ads_ntstatus(status);
2062 /* otherwise do a NT1 style session setup */
2063 status = cli_session_setup_nt1(cli, user, pass, passlen,
2064 ntpass, ntpasslen, workgroup);
2065 if (!NT_STATUS_IS_OK(status)) {
2066 DEBUG(3,("cli_session_setup: NT1 session setup "
2067 "failed: %s\n", nt_errstr(status)));
2072 if (strstr(cli->server_type, "Samba")) {
2073 cli->is_samba = True;
2076 return NT_STATUS_OK;
2079 /****************************************************************************
2081 *****************************************************************************/
2083 struct cli_ulogoff_state {
2084 struct cli_state *cli;
2088 static void cli_ulogoff_done(struct tevent_req *subreq);
2090 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2091 struct tevent_context *ev,
2092 struct cli_state *cli)
2094 struct tevent_req *req, *subreq;
2095 struct cli_ulogoff_state *state;
2097 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2103 SCVAL(state->vwv+0, 0, 0xFF);
2104 SCVAL(state->vwv+1, 0, 0);
2105 SSVAL(state->vwv+2, 0, 0);
2107 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2109 if (tevent_req_nomem(subreq, req)) {
2110 return tevent_req_post(req, ev);
2112 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2116 static void cli_ulogoff_done(struct tevent_req *subreq)
2118 struct tevent_req *req = tevent_req_callback_data(
2119 subreq, struct tevent_req);
2120 struct cli_ulogoff_state *state = tevent_req_data(
2121 req, struct cli_ulogoff_state);
2124 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2125 if (!NT_STATUS_IS_OK(status)) {
2126 tevent_req_nterror(req, status);
2129 state->cli->vuid = -1;
2130 tevent_req_done(req);
2133 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2135 return tevent_req_simple_recv_ntstatus(req);
2138 NTSTATUS cli_ulogoff(struct cli_state *cli)
2140 struct tevent_context *ev;
2141 struct tevent_req *req;
2142 NTSTATUS status = NT_STATUS_NO_MEMORY;
2144 if (cli_has_async_calls(cli)) {
2145 return NT_STATUS_INVALID_PARAMETER;
2147 ev = tevent_context_init(talloc_tos());
2151 req = cli_ulogoff_send(ev, ev, cli);
2155 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2158 status = cli_ulogoff_recv(req);
2164 /****************************************************************************
2166 ****************************************************************************/
2168 struct cli_tcon_andx_state {
2169 struct cli_state *cli;
2174 static void cli_tcon_andx_done(struct tevent_req *subreq);
2176 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2177 struct event_context *ev,
2178 struct cli_state *cli,
2179 const char *share, const char *dev,
2180 const char *pass, int passlen,
2181 struct tevent_req **psmbreq)
2183 struct tevent_req *req, *subreq;
2184 struct cli_tcon_andx_state *state;
2192 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2199 cli->share = talloc_strdup(cli, share);
2204 /* in user level security don't send a password now */
2205 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2208 } else if (pass == NULL) {
2209 DEBUG(1, ("Server not using user level security and no "
2210 "password supplied.\n"));
2214 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2215 *pass && passlen != 24) {
2216 if (!lp_client_lanman_auth()) {
2217 DEBUG(1, ("Server requested LANMAN password "
2218 "(share-level security) but "
2219 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2224 * Non-encrypted passwords - convert to DOS codepage before
2227 SMBencrypt(pass, cli->secblob.data, p24);
2229 pass = (const char *)p24;
2231 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2232 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2236 if (!lp_client_plaintext_auth() && (*pass)) {
2237 DEBUG(1, ("Server requested plaintext "
2239 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2244 * Non-encrypted passwords - convert to DOS codepage
2247 tmp_pass = talloc_array(talloc_tos(), char, 128);
2248 if (tmp_pass == NULL) {
2249 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2250 return tevent_req_post(req, ev);
2252 passlen = clistr_push(cli,
2255 talloc_get_size(tmp_pass),
2257 if (passlen == -1) {
2258 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2259 return tevent_req_post(req, ev);
2265 SCVAL(vwv+0, 0, 0xFF);
2268 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2269 SSVAL(vwv+3, 0, passlen);
2271 if (passlen && pass) {
2272 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2274 bytes = talloc_array(state, uint8_t, 0);
2280 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2281 cli->desthost, share);
2286 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2291 * Add the devicetype
2293 tmp = talloc_strdup_upper(talloc_tos(), dev);
2298 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2301 if (bytes == NULL) {
2306 state->bytes.iov_base = (void *)bytes;
2307 state->bytes.iov_len = talloc_get_size(bytes);
2309 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2311 if (subreq == NULL) {
2315 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2320 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2321 return tevent_req_post(req, ev);
2324 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2325 struct event_context *ev,
2326 struct cli_state *cli,
2327 const char *share, const char *dev,
2328 const char *pass, int passlen)
2330 struct tevent_req *req, *subreq;
2333 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2338 if (subreq == NULL) {
2341 status = cli_smb_req_send(subreq);
2342 if (!NT_STATUS_IS_OK(status)) {
2343 tevent_req_nterror(req, status);
2344 return tevent_req_post(req, ev);
2349 static void cli_tcon_andx_done(struct tevent_req *subreq)
2351 struct tevent_req *req = tevent_req_callback_data(
2352 subreq, struct tevent_req);
2353 struct cli_tcon_andx_state *state = tevent_req_data(
2354 req, struct cli_tcon_andx_state);
2355 struct cli_state *cli = state->cli;
2364 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2365 &num_bytes, &bytes);
2366 TALLOC_FREE(subreq);
2367 if (!NT_STATUS_IS_OK(status)) {
2368 tevent_req_nterror(req, status);
2375 if (clistr_pull_talloc(cli,
2377 SVAL(inbuf, smb_flg2),
2381 STR_TERMINATE|STR_ASCII) == -1) {
2382 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2386 cli->dev = talloc_strdup(cli, "");
2387 if (cli->dev == NULL) {
2388 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2393 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
2394 /* almost certainly win95 - enable bug fixes */
2399 * Make sure that we have the optional support 16-bit field. WCT > 2.
2400 * Avoids issues when connecting to Win9x boxes sharing files
2403 cli->dfsroot = false;
2405 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
2406 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2409 cli->cnum = SVAL(inbuf,smb_tid);
2410 tevent_req_done(req);
2413 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2415 return tevent_req_simple_recv_ntstatus(req);
2418 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2419 const char *dev, const char *pass, int passlen)
2421 TALLOC_CTX *frame = talloc_stackframe();
2422 struct event_context *ev;
2423 struct tevent_req *req;
2424 NTSTATUS status = NT_STATUS_OK;
2426 if (cli_has_async_calls(cli)) {
2428 * Can't use sync call while an async call is in flight
2430 status = NT_STATUS_INVALID_PARAMETER;
2434 ev = event_context_init(frame);
2436 status = NT_STATUS_NO_MEMORY;
2440 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2442 status = NT_STATUS_NO_MEMORY;
2446 if (!tevent_req_poll(req, ev)) {
2447 status = map_nt_error_from_unix(errno);
2451 status = cli_tcon_andx_recv(req);
2457 /****************************************************************************
2458 Send a tree disconnect.
2459 ****************************************************************************/
2461 struct cli_tdis_state {
2462 struct cli_state *cli;
2465 static void cli_tdis_done(struct tevent_req *subreq);
2467 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2468 struct tevent_context *ev,
2469 struct cli_state *cli)
2471 struct tevent_req *req, *subreq;
2472 struct cli_tdis_state *state;
2474 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2480 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2481 if (tevent_req_nomem(subreq, req)) {
2482 return tevent_req_post(req, ev);
2484 tevent_req_set_callback(subreq, cli_tdis_done, req);
2488 static void cli_tdis_done(struct tevent_req *subreq)
2490 struct tevent_req *req = tevent_req_callback_data(
2491 subreq, struct tevent_req);
2492 struct cli_tdis_state *state = tevent_req_data(
2493 req, struct cli_tdis_state);
2496 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2497 TALLOC_FREE(subreq);
2498 if (!NT_STATUS_IS_OK(status)) {
2499 tevent_req_nterror(req, status);
2502 state->cli->cnum = -1;
2503 tevent_req_done(req);
2506 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2508 return tevent_req_simple_recv_ntstatus(req);
2511 NTSTATUS cli_tdis(struct cli_state *cli)
2513 struct tevent_context *ev;
2514 struct tevent_req *req;
2515 NTSTATUS status = NT_STATUS_NO_MEMORY;
2517 if (cli_has_async_calls(cli)) {
2518 return NT_STATUS_INVALID_PARAMETER;
2520 ev = tevent_context_init(talloc_tos());
2524 req = cli_tdis_send(ev, ev, cli);
2528 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2531 status = cli_tdis_recv(req);
2537 /****************************************************************************
2538 Send a negprot command.
2539 ****************************************************************************/
2541 struct cli_negprot_state {
2542 struct cli_state *cli;
2545 static void cli_negprot_done(struct tevent_req *subreq);
2547 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2548 struct event_context *ev,
2549 struct cli_state *cli)
2551 struct tevent_req *req, *subreq;
2552 struct cli_negprot_state *state;
2553 uint8_t *bytes = NULL;
2557 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2563 if (cli->protocol < PROTOCOL_NT1)
2564 cli->use_spnego = False;
2566 /* setup the protocol strings */
2567 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2569 if (prots[numprots].prot > cli->protocol) {
2572 bytes = (uint8_t *)talloc_append_blob(
2573 state, bytes, data_blob_const(&c, sizeof(c)));
2574 if (tevent_req_nomem(bytes, req)) {
2575 return tevent_req_post(req, ev);
2577 bytes = smb_bytes_push_str(bytes, false,
2578 prots[numprots].name,
2579 strlen(prots[numprots].name)+1,
2581 if (tevent_req_nomem(bytes, req)) {
2582 return tevent_req_post(req, ev);
2589 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2590 talloc_get_size(bytes), bytes);
2593 if (tevent_req_nomem(subreq, req)) {
2594 return tevent_req_post(req, ev);
2596 tevent_req_set_callback(subreq, cli_negprot_done, req);
2600 static void cli_negprot_done(struct tevent_req *subreq)
2602 struct tevent_req *req = tevent_req_callback_data(
2603 subreq, struct tevent_req);
2604 struct cli_negprot_state *state = tevent_req_data(
2605 req, struct cli_negprot_state);
2606 struct cli_state *cli = state->cli;
2615 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2616 &num_bytes, &bytes);
2617 TALLOC_FREE(subreq);
2618 if (!NT_STATUS_IS_OK(status)) {
2619 tevent_req_nterror(req, status);
2623 protnum = SVAL(vwv, 0);
2625 if ((protnum >= ARRAY_SIZE(prots))
2626 || (prots[protnum].prot > cli->protocol)) {
2627 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2631 cli->protocol = prots[protnum].prot;
2633 if ((cli->protocol < PROTOCOL_NT1) &&
2634 client_is_signing_mandatory(cli)) {
2635 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2636 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2640 if (cli->protocol >= PROTOCOL_NT1) {
2642 bool negotiated_smb_signing = false;
2645 cli->sec_mode = CVAL(vwv + 1, 0);
2646 cli->max_mux = SVAL(vwv + 1, 1);
2647 cli->max_xmit = IVAL(vwv + 3, 1);
2648 cli->sesskey = IVAL(vwv + 7, 1);
2649 cli->serverzone = SVALS(vwv + 15, 1);
2650 cli->serverzone *= 60;
2651 /* this time arrives in real GMT */
2652 ts = interpret_long_date(((char *)(vwv+11))+1);
2653 cli->servertime = ts.tv_sec;
2654 cli->secblob = data_blob(bytes, num_bytes);
2655 cli->capabilities = IVAL(vwv + 9, 1);
2656 if (cli->capabilities & CAP_RAW_MODE) {
2657 cli->readbraw_supported = True;
2658 cli->writebraw_supported = True;
2660 /* work out if they sent us a workgroup */
2661 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2662 smb_buflen(inbuf) > 8) {
2664 status = smb_bytes_talloc_string(
2665 cli, (char *)inbuf, &cli->server_domain,
2666 bytes + 8, num_bytes - 8, &ret);
2667 if (tevent_req_nterror(req, status)) {
2673 * As signing is slow we only turn it on if either the client or
2674 * the server require it. JRA.
2677 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2678 /* Fail if server says signing is mandatory and we don't want to support it. */
2679 if (!client_is_signing_allowed(cli)) {
2680 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2681 tevent_req_nterror(req,
2682 NT_STATUS_ACCESS_DENIED);
2685 negotiated_smb_signing = true;
2686 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2687 /* Fail if client says signing is mandatory and the server doesn't support it. */
2688 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2689 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2690 tevent_req_nterror(req,
2691 NT_STATUS_ACCESS_DENIED);
2694 negotiated_smb_signing = true;
2695 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2696 negotiated_smb_signing = true;
2699 if (negotiated_smb_signing) {
2700 cli_set_signing_negotiated(cli);
2703 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2704 SAFE_FREE(cli->outbuf);
2705 SAFE_FREE(cli->inbuf);
2706 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2707 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2708 if (!cli->outbuf || !cli->inbuf) {
2709 tevent_req_nterror(req,
2710 NT_STATUS_NO_MEMORY);
2713 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2716 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2717 cli->use_spnego = False;
2718 cli->sec_mode = SVAL(vwv + 1, 0);
2719 cli->max_xmit = SVAL(vwv + 2, 0);
2720 cli->max_mux = SVAL(vwv + 3, 0);
2721 cli->sesskey = IVAL(vwv + 6, 0);
2722 cli->serverzone = SVALS(vwv + 10, 0);
2723 cli->serverzone *= 60;
2724 /* this time is converted to GMT by make_unix_date */
2725 cli->servertime = make_unix_date(
2726 (char *)(vwv + 8), cli->serverzone);
2727 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2728 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2729 cli->secblob = data_blob(bytes, num_bytes);
2731 /* the old core protocol */
2732 cli->use_spnego = False;
2734 cli->serverzone = get_time_zone(time(NULL));
2737 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2739 /* a way to force ascii SMB */
2740 if (getenv("CLI_FORCE_ASCII"))
2741 cli->capabilities &= ~CAP_UNICODE;
2743 tevent_req_done(req);
2746 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2748 return tevent_req_simple_recv_ntstatus(req);
2751 NTSTATUS cli_negprot(struct cli_state *cli)
2753 TALLOC_CTX *frame = talloc_stackframe();
2754 struct event_context *ev;
2755 struct tevent_req *req;
2756 NTSTATUS status = NT_STATUS_OK;
2758 if (cli_has_async_calls(cli)) {
2760 * Can't use sync call while an async call is in flight
2762 status = NT_STATUS_INVALID_PARAMETER;
2766 ev = event_context_init(frame);
2768 status = NT_STATUS_NO_MEMORY;
2772 req = cli_negprot_send(frame, ev, cli);
2774 status = NT_STATUS_NO_MEMORY;
2778 if (!tevent_req_poll(req, ev)) {
2779 status = map_nt_error_from_unix(errno);
2783 status = cli_negprot_recv(req);
2789 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2790 const struct sockaddr_storage *pss,
2791 const char *myname, uint16_t port,
2792 int sec_timeout, int *pfd, uint16_t *pport)
2794 TALLOC_CTX *frame = talloc_stackframe();
2796 unsigned int i, num_addrs;
2797 const char **called_names;
2798 const char **calling_names;
2803 prog = getenv("LIBSMB_PROG");
2805 fd = sock_exec(prog);
2807 return map_nt_error_from_unix(errno);
2813 if ((pss == NULL) || is_zero_addr(pss)) {
2814 struct sockaddr_storage *addrs;
2815 status = resolve_name_list(talloc_tos(), host, name_type,
2816 &addrs, &num_addrs);
2817 if (!NT_STATUS_IS_OK(status)) {
2825 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2826 if (called_names == NULL) {
2827 status = NT_STATUS_NO_MEMORY;
2830 called_types = talloc_array(talloc_tos(), int, num_addrs);
2831 if (called_types == NULL) {
2832 status = NT_STATUS_NO_MEMORY;
2835 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2836 if (calling_names == NULL) {
2837 status = NT_STATUS_NO_MEMORY;
2840 for (i=0; i<num_addrs; i++) {
2841 called_names[i] = host;
2842 called_types[i] = name_type;
2843 calling_names[i] = myname;
2845 status = smbsock_any_connect(pss, called_names, called_types,
2846 calling_names, NULL, num_addrs, port,
2847 sec_timeout, &fd, NULL, &port);
2848 if (!NT_STATUS_IS_OK(status)) {
2851 set_socket_options(fd, lp_socket_options());
2855 status = NT_STATUS_OK;
2861 NTSTATUS cli_connect_nb(const char *host, struct sockaddr_storage *pss,
2862 uint16_t port, int name_type, const char *myname,
2863 int signing_state, struct cli_state **pcli)
2865 TALLOC_CTX *frame = talloc_stackframe();
2866 struct cli_state *cli;
2867 NTSTATUS status = NT_STATUS_NO_MEMORY;
2874 desthost = talloc_strdup(talloc_tos(), host);
2875 if (desthost == NULL) {
2879 p = strchr(host, '#');
2881 name_type = strtol(p+1, NULL, 16);
2882 host = talloc_strndup(talloc_tos(), host, p - host);
2888 cli = cli_initialise_ex(signing_state);
2892 cli->desthost = talloc_move(cli, &desthost);
2894 status = cli_connect_sock(host, name_type, pss, myname, port, 20, &fd,
2896 if (!NT_STATUS_IS_OK(status)) {
2903 length = sizeof(cli->dest_ss);
2904 ret = getpeername(fd, (struct sockaddr *)(void *)&cli->dest_ss,
2907 status = map_nt_error_from_unix(errno);
2913 *pss = cli->dest_ss;
2917 status = NT_STATUS_OK;
2924 establishes a connection to after the negprot.
2925 @param output_cli A fully initialised cli structure, non-null only on success
2926 @param dest_host The netbios name of the remote host
2927 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2928 @param port (optional) The destination port (0 for default)
2930 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2931 const char *my_name,
2932 const char *dest_host,
2933 struct sockaddr_storage *dest_ss, int port,
2934 int signing_state, int flags)
2937 struct cli_state *cli;
2939 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2940 signing_state, &cli);
2941 if (!NT_STATUS_IS_OK(nt_status)) {
2942 DEBUG(10, ("cli_connect_nb failed: %s\n",
2943 nt_errstr(nt_status)));
2947 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2948 cli->use_spnego = False;
2949 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2950 cli->use_kerberos = True;
2952 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2953 cli->use_kerberos) {
2954 cli->fallback_after_kerberos = true;
2956 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2957 cli->use_ccache = true;
2960 nt_status = cli_negprot(cli);
2961 if (!NT_STATUS_IS_OK(nt_status)) {
2962 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2968 return NT_STATUS_OK;
2973 establishes a connection right up to doing tconX, password specified.
2974 @param output_cli A fully initialised cli structure, non-null only on success
2975 @param dest_host The netbios name of the remote host
2976 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2977 @param port (optional) The destination port (0 for default)
2978 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2979 @param service_type The 'type' of serivice.
2980 @param user Username, unix string
2981 @param domain User's domain
2982 @param password User's password, unencrypted unix string.
2985 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2986 const char *my_name,
2987 const char *dest_host,
2988 struct sockaddr_storage *dest_ss, int port,
2989 const char *service, const char *service_type,
2990 const char *user, const char *domain,
2991 const char *password, int flags,
2995 struct cli_state *cli = NULL;
2996 int pw_len = password ? strlen(password)+1 : 0;
3000 if (password == NULL) {
3004 nt_status = cli_start_connection(&cli, my_name, dest_host,
3005 dest_ss, port, signing_state,
3008 if (!NT_STATUS_IS_OK(nt_status)) {
3012 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3013 cli->use_level_II_oplocks =
3014 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3016 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3018 if (!NT_STATUS_IS_OK(nt_status)) {
3020 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3021 DEBUG(1,("failed session setup with %s\n",
3022 nt_errstr(nt_status)));
3027 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3028 if (!NT_STATUS_IS_OK(nt_status)) {
3029 DEBUG(1,("anonymous failed session setup with %s\n",
3030 nt_errstr(nt_status)));
3037 nt_status = cli_tcon_andx(cli, service, service_type, password,
3039 if (!NT_STATUS_IS_OK(nt_status)) {
3040 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3042 if (NT_STATUS_IS_OK(nt_status)) {
3043 nt_status = NT_STATUS_UNSUCCESSFUL;
3049 nt_status = cli_init_creds(cli, user, domain, password);
3050 if (!NT_STATUS_IS_OK(nt_status)) {
3056 return NT_STATUS_OK;
3059 /****************************************************************************
3060 Send an old style tcon.
3061 ****************************************************************************/
3062 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3063 const char *service, const char *pass, const char *dev,
3064 uint16 *max_xmit, uint16 *tid)
3066 struct tevent_req *req;
3071 if (!lp_client_plaintext_auth() && (*pass)) {
3072 DEBUG(1, ("Server requested plaintext password but 'client "
3073 "plaintext auth' is disabled\n"));
3074 return NT_STATUS_ACCESS_DENIED;
3077 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3078 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3079 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3080 service, strlen(service)+1, NULL);
3081 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3082 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3083 pass, strlen(pass)+1, NULL);
3084 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3085 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3086 dev, strlen(dev)+1, NULL);
3088 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3089 talloc_get_size(bytes), bytes, &req,
3090 2, NULL, &ret_vwv, NULL, NULL);
3091 if (!NT_STATUS_IS_OK(status)) {
3095 *max_xmit = SVAL(ret_vwv + 0, 0);
3096 *tid = SVAL(ret_vwv + 1, 0);
3098 return NT_STATUS_OK;
3101 /* Return a cli_state pointing at the IPC$ share for the given server */
3103 struct cli_state *get_ipc_connect(char *server,
3104 struct sockaddr_storage *server_ss,
3105 const struct user_auth_info *user_info)
3107 struct cli_state *cli;
3109 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3111 if (user_info->use_kerberos) {
3112 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3115 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3116 user_info->username ? user_info->username : "",
3118 user_info->password ? user_info->password : "",
3122 if (NT_STATUS_IS_OK(nt_status)) {
3124 } else if (is_ipaddress(server)) {
3125 /* windows 9* needs a correct NMB name for connections */
3126 fstring remote_name;
3128 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3129 cli = get_ipc_connect(remote_name, server_ss, user_info);
3138 * Given the IP address of a master browser on the network, return its
3139 * workgroup and connect to it.
3141 * This function is provided to allow additional processing beyond what
3142 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3143 * browsers and obtain each master browsers' list of domains (in case the
3144 * first master browser is recently on the network and has not yet
3145 * synchronized with other master browsers and therefore does not yet have the
3146 * entire network browse list)
3149 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3150 struct sockaddr_storage *mb_ip,
3151 const struct user_auth_info *user_info,
3152 char **pp_workgroup_out)
3154 char addr[INET6_ADDRSTRLEN];
3156 struct cli_state *cli;
3157 struct sockaddr_storage server_ss;
3159 *pp_workgroup_out = NULL;
3161 print_sockaddr(addr, sizeof(addr), mb_ip);
3162 DEBUG(99, ("Looking up name of master browser %s\n",
3166 * Do a name status query to find out the name of the master browser.
3167 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3168 * master browser will not respond to a wildcard query (or, at least,
3169 * an NT4 server acting as the domain master browser will not).
3171 * We might be able to use ONLY the query on MSBROWSE, but that's not
3172 * yet been tested with all Windows versions, so until it is, leave
3173 * the original wildcard query as the first choice and fall back to
3174 * MSBROWSE if the wildcard query fails.
3176 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3177 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3179 DEBUG(99, ("Could not retrieve name status for %s\n",
3184 if (!find_master_ip(name, &server_ss)) {
3185 DEBUG(99, ("Could not find master ip for %s\n", name));
3189 *pp_workgroup_out = talloc_strdup(ctx, name);
3191 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3193 print_sockaddr(addr, sizeof(addr), &server_ss);
3194 cli = get_ipc_connect(addr, &server_ss, user_info);
3200 * Return the IP address and workgroup of a master browser on the network, and
3204 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3205 const struct user_auth_info *user_info,
3206 char **pp_workgroup_out)
3208 struct sockaddr_storage *ip_list;
3209 struct cli_state *cli;
3213 *pp_workgroup_out = NULL;
3215 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3217 /* Go looking for workgroups by broadcasting on the local network */
3219 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3221 if (!NT_STATUS_IS_OK(status)) {
3222 DEBUG(99, ("No master browsers responded: %s\n",
3223 nt_errstr(status)));
3227 for (i = 0; i < count; i++) {
3228 char addr[INET6_ADDRSTRLEN];
3229 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3230 DEBUG(99, ("Found master browser %s\n", addr));
3232 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3233 user_info, pp_workgroup_out);