2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "popt_common.h"
23 #include "../libcli/auth/libcli_auth.h"
24 #include "../libcli/auth/spnego.h"
26 #include "../libcli/auth/ntlmssp.h"
27 #include "libads/kerberos_proto.h"
29 #include "async_smb.h"
35 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
36 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
37 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
38 {PROTOCOL_LANMAN1, "LANMAN1.0"},
39 {PROTOCOL_LANMAN2, "LM1.2X002"},
40 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
41 {PROTOCOL_LANMAN2, "LANMAN2.1"},
42 {PROTOCOL_LANMAN2, "Samba"},
43 {PROTOCOL_NT1, "NT LANMAN 1.0"},
44 {PROTOCOL_NT1, "NT LM 0.12"},
47 #define STAR_SMBSERVER "*SMBSERVER"
50 * Set the user session key for a connection
51 * @param cli The cli structure to add it too
52 * @param session_key The session key used. (A copy of this is taken for the cli struct)
56 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
58 cli->user_session_key = data_blob(session_key.data, session_key.length);
61 /****************************************************************************
62 Do an old lanman2 style session setup.
63 ****************************************************************************/
65 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
67 const char *pass, size_t passlen,
68 const char *workgroup)
70 DATA_BLOB session_key = data_blob_null;
71 DATA_BLOB lm_response = data_blob_null;
76 if (passlen > sizeof(pword)-1) {
77 return NT_STATUS_INVALID_PARAMETER;
80 /* LANMAN servers predate NT status codes and Unicode and ignore those
81 smb flags so we must disable the corresponding default capabilities
82 that would otherwise cause the Unicode and NT Status flags to be
83 set (and even returned by the server) */
85 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
87 /* if in share level security then don't send a password now */
88 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
91 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
92 /* Encrypted mode needed, and non encrypted password supplied. */
93 lm_response = data_blob(NULL, 24);
94 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
95 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
96 return NT_STATUS_ACCESS_DENIED;
98 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
99 /* Encrypted mode needed, and encrypted password supplied. */
100 lm_response = data_blob(pass, passlen);
101 } else if (passlen > 0) {
102 /* Plaintext mode needed, assume plaintext supplied. */
103 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
104 lm_response = data_blob(pass, passlen);
107 /* send a session setup command */
108 memset(cli->outbuf,'\0',smb_size);
109 cli_set_message(cli->outbuf,10, 0, True);
110 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
111 cli_setup_packet(cli);
113 SCVAL(cli->outbuf,smb_vwv0,0xFF);
114 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
115 SSVAL(cli->outbuf,smb_vwv3,2);
116 SSVAL(cli->outbuf,smb_vwv4,1);
117 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
118 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
120 p = smb_buf(cli->outbuf);
121 memcpy(p,lm_response.data,lm_response.length);
122 p += lm_response.length;
123 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
124 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
125 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
126 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
127 cli_setup_bcc(cli, p);
129 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
130 return cli_nt_error(cli);
133 show_msg(cli->inbuf);
135 if (cli_is_error(cli)) {
136 return cli_nt_error(cli);
139 /* use the returned vuid from now on */
140 cli->vuid = SVAL(cli->inbuf,smb_uid);
141 status = cli_set_username(cli, user);
142 if (!NT_STATUS_IS_OK(status)) {
146 if (session_key.data) {
147 /* Have plaintext orginal */
148 cli_set_session_key(cli, session_key);
154 /****************************************************************************
155 Work out suitable capabilities to offer the server.
156 ****************************************************************************/
158 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
160 uint32 capabilities = CAP_NT_SMBS;
162 if (!cli->force_dos_errors)
163 capabilities |= CAP_STATUS32;
165 if (cli->use_level_II_oplocks)
166 capabilities |= CAP_LEVEL_II_OPLOCKS;
168 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
172 /****************************************************************************
173 Do a NT1 guest session setup.
174 ****************************************************************************/
176 struct cli_session_setup_guest_state {
177 struct cli_state *cli;
182 static void cli_session_setup_guest_done(struct tevent_req *subreq);
184 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
185 struct event_context *ev,
186 struct cli_state *cli,
187 struct tevent_req **psmbreq)
189 struct tevent_req *req, *subreq;
190 struct cli_session_setup_guest_state *state;
194 req = tevent_req_create(mem_ctx, &state,
195 struct cli_session_setup_guest_state);
202 SCVAL(vwv+0, 0, 0xFF);
205 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
207 SSVAL(vwv+4, 0, cli->pid);
208 SIVAL(vwv+5, 0, cli->sesskey);
213 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
215 bytes = talloc_array(state, uint8_t, 0);
217 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
219 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
221 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
222 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
229 state->bytes.iov_base = (void *)bytes;
230 state->bytes.iov_len = talloc_get_size(bytes);
232 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
234 if (subreq == NULL) {
238 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
243 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
244 struct event_context *ev,
245 struct cli_state *cli)
247 struct tevent_req *req, *subreq;
250 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
255 status = cli_smb_req_send(subreq);
256 if (NT_STATUS_IS_OK(status)) {
257 tevent_req_nterror(req, status);
258 return tevent_req_post(req, ev);
263 static void cli_session_setup_guest_done(struct tevent_req *subreq)
265 struct tevent_req *req = tevent_req_callback_data(
266 subreq, struct tevent_req);
267 struct cli_session_setup_guest_state *state = tevent_req_data(
268 req, struct cli_session_setup_guest_state);
269 struct cli_state *cli = state->cli;
277 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
280 if (!NT_STATUS_IS_OK(status)) {
281 tevent_req_nterror(req, status);
288 cli->vuid = SVAL(inbuf, smb_uid);
290 p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
291 bytes+num_bytes-p, STR_TERMINATE);
292 p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
293 bytes+num_bytes-p, STR_TERMINATE);
294 p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
295 bytes+num_bytes-p, STR_TERMINATE);
297 if (strstr(cli->server_type, "Samba")) {
298 cli->is_samba = True;
301 status = cli_set_username(cli, "");
302 if (!NT_STATUS_IS_OK(status)) {
303 tevent_req_nterror(req, status);
306 tevent_req_done(req);
309 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
311 return tevent_req_simple_recv_ntstatus(req);
314 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
316 TALLOC_CTX *frame = talloc_stackframe();
317 struct event_context *ev;
318 struct tevent_req *req;
319 NTSTATUS status = NT_STATUS_OK;
321 if (cli_has_async_calls(cli)) {
323 * Can't use sync call while an async call is in flight
325 status = NT_STATUS_INVALID_PARAMETER;
329 ev = event_context_init(frame);
331 status = NT_STATUS_NO_MEMORY;
335 req = cli_session_setup_guest_send(frame, ev, cli);
337 status = NT_STATUS_NO_MEMORY;
341 if (!tevent_req_poll(req, ev)) {
342 status = map_nt_error_from_unix(errno);
346 status = cli_session_setup_guest_recv(req);
349 if (!NT_STATUS_IS_OK(status)) {
350 cli_set_error(cli, status);
355 /****************************************************************************
356 Do a NT1 plaintext session setup.
357 ****************************************************************************/
359 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
360 const char *user, const char *pass,
361 const char *workgroup)
363 uint32 capabilities = cli_session_setup_capabilities(cli);
368 fstr_sprintf( lanman, "Samba %s", samba_version_string());
370 memset(cli->outbuf, '\0', smb_size);
371 cli_set_message(cli->outbuf,13,0,True);
372 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
373 cli_setup_packet(cli);
375 SCVAL(cli->outbuf,smb_vwv0,0xFF);
376 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
377 SSVAL(cli->outbuf,smb_vwv3,2);
378 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
379 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
380 SSVAL(cli->outbuf,smb_vwv8,0);
381 SIVAL(cli->outbuf,smb_vwv11,capabilities);
382 p = smb_buf(cli->outbuf);
384 /* check wether to send the ASCII or UNICODE version of the password */
386 if ( (capabilities & CAP_UNICODE) == 0 ) {
387 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
388 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
391 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
392 * the space taken by the unicode password to be one byte too
393 * long (as we're on an odd byte boundary here). Reduce the
394 * count by 1 to cope with this. Fixes smbclient against NetApp
395 * servers which can't cope. Fix from
396 * bryan.kolodziej@allenlund.com in bug #3840.
398 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
399 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
402 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
403 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
404 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
405 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
406 cli_setup_bcc(cli, p);
408 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
409 return cli_nt_error(cli);
412 show_msg(cli->inbuf);
414 if (cli_is_error(cli)) {
415 return cli_nt_error(cli);
418 cli->vuid = SVAL(cli->inbuf,smb_uid);
419 p = smb_buf(cli->inbuf);
420 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
422 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
424 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
426 status = cli_set_username(cli, user);
427 if (!NT_STATUS_IS_OK(status)) {
430 if (strstr(cli->server_type, "Samba")) {
431 cli->is_samba = True;
437 /****************************************************************************
438 do a NT1 NTLM/LM encrypted session setup - for when extended security
440 @param cli client state to create do session setup on
442 @param pass *either* cleartext password (passlen !=24) or LM response.
443 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
444 @param workgroup The user's domain.
445 ****************************************************************************/
447 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
448 const char *pass, size_t passlen,
449 const char *ntpass, size_t ntpasslen,
450 const char *workgroup)
452 uint32 capabilities = cli_session_setup_capabilities(cli);
453 DATA_BLOB lm_response = data_blob_null;
454 DATA_BLOB nt_response = data_blob_null;
455 DATA_BLOB session_key = data_blob_null;
461 /* do nothing - guest login */
462 } else if (passlen != 24) {
463 if (lp_client_ntlmv2_auth()) {
464 DATA_BLOB server_chal;
465 DATA_BLOB names_blob;
466 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
468 /* note that the 'workgroup' here is a best guess - we don't know
469 the server's domain at this point. The 'server name' is also
472 names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup);
474 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal,
476 &lm_response, &nt_response, NULL, &session_key)) {
477 data_blob_free(&names_blob);
478 data_blob_free(&server_chal);
479 return NT_STATUS_ACCESS_DENIED;
481 data_blob_free(&names_blob);
482 data_blob_free(&server_chal);
486 E_md4hash(pass, nt_hash);
489 nt_response = data_blob_null;
491 nt_response = data_blob(NULL, 24);
492 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
494 /* non encrypted password supplied. Ignore ntpass. */
495 if (lp_client_lanman_auth()) {
496 lm_response = data_blob(NULL, 24);
497 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
498 /* Oops, the LM response is invalid, just put
499 the NT response there instead */
500 data_blob_free(&lm_response);
501 lm_response = data_blob(nt_response.data, nt_response.length);
504 /* LM disabled, place NT# in LM field instead */
505 lm_response = data_blob(nt_response.data, nt_response.length);
508 session_key = data_blob(NULL, 16);
510 E_deshash(pass, session_key.data);
511 memset(&session_key.data[8], '\0', 8);
513 SMBsesskeygen_ntv1(nt_hash, session_key.data);
516 cli_temp_set_signing(cli);
518 /* pre-encrypted password supplied. Only used for
519 security=server, can't do
520 signing because we don't have original key */
522 lm_response = data_blob(pass, passlen);
523 nt_response = data_blob(ntpass, ntpasslen);
526 /* send a session setup command */
527 memset(cli->outbuf,'\0',smb_size);
529 cli_set_message(cli->outbuf,13,0,True);
530 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
531 cli_setup_packet(cli);
533 SCVAL(cli->outbuf,smb_vwv0,0xFF);
534 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
535 SSVAL(cli->outbuf,smb_vwv3,2);
536 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
537 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
538 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
539 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
540 SIVAL(cli->outbuf,smb_vwv11,capabilities);
541 p = smb_buf(cli->outbuf);
542 if (lm_response.length) {
543 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
545 if (nt_response.length) {
546 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
548 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
550 /* Upper case here might help some NTLMv2 implementations */
551 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
552 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
553 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
554 cli_setup_bcc(cli, p);
556 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
557 result = cli_nt_error(cli);
561 /* show_msg(cli->inbuf); */
563 if (cli_is_error(cli)) {
564 result = cli_nt_error(cli);
569 ok = cli_simple_set_signing(cli, session_key, lm_response);
571 ok = cli_simple_set_signing(cli, session_key, nt_response);
574 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
575 result = NT_STATUS_ACCESS_DENIED;
580 /* use the returned vuid from now on */
581 cli->vuid = SVAL(cli->inbuf,smb_uid);
583 p = smb_buf(cli->inbuf);
584 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
586 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
588 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
591 if (strstr(cli->server_type, "Samba")) {
592 cli->is_samba = True;
595 result = cli_set_username(cli, user);
596 if (!NT_STATUS_IS_OK(result)) {
600 if (session_key.data) {
601 /* Have plaintext orginal */
602 cli_set_session_key(cli, session_key);
605 result = NT_STATUS_OK;
607 data_blob_free(&lm_response);
608 data_blob_free(&nt_response);
609 data_blob_free(&session_key);
613 /* The following is calculated from :
615 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
616 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
620 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
622 struct cli_sesssetup_blob_state {
623 struct tevent_context *ev;
624 struct cli_state *cli;
626 uint16_t max_blob_size;
635 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
636 struct tevent_req **psubreq);
637 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
639 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
640 struct tevent_context *ev,
641 struct cli_state *cli,
644 struct tevent_req *req, *subreq;
645 struct cli_sesssetup_blob_state *state;
647 req = tevent_req_create(mem_ctx, &state,
648 struct cli_sesssetup_blob_state);
656 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
657 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
658 "(was %u, need minimum %u)\n",
659 (unsigned int)cli->max_xmit,
660 BASE_SESSSETUP_BLOB_PACKET_SIZE));
661 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
662 return tevent_req_post(req, ev);
664 state->max_blob_size =
665 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
667 if (!cli_sesssetup_blob_next(state, &subreq)) {
668 tevent_req_nomem(NULL, req);
669 return tevent_req_post(req, ev);
671 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
675 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
676 struct tevent_req **psubreq)
678 struct tevent_req *subreq;
681 SCVAL(state->vwv+0, 0, 0xFF);
682 SCVAL(state->vwv+0, 1, 0);
683 SSVAL(state->vwv+1, 0, 0);
684 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
685 SSVAL(state->vwv+3, 0, 2);
686 SSVAL(state->vwv+4, 0, 1);
687 SIVAL(state->vwv+5, 0, 0);
689 thistime = MIN(state->blob.length, state->max_blob_size);
690 SSVAL(state->vwv+7, 0, thistime);
692 SSVAL(state->vwv+8, 0, 0);
693 SSVAL(state->vwv+9, 0, 0);
694 SIVAL(state->vwv+10, 0,
695 cli_session_setup_capabilities(state->cli)
696 | CAP_EXTENDED_SECURITY);
698 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
700 if (state->buf == NULL) {
703 state->blob.data += thistime;
704 state->blob.length -= thistime;
706 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
708 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
710 if (state->buf == NULL) {
713 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
715 talloc_get_size(state->buf), state->buf);
716 if (subreq == NULL) {
723 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
725 struct tevent_req *req = tevent_req_callback_data(
726 subreq, struct tevent_req);
727 struct cli_sesssetup_blob_state *state = tevent_req_data(
728 req, struct cli_sesssetup_blob_state);
729 struct cli_state *cli = state->cli;
736 uint16_t blob_length;
739 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
742 if (!NT_STATUS_IS_OK(status)
743 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
744 tevent_req_nterror(req, status);
748 state->status = status;
749 TALLOC_FREE(state->buf);
751 state->inbuf = (char *)inbuf;
752 cli->vuid = SVAL(state->inbuf, smb_uid);
754 blob_length = SVAL(vwv+3, 0);
755 if (blob_length > num_bytes) {
756 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
759 state->ret_blob = data_blob_const(bytes, blob_length);
761 p = bytes + blob_length;
763 p += clistr_pull(state->inbuf, cli->server_os,
764 (char *)p, sizeof(fstring),
765 bytes+num_bytes-p, STR_TERMINATE);
766 p += clistr_pull(state->inbuf, cli->server_type,
767 (char *)p, sizeof(fstring),
768 bytes+num_bytes-p, STR_TERMINATE);
769 p += clistr_pull(state->inbuf, cli->server_domain,
770 (char *)p, sizeof(fstring),
771 bytes+num_bytes-p, STR_TERMINATE);
773 if (strstr(cli->server_type, "Samba")) {
774 cli->is_samba = True;
777 if (state->blob.length != 0) {
781 if (!cli_sesssetup_blob_next(state, &subreq)) {
782 tevent_req_nomem(NULL, req);
785 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
788 tevent_req_done(req);
791 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
796 struct cli_sesssetup_blob_state *state = tevent_req_data(
797 req, struct cli_sesssetup_blob_state);
801 if (tevent_req_is_nterror(req, &status)) {
802 state->cli->vuid = 0;
806 inbuf = talloc_move(mem_ctx, &state->inbuf);
808 *pblob = state->ret_blob;
810 if (pinbuf != NULL) {
813 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
814 return state->status;
819 /****************************************************************************
820 Use in-memory credentials cache
821 ****************************************************************************/
823 static void use_in_memory_ccache(void) {
824 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
827 /****************************************************************************
828 Do a spnego/kerberos encrypted session setup.
829 ****************************************************************************/
831 struct cli_session_setup_kerberos_state {
832 struct cli_state *cli;
833 DATA_BLOB negTokenTarg;
834 DATA_BLOB session_key_krb5;
835 ADS_STATUS ads_status;
838 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
840 static struct tevent_req *cli_session_setup_kerberos_send(
841 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
842 const char *principal, const char *workgroup)
844 struct tevent_req *req, *subreq;
845 struct cli_session_setup_kerberos_state *state;
848 DEBUG(2,("Doing kerberos session setup\n"));
850 req = tevent_req_create(mem_ctx, &state,
851 struct cli_session_setup_kerberos_state);
856 state->ads_status = ADS_SUCCESS;
858 cli_temp_set_signing(cli);
861 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
862 * we have to acquire a ticket. To be fixed later :-)
864 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
865 &state->session_key_krb5, 0, NULL);
867 DEBUG(1, ("cli_session_setup_kerberos: "
868 "spnego_gen_krb5_negTokenInit failed: %s\n",
870 state->ads_status = ADS_ERROR_KRB5(rc);
871 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
872 return tevent_req_post(req, ev);
876 file_save("negTokenTarg.dat", state->negTokenTarg.data,
877 state->negTokenTarg.length);
880 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
881 if (tevent_req_nomem(subreq, req)) {
882 return tevent_req_post(req, ev);
884 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
888 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
890 struct tevent_req *req = tevent_req_callback_data(
891 subreq, struct tevent_req);
892 struct cli_session_setup_kerberos_state *state = tevent_req_data(
893 req, struct cli_session_setup_kerberos_state);
897 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
898 if (!NT_STATUS_IS_OK(status)) {
900 tevent_req_nterror(req, status);
904 cli_set_session_key(state->cli, state->session_key_krb5);
906 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
908 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
910 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
914 tevent_req_done(req);
917 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
919 struct cli_session_setup_kerberos_state *state = tevent_req_data(
920 req, struct cli_session_setup_kerberos_state);
923 if (tevent_req_is_nterror(req, &status)) {
924 return ADS_ERROR_NT(status);
926 return state->ads_status;
929 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
930 const char *principal,
931 const char *workgroup)
933 struct tevent_context *ev;
934 struct tevent_req *req;
935 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
937 if (cli_has_async_calls(cli)) {
938 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
940 ev = tevent_context_init(talloc_tos());
944 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
949 if (!tevent_req_poll(req, ev)) {
950 status = ADS_ERROR_SYSTEM(errno);
953 status = cli_session_setup_kerberos_recv(req);
958 #endif /* HAVE_KRB5 */
960 /****************************************************************************
961 Do a spnego/NTLMSSP encrypted session setup.
962 ****************************************************************************/
964 struct cli_session_setup_ntlmssp_state {
965 struct tevent_context *ev;
966 struct cli_state *cli;
967 struct ntlmssp_state *ntlmssp_state;
972 static int cli_session_setup_ntlmssp_state_destructor(
973 struct cli_session_setup_ntlmssp_state *state)
975 if (state->ntlmssp_state != NULL) {
976 TALLOC_FREE(state->ntlmssp_state);
981 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
983 static struct tevent_req *cli_session_setup_ntlmssp_send(
984 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
985 const char *user, const char *pass, const char *domain)
987 struct tevent_req *req, *subreq;
988 struct cli_session_setup_ntlmssp_state *state;
991 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
993 req = tevent_req_create(mem_ctx, &state,
994 struct cli_session_setup_ntlmssp_state);
1002 state->ntlmssp_state = NULL;
1003 talloc_set_destructor(
1004 state, cli_session_setup_ntlmssp_state_destructor);
1006 cli_temp_set_signing(cli);
1008 status = ntlmssp_client_start(state,
1011 lp_client_ntlmv2_auth(),
1012 &state->ntlmssp_state);
1013 if (!NT_STATUS_IS_OK(status)) {
1016 ntlmssp_want_feature(state->ntlmssp_state,
1017 NTLMSSP_FEATURE_SESSION_KEY);
1018 if (cli->use_ccache) {
1019 ntlmssp_want_feature(state->ntlmssp_state,
1020 NTLMSSP_FEATURE_CCACHE);
1022 status = ntlmssp_set_username(state->ntlmssp_state, user);
1023 if (!NT_STATUS_IS_OK(status)) {
1026 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1027 if (!NT_STATUS_IS_OK(status)) {
1030 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1031 if (!NT_STATUS_IS_OK(status)) {
1034 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1036 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1040 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1041 data_blob_free(&blob_out);
1043 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1044 if (tevent_req_nomem(subreq, req)) {
1045 return tevent_req_post(req, ev);
1047 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1050 tevent_req_nterror(req, status);
1051 return tevent_req_post(req, ev);
1054 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1056 struct tevent_req *req = tevent_req_callback_data(
1057 subreq, struct tevent_req);
1058 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1059 req, struct cli_session_setup_ntlmssp_state);
1060 DATA_BLOB blob_in, msg_in, blob_out;
1065 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1067 TALLOC_FREE(subreq);
1068 data_blob_free(&state->blob_out);
1070 if (NT_STATUS_IS_OK(status)) {
1071 if (state->cli->server_domain[0] == '\0') {
1072 fstrcpy(state->cli->server_domain,
1073 state->ntlmssp_state->server.netbios_domain);
1075 cli_set_session_key(
1076 state->cli, state->ntlmssp_state->session_key);
1078 if (cli_simple_set_signing(
1079 state->cli, state->ntlmssp_state->session_key,
1081 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1082 TALLOC_FREE(subreq);
1083 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1086 TALLOC_FREE(subreq);
1087 TALLOC_FREE(state->ntlmssp_state);
1088 tevent_req_done(req);
1091 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1092 tevent_req_nterror(req, status);
1096 if (blob_in.length == 0) {
1097 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1101 if ((state->turn == 1)
1102 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1103 DATA_BLOB tmp_blob = data_blob_null;
1104 /* the server might give us back two challenges */
1105 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1107 data_blob_free(&tmp_blob);
1109 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1110 OID_NTLMSSP, &msg_in);
1115 DEBUG(3,("Failed to parse auth response\n"));
1116 if (NT_STATUS_IS_OK(status)
1117 || NT_STATUS_EQUAL(status,
1118 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1120 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1125 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1127 if (!NT_STATUS_IS_OK(status)
1128 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1129 TALLOC_FREE(subreq);
1130 TALLOC_FREE(state->ntlmssp_state);
1131 tevent_req_nterror(req, status);
1135 state->blob_out = spnego_gen_auth(state, blob_out);
1136 TALLOC_FREE(subreq);
1137 if (tevent_req_nomem(state->blob_out.data, req)) {
1141 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1143 if (tevent_req_nomem(subreq, req)) {
1146 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1149 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1151 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1152 req, struct cli_session_setup_ntlmssp_state);
1155 if (tevent_req_is_nterror(req, &status)) {
1156 state->cli->vuid = 0;
1159 return NT_STATUS_OK;
1162 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1167 struct tevent_context *ev;
1168 struct tevent_req *req;
1169 NTSTATUS status = NT_STATUS_NO_MEMORY;
1171 if (cli_has_async_calls(cli)) {
1172 return NT_STATUS_INVALID_PARAMETER;
1174 ev = tevent_context_init(talloc_tos());
1178 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1182 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1185 status = cli_session_setup_ntlmssp_recv(req);
1188 if (!NT_STATUS_IS_OK(status)) {
1189 cli_set_error(cli, status);
1194 /****************************************************************************
1195 Do a spnego encrypted session setup.
1197 user_domain: The shortname of the domain the user/machine is a member of.
1198 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1199 ****************************************************************************/
1201 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1202 const char *pass, const char *user_domain,
1203 const char * dest_realm)
1205 char *principal = NULL;
1206 char *OIDs[ASN1_MAX_OIDS];
1209 const char *p = NULL;
1210 char *account = NULL;
1213 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1215 /* the server might not even do spnego */
1216 if (cli->secblob.length <= 16) {
1217 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1222 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1225 /* there is 16 bytes of GUID before the real spnego packet starts */
1226 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1228 /* The server sent us the first part of the SPNEGO exchange in the
1229 * negprot reply. It is WRONG to depend on the principal sent in the
1230 * negprot reply, but right now we do it. If we don't receive one,
1231 * we try to best guess, then fall back to NTLM. */
1232 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1234 data_blob_free(&blob);
1235 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1237 data_blob_free(&blob);
1239 /* make sure the server understands kerberos */
1240 for (i=0;OIDs[i];i++) {
1242 DEBUG(3,("got OID=%s\n", OIDs[i]));
1244 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1245 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1246 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1247 cli->got_kerberos_mechanism = True;
1249 talloc_free(OIDs[i]);
1252 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1254 status = cli_set_username(cli, user);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 TALLOC_FREE(principal);
1257 return ADS_ERROR_NT(status);
1261 /* If password is set we reauthenticate to kerberos server
1262 * and do not store results */
1264 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1267 if (pass && *pass) {
1270 use_in_memory_ccache();
1271 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1274 TALLOC_FREE(principal);
1275 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1276 if (cli->fallback_after_kerberos)
1278 return ADS_ERROR_KRB5(ret);
1282 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1284 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1285 TALLOC_FREE(principal);
1288 if (principal == NULL &&
1289 !is_ipaddress(cli->desthost) &&
1290 !strequal(STAR_SMBSERVER,
1293 char *machine = NULL;
1295 DEBUG(3,("cli_session_setup_spnego: got a "
1296 "bad server principal, trying to guess ...\n"));
1298 host = strchr_m(cli->desthost, '.');
1300 /* We had a '.' in the name. */
1301 machine = SMB_STRNDUP(cli->desthost,
1302 host - cli->desthost);
1304 machine = SMB_STRDUP(cli->desthost);
1306 if (machine == NULL) {
1307 TALLOC_FREE(principal);
1308 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1312 realm = SMB_STRDUP(dest_realm);
1317 realm = kerberos_get_realm_from_hostname(cli->desthost);
1319 /* NetBIOS name - use our realm. */
1320 realm = kerberos_get_default_realm_from_ccache();
1324 if (realm && *realm) {
1327 principal = talloc_asprintf(talloc_tos(),
1332 /* NetBIOS name, use machine account. */
1333 principal = talloc_asprintf(talloc_tos(),
1341 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1343 DEBUG(3,("cli_session_setup_spnego: guessed "
1344 "server principal=%s\n",
1345 principal ? principal : "<null>"));
1352 rc = cli_session_setup_kerberos(cli, principal,
1354 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1355 TALLOC_FREE(principal);
1362 TALLOC_FREE(principal);
1366 account = talloc_strdup(talloc_tos(), user);
1368 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1371 /* when falling back to ntlmssp while authenticating with a machine
1372 * account strip off the realm - gd */
1374 if ((p = strchr_m(user, '@')) != NULL) {
1375 account[PTR_DIFF(p,user)] = '\0';
1378 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1381 /****************************************************************************
1382 Send a session setup. The username and workgroup is in UNIX character
1383 format and must be converted to DOS codepage format before sending. If the
1384 password is in plaintext, the same should be done.
1385 ****************************************************************************/
1387 NTSTATUS cli_session_setup(struct cli_state *cli,
1389 const char *pass, int passlen,
1390 const char *ntpass, int ntpasslen,
1391 const char *workgroup)
1397 fstrcpy(user2, user);
1406 /* allow for workgroups as part of the username */
1407 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1408 (p=strchr_m(user2,*lp_winbind_separator()))) {
1414 if (cli->protocol < PROTOCOL_LANMAN1) {
1415 return NT_STATUS_OK;
1418 /* now work out what sort of session setup we are going to
1419 do. I have split this into separate functions to make the
1420 flow a bit easier to understand (tridge) */
1422 /* if its an older server then we have to use the older request format */
1424 if (cli->protocol < PROTOCOL_NT1) {
1425 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1426 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1428 return NT_STATUS_ACCESS_DENIED;
1431 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1432 !lp_client_plaintext_auth() && (*pass)) {
1433 DEBUG(1, ("Server requested plaintext password but "
1434 "'client plaintext auth' is disabled\n"));
1435 return NT_STATUS_ACCESS_DENIED;
1438 return cli_session_setup_lanman2(cli, user, pass, passlen,
1442 /* if no user is supplied then we have to do an anonymous connection.
1443 passwords are ignored */
1445 if (!user || !*user)
1446 return cli_session_setup_guest(cli);
1448 /* if the server is share level then send a plaintext null
1449 password at this point. The password is sent in the tree
1452 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1453 return cli_session_setup_plaintext(cli, user, "", workgroup);
1455 /* if the server doesn't support encryption then we have to use
1456 plaintext. The second password is ignored */
1458 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1459 if (!lp_client_plaintext_auth() && (*pass)) {
1460 DEBUG(1, ("Server requested plaintext password but "
1461 "'client plaintext auth' is disabled\n"));
1462 return NT_STATUS_ACCESS_DENIED;
1464 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1467 /* if the server supports extended security then use SPNEGO */
1469 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1470 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1472 if (!ADS_ERR_OK(status)) {
1473 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1474 return ads_ntstatus(status);
1479 /* otherwise do a NT1 style session setup */
1480 status = cli_session_setup_nt1(cli, user, pass, passlen,
1481 ntpass, ntpasslen, workgroup);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 DEBUG(3,("cli_session_setup: NT1 session setup "
1484 "failed: %s\n", nt_errstr(status)));
1489 if (strstr(cli->server_type, "Samba")) {
1490 cli->is_samba = True;
1493 return NT_STATUS_OK;
1496 /****************************************************************************
1498 *****************************************************************************/
1500 struct cli_ulogoff_state {
1501 struct cli_state *cli;
1505 static void cli_ulogoff_done(struct tevent_req *subreq);
1507 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1508 struct tevent_context *ev,
1509 struct cli_state *cli)
1511 struct tevent_req *req, *subreq;
1512 struct cli_ulogoff_state *state;
1514 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1520 SCVAL(state->vwv+0, 0, 0xFF);
1521 SCVAL(state->vwv+1, 0, 0);
1522 SSVAL(state->vwv+2, 0, 0);
1524 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
1526 if (tevent_req_nomem(subreq, req)) {
1527 return tevent_req_post(req, ev);
1529 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1533 static void cli_ulogoff_done(struct tevent_req *subreq)
1535 struct tevent_req *req = tevent_req_callback_data(
1536 subreq, struct tevent_req);
1537 struct cli_ulogoff_state *state = tevent_req_data(
1538 req, struct cli_ulogoff_state);
1541 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 tevent_req_nterror(req, status);
1546 state->cli->vuid = -1;
1547 tevent_req_done(req);
1550 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1552 return tevent_req_simple_recv_ntstatus(req);
1555 NTSTATUS cli_ulogoff(struct cli_state *cli)
1557 struct tevent_context *ev;
1558 struct tevent_req *req;
1559 NTSTATUS status = NT_STATUS_NO_MEMORY;
1561 if (cli_has_async_calls(cli)) {
1562 return NT_STATUS_INVALID_PARAMETER;
1564 ev = tevent_context_init(talloc_tos());
1568 req = cli_ulogoff_send(ev, ev, cli);
1572 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1575 status = cli_ulogoff_recv(req);
1578 if (!NT_STATUS_IS_OK(status)) {
1579 cli_set_error(cli, status);
1584 /****************************************************************************
1586 ****************************************************************************/
1588 struct cli_tcon_andx_state {
1589 struct cli_state *cli;
1594 static void cli_tcon_andx_done(struct tevent_req *subreq);
1596 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1597 struct event_context *ev,
1598 struct cli_state *cli,
1599 const char *share, const char *dev,
1600 const char *pass, int passlen,
1601 struct tevent_req **psmbreq)
1603 struct tevent_req *req, *subreq;
1604 struct cli_tcon_andx_state *state;
1612 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1619 fstrcpy(cli->share, share);
1621 /* in user level security don't send a password now */
1622 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1625 } else if (pass == NULL) {
1626 DEBUG(1, ("Server not using user level security and no "
1627 "password supplied.\n"));
1631 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1632 *pass && passlen != 24) {
1633 if (!lp_client_lanman_auth()) {
1634 DEBUG(1, ("Server requested LANMAN password "
1635 "(share-level security) but "
1636 "'client lanman auth' is disabled\n"));
1641 * Non-encrypted passwords - convert to DOS codepage before
1645 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1647 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1648 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1650 if (!lp_client_plaintext_auth() && (*pass)) {
1651 DEBUG(1, ("Server requested plaintext "
1652 "password but 'client plaintext "
1653 "auth' is disabled\n"));
1658 * Non-encrypted passwords - convert to DOS codepage
1661 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1663 if (passlen == -1) {
1664 DEBUG(1, ("clistr_push(pword) failed\n"));
1669 memcpy(pword, pass, passlen);
1674 SCVAL(vwv+0, 0, 0xFF);
1677 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1678 SSVAL(vwv+3, 0, passlen);
1681 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1683 bytes = talloc_array(state, uint8_t, 0);
1689 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1690 cli->desthost, share);
1695 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1700 * Add the devicetype
1702 tmp = talloc_strdup_upper(talloc_tos(), dev);
1707 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1710 if (bytes == NULL) {
1715 state->bytes.iov_base = (void *)bytes;
1716 state->bytes.iov_len = talloc_get_size(bytes);
1718 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1720 if (subreq == NULL) {
1724 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1729 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1730 return tevent_req_post(req, ev);
1733 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1734 struct event_context *ev,
1735 struct cli_state *cli,
1736 const char *share, const char *dev,
1737 const char *pass, int passlen)
1739 struct tevent_req *req, *subreq;
1742 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1747 if (subreq == NULL) {
1750 status = cli_smb_req_send(subreq);
1751 if (!NT_STATUS_IS_OK(status)) {
1752 tevent_req_nterror(req, status);
1753 return tevent_req_post(req, ev);
1758 static void cli_tcon_andx_done(struct tevent_req *subreq)
1760 struct tevent_req *req = tevent_req_callback_data(
1761 subreq, struct tevent_req);
1762 struct cli_tcon_andx_state *state = tevent_req_data(
1763 req, struct cli_tcon_andx_state);
1764 struct cli_state *cli = state->cli;
1773 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
1774 &num_bytes, &bytes);
1775 TALLOC_FREE(subreq);
1776 if (!NT_STATUS_IS_OK(status)) {
1777 tevent_req_nterror(req, status);
1783 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1784 STR_TERMINATE|STR_ASCII);
1786 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1787 /* almost certainly win95 - enable bug fixes */
1792 * Make sure that we have the optional support 16-bit field. WCT > 2.
1793 * Avoids issues when connecting to Win9x boxes sharing files
1796 cli->dfsroot = false;
1798 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1799 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1802 cli->cnum = SVAL(inbuf,smb_tid);
1803 tevent_req_done(req);
1806 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1808 return tevent_req_simple_recv_ntstatus(req);
1811 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1812 const char *dev, const char *pass, int passlen)
1814 TALLOC_CTX *frame = talloc_stackframe();
1815 struct event_context *ev;
1816 struct tevent_req *req;
1817 NTSTATUS status = NT_STATUS_OK;
1819 if (cli_has_async_calls(cli)) {
1821 * Can't use sync call while an async call is in flight
1823 status = NT_STATUS_INVALID_PARAMETER;
1827 ev = event_context_init(frame);
1829 status = NT_STATUS_NO_MEMORY;
1833 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1835 status = NT_STATUS_NO_MEMORY;
1839 if (!tevent_req_poll(req, ev)) {
1840 status = map_nt_error_from_unix(errno);
1844 status = cli_tcon_andx_recv(req);
1847 if (!NT_STATUS_IS_OK(status)) {
1848 cli_set_error(cli, status);
1853 /****************************************************************************
1854 Send a tree disconnect.
1855 ****************************************************************************/
1857 struct cli_tdis_state {
1858 struct cli_state *cli;
1861 static void cli_tdis_done(struct tevent_req *subreq);
1863 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
1864 struct tevent_context *ev,
1865 struct cli_state *cli)
1867 struct tevent_req *req, *subreq;
1868 struct cli_tdis_state *state;
1870 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
1876 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
1877 if (tevent_req_nomem(subreq, req)) {
1878 return tevent_req_post(req, ev);
1880 tevent_req_set_callback(subreq, cli_tdis_done, req);
1884 static void cli_tdis_done(struct tevent_req *subreq)
1886 struct tevent_req *req = tevent_req_callback_data(
1887 subreq, struct tevent_req);
1888 struct cli_tdis_state *state = tevent_req_data(
1889 req, struct cli_tdis_state);
1892 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1893 TALLOC_FREE(subreq);
1894 if (!NT_STATUS_IS_OK(status)) {
1895 tevent_req_nterror(req, status);
1898 state->cli->cnum = -1;
1899 tevent_req_done(req);
1902 NTSTATUS cli_tdis_recv(struct tevent_req *req)
1904 return tevent_req_simple_recv_ntstatus(req);
1907 NTSTATUS cli_tdis(struct cli_state *cli)
1909 struct tevent_context *ev;
1910 struct tevent_req *req;
1911 NTSTATUS status = NT_STATUS_NO_MEMORY;
1913 if (cli_has_async_calls(cli)) {
1914 return NT_STATUS_INVALID_PARAMETER;
1916 ev = tevent_context_init(talloc_tos());
1920 req = cli_tdis_send(ev, ev, cli);
1924 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1927 status = cli_tdis_recv(req);
1930 if (!NT_STATUS_IS_OK(status)) {
1931 cli_set_error(cli, status);
1936 /****************************************************************************
1937 Send a negprot command.
1938 ****************************************************************************/
1940 void cli_negprot_sendsync(struct cli_state *cli)
1945 if (cli->protocol < PROTOCOL_NT1)
1946 cli->use_spnego = False;
1948 memset(cli->outbuf,'\0',smb_size);
1950 /* setup the protocol strings */
1951 cli_set_message(cli->outbuf,0,0,True);
1953 p = smb_buf(cli->outbuf);
1954 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1955 if (prots[numprots].prot > cli->protocol) {
1959 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1962 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1963 cli_setup_bcc(cli, p);
1964 cli_setup_packet(cli);
1966 SCVAL(smb_buf(cli->outbuf),0,2);
1971 /****************************************************************************
1972 Send a negprot command.
1973 ****************************************************************************/
1975 struct cli_negprot_state {
1976 struct cli_state *cli;
1979 static void cli_negprot_done(struct tevent_req *subreq);
1981 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1982 struct event_context *ev,
1983 struct cli_state *cli)
1985 struct tevent_req *req, *subreq;
1986 struct cli_negprot_state *state;
1987 uint8_t *bytes = NULL;
1991 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1997 if (cli->protocol < PROTOCOL_NT1)
1998 cli->use_spnego = False;
2000 /* setup the protocol strings */
2001 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2003 if (prots[numprots].prot > cli->protocol) {
2006 bytes = (uint8_t *)talloc_append_blob(
2007 state, bytes, data_blob_const(&c, sizeof(c)));
2008 if (tevent_req_nomem(bytes, req)) {
2009 return tevent_req_post(req, ev);
2011 bytes = smb_bytes_push_str(bytes, false,
2012 prots[numprots].name,
2013 strlen(prots[numprots].name)+1,
2015 if (tevent_req_nomem(bytes, req)) {
2016 return tevent_req_post(req, ev);
2023 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2024 talloc_get_size(bytes), bytes);
2027 if (tevent_req_nomem(subreq, req)) {
2028 return tevent_req_post(req, ev);
2030 tevent_req_set_callback(subreq, cli_negprot_done, req);
2034 static void cli_negprot_done(struct tevent_req *subreq)
2036 struct tevent_req *req = tevent_req_callback_data(
2037 subreq, struct tevent_req);
2038 struct cli_negprot_state *state = tevent_req_data(
2039 req, struct cli_negprot_state);
2040 struct cli_state *cli = state->cli;
2049 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2050 &num_bytes, &bytes);
2051 TALLOC_FREE(subreq);
2052 if (!NT_STATUS_IS_OK(status)) {
2053 tevent_req_nterror(req, status);
2057 protnum = SVAL(vwv, 0);
2059 if ((protnum >= ARRAY_SIZE(prots))
2060 || (prots[protnum].prot > cli->protocol)) {
2061 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2065 cli->protocol = prots[protnum].prot;
2067 if ((cli->protocol < PROTOCOL_NT1) &&
2068 client_is_signing_mandatory(cli)) {
2069 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2070 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2074 if (cli->protocol >= PROTOCOL_NT1) {
2076 bool negotiated_smb_signing = false;
2079 cli->sec_mode = CVAL(vwv + 1, 0);
2080 cli->max_mux = SVAL(vwv + 1, 1);
2081 cli->max_xmit = IVAL(vwv + 3, 1);
2082 cli->sesskey = IVAL(vwv + 7, 1);
2083 cli->serverzone = SVALS(vwv + 15, 1);
2084 cli->serverzone *= 60;
2085 /* this time arrives in real GMT */
2086 ts = interpret_long_date(((char *)(vwv+11))+1);
2087 cli->servertime = ts.tv_sec;
2088 cli->secblob = data_blob(bytes, num_bytes);
2089 cli->capabilities = IVAL(vwv + 9, 1);
2090 if (cli->capabilities & CAP_RAW_MODE) {
2091 cli->readbraw_supported = True;
2092 cli->writebraw_supported = True;
2094 /* work out if they sent us a workgroup */
2095 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2096 smb_buflen(cli->inbuf) > 8) {
2097 clistr_pull(cli->inbuf, cli->server_domain,
2098 bytes+8, sizeof(cli->server_domain),
2100 STR_UNICODE|STR_NOALIGN);
2104 * As signing is slow we only turn it on if either the client or
2105 * the server require it. JRA.
2108 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2109 /* Fail if server says signing is mandatory and we don't want to support it. */
2110 if (!client_is_signing_allowed(cli)) {
2111 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2112 tevent_req_nterror(req,
2113 NT_STATUS_ACCESS_DENIED);
2116 negotiated_smb_signing = true;
2117 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2118 /* Fail if client says signing is mandatory and the server doesn't support it. */
2119 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2120 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2121 tevent_req_nterror(req,
2122 NT_STATUS_ACCESS_DENIED);
2125 negotiated_smb_signing = true;
2126 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2127 negotiated_smb_signing = true;
2130 if (negotiated_smb_signing) {
2131 cli_set_signing_negotiated(cli);
2134 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2135 SAFE_FREE(cli->outbuf);
2136 SAFE_FREE(cli->inbuf);
2137 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2138 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2139 if (!cli->outbuf || !cli->inbuf) {
2140 tevent_req_nterror(req,
2141 NT_STATUS_NO_MEMORY);
2144 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2147 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2148 cli->use_spnego = False;
2149 cli->sec_mode = SVAL(vwv + 1, 0);
2150 cli->max_xmit = SVAL(vwv + 2, 0);
2151 cli->max_mux = SVAL(vwv + 3, 0);
2152 cli->sesskey = IVAL(vwv + 6, 0);
2153 cli->serverzone = SVALS(vwv + 10, 0);
2154 cli->serverzone *= 60;
2155 /* this time is converted to GMT by make_unix_date */
2156 cli->servertime = make_unix_date(
2157 (char *)(vwv + 8), cli->serverzone);
2158 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2159 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2160 cli->secblob = data_blob(bytes, num_bytes);
2162 /* the old core protocol */
2163 cli->use_spnego = False;
2165 cli->serverzone = get_time_zone(time(NULL));
2168 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2170 /* a way to force ascii SMB */
2171 if (getenv("CLI_FORCE_ASCII"))
2172 cli->capabilities &= ~CAP_UNICODE;
2174 tevent_req_done(req);
2177 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2179 return tevent_req_simple_recv_ntstatus(req);
2182 NTSTATUS cli_negprot(struct cli_state *cli)
2184 TALLOC_CTX *frame = talloc_stackframe();
2185 struct event_context *ev;
2186 struct tevent_req *req;
2187 NTSTATUS status = NT_STATUS_OK;
2189 if (cli_has_async_calls(cli)) {
2191 * Can't use sync call while an async call is in flight
2193 status = NT_STATUS_INVALID_PARAMETER;
2197 ev = event_context_init(frame);
2199 status = NT_STATUS_NO_MEMORY;
2203 req = cli_negprot_send(frame, ev, cli);
2205 status = NT_STATUS_NO_MEMORY;
2209 if (!tevent_req_poll(req, ev)) {
2210 status = map_nt_error_from_unix(errno);
2214 status = cli_negprot_recv(req);
2217 if (!NT_STATUS_IS_OK(status)) {
2218 cli_set_error(cli, status);
2223 /****************************************************************************
2224 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2225 ****************************************************************************/
2227 bool cli_session_request(struct cli_state *cli,
2228 struct nmb_name *calling, struct nmb_name *called)
2235 /* 445 doesn't have session request */
2236 if (cli->port == 445)
2239 memcpy(&(cli->calling), calling, sizeof(*calling));
2240 memcpy(&(cli->called ), called , sizeof(*called ));
2242 /* put in the destination name */
2244 tmp = name_mangle(talloc_tos(), cli->called.name,
2245 cli->called.name_type);
2250 p = cli->outbuf+len;
2251 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2253 memcpy(p, tmp, namelen);
2260 tmp = name_mangle(talloc_tos(), cli->calling.name,
2261 cli->calling.name_type);
2266 p = cli->outbuf+len;
2267 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2269 memcpy(p, tmp, namelen);
2274 /* send a session request (RFC 1002) */
2275 /* setup the packet length
2276 * Remove four bytes from the length count, since the length
2277 * field in the NBT Session Service header counts the number
2278 * of bytes which follow. The cli_send_smb() function knows
2279 * about this and accounts for those four bytes.
2283 _smb_setlen(cli->outbuf,len);
2284 SCVAL(cli->outbuf,0,0x81);
2287 DEBUG(5,("Sent session request\n"));
2289 if (!cli_receive_smb(cli))
2292 if (CVAL(cli->inbuf,0) == 0x84) {
2293 /* C. Hoch 9/14/95 Start */
2294 /* For information, here is the response structure.
2295 * We do the byte-twiddling to for portability.
2296 struct RetargetResponse{
2298 unsigned char flags;
2304 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2305 struct in_addr dest_ip;
2308 /* SESSION RETARGET */
2309 putip((char *)&dest_ip,cli->inbuf+4);
2310 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2312 status = open_socket_out(&cli->dest_ss, port,
2313 LONG_CONNECT_TIMEOUT, &cli->fd);
2314 if (!NT_STATUS_IS_OK(status)) {
2318 DEBUG(3,("Retargeted\n"));
2320 set_socket_options(cli->fd, lp_socket_options());
2327 DEBUG(0,("Retarget recursion - failing\n"));
2331 ret = cli_session_request(cli, calling, called);
2335 } /* C. Hoch 9/14/95 End */
2337 if (CVAL(cli->inbuf,0) != 0x82) {
2338 /* This is the wrong place to put the error... JRA. */
2339 cli->rap_error = CVAL(cli->inbuf,4);
2349 static void smb_sock_connected(struct tevent_req *req)
2351 struct fd_struct *pfd = tevent_req_callback_data(
2352 req, struct fd_struct);
2356 status = open_socket_out_defer_recv(req, &fd);
2357 if (NT_STATUS_IS_OK(status)) {
2362 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2363 uint16_t *port, int timeout, int *pfd)
2365 struct event_context *ev;
2366 struct tevent_req *r139, *r445;
2367 struct fd_struct *fd139, *fd445;
2368 NTSTATUS status = NT_STATUS_NO_MEMORY;
2371 return open_socket_out(pss, *port, timeout, pfd);
2374 ev = event_context_init(talloc_tos());
2376 return NT_STATUS_NO_MEMORY;
2379 fd139 = talloc(ev, struct fd_struct);
2380 if (fd139 == NULL) {
2385 fd445 = talloc(ev, struct fd_struct);
2386 if (fd445 == NULL) {
2391 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2393 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2395 if ((r445 == NULL) || (r139 == NULL)) {
2398 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2399 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2401 while ((fd445->fd == -1) && (fd139->fd == -1)
2402 && (tevent_req_is_in_progress(r139)
2403 || tevent_req_is_in_progress(r445))) {
2404 event_loop_once(ev);
2407 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2412 if (fd445->fd != -1) {
2415 status = NT_STATUS_OK;
2418 if (fd139->fd != -1) {
2421 status = NT_STATUS_OK;
2425 status = open_socket_out_defer_recv(r445, &fd445->fd);
2431 /****************************************************************************
2432 Open the client sockets.
2433 ****************************************************************************/
2435 NTSTATUS cli_connect(struct cli_state *cli,
2437 struct sockaddr_storage *dest_ss)
2440 int name_type = 0x20;
2441 TALLOC_CTX *frame = talloc_stackframe();
2442 unsigned int num_addrs = 0;
2444 struct sockaddr_storage *ss_arr = NULL;
2447 /* reasonable default hostname */
2449 host = STAR_SMBSERVER;
2452 fstrcpy(cli->desthost, host);
2454 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2455 if ((p = strchr(cli->desthost, '#'))) {
2456 name_type = strtol(p+1, NULL, 16);
2460 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2461 NTSTATUS status =resolve_name_list(frame,
2466 if (!NT_STATUS_IS_OK(status)) {
2468 return NT_STATUS_BAD_NETWORK_NAME;
2472 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2475 return NT_STATUS_NO_MEMORY;
2480 for (i = 0; i < num_addrs; i++) {
2481 cli->dest_ss = ss_arr[i];
2482 if (getenv("LIBSMB_PROG")) {
2483 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2485 uint16_t port = cli->port;
2487 status = open_smb_socket(&cli->dest_ss, &port,
2488 cli->timeout, &cli->fd);
2489 if (NT_STATUS_IS_OK(status)) {
2493 if (cli->fd == -1) {
2494 char addr[INET6_ADDRSTRLEN];
2495 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2496 DEBUG(2,("Error connecting to %s (%s)\n",
2497 dest_ss?addr:host,strerror(errno)));
2499 /* Exit from loop on first connection. */
2504 if (cli->fd == -1) {
2506 return map_nt_error_from_unix(errno);
2510 *dest_ss = cli->dest_ss;
2513 set_socket_options(cli->fd, lp_socket_options());
2516 return NT_STATUS_OK;
2520 establishes a connection to after the negprot.
2521 @param output_cli A fully initialised cli structure, non-null only on success
2522 @param dest_host The netbios name of the remote host
2523 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2524 @param port (optional) The destination port (0 for default)
2525 @param retry bool. Did this connection fail with a retryable error ?
2528 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2529 const char *my_name,
2530 const char *dest_host,
2531 struct sockaddr_storage *dest_ss, int port,
2532 int signing_state, int flags,
2536 struct nmb_name calling;
2537 struct nmb_name called;
2538 struct cli_state *cli;
2539 struct sockaddr_storage ss;
2545 my_name = global_myname();
2547 if (!(cli = cli_initialise_ex(signing_state))) {
2548 return NT_STATUS_NO_MEMORY;
2551 make_nmb_name(&calling, my_name, 0x0);
2552 make_nmb_name(&called , dest_host, 0x20);
2554 cli_set_port(cli, port);
2555 cli_set_timeout(cli, 10000); /* 10 seconds. */
2565 DEBUG(3,("Connecting to host=%s\n", dest_host));
2567 nt_status = cli_connect(cli, dest_host, &ss);
2568 if (!NT_STATUS_IS_OK(nt_status)) {
2569 char addr[INET6_ADDRSTRLEN];
2570 print_sockaddr(addr, sizeof(addr), &ss);
2571 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2572 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2580 if (!cli_session_request(cli, &calling, &called)) {
2582 DEBUG(1,("session request to %s failed (%s)\n",
2583 called.name, cli_errstr(cli)));
2584 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2588 if (strcmp(called.name, STAR_SMBSERVER)) {
2589 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2592 return NT_STATUS_BAD_NETWORK_NAME;
2595 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2596 cli->use_spnego = False;
2597 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2598 cli->use_kerberos = True;
2600 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2601 cli->use_kerberos) {
2602 cli->fallback_after_kerberos = true;
2604 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2605 cli->use_ccache = true;
2608 nt_status = cli_negprot(cli);
2609 if (!NT_STATUS_IS_OK(nt_status)) {
2610 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2616 return NT_STATUS_OK;
2621 establishes a connection right up to doing tconX, password specified.
2622 @param output_cli A fully initialised cli structure, non-null only on success
2623 @param dest_host The netbios name of the remote host
2624 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2625 @param port (optional) The destination port (0 for default)
2626 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2627 @param service_type The 'type' of serivice.
2628 @param user Username, unix string
2629 @param domain User's domain
2630 @param password User's password, unencrypted unix string.
2631 @param retry bool. Did this connection fail with a retryable error ?
2634 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2635 const char *my_name,
2636 const char *dest_host,
2637 struct sockaddr_storage *dest_ss, int port,
2638 const char *service, const char *service_type,
2639 const char *user, const char *domain,
2640 const char *password, int flags,
2645 struct cli_state *cli = NULL;
2646 int pw_len = password ? strlen(password)+1 : 0;
2650 if (password == NULL) {
2654 nt_status = cli_start_connection(&cli, my_name, dest_host,
2655 dest_ss, port, signing_state,
2658 if (!NT_STATUS_IS_OK(nt_status)) {
2662 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2663 cli->use_level_II_oplocks =
2664 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2666 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2668 if (!NT_STATUS_IS_OK(nt_status)) {
2670 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2671 DEBUG(1,("failed session setup with %s\n",
2672 nt_errstr(nt_status)));
2677 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2678 if (!NT_STATUS_IS_OK(nt_status)) {
2679 DEBUG(1,("anonymous failed session setup with %s\n",
2680 nt_errstr(nt_status)));
2687 nt_status = cli_tcon_andx(cli, service, service_type, password,
2689 if (!NT_STATUS_IS_OK(nt_status)) {
2690 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2692 if (NT_STATUS_IS_OK(nt_status)) {
2693 nt_status = NT_STATUS_UNSUCCESSFUL;
2699 nt_status = cli_init_creds(cli, user, domain, password);
2700 if (!NT_STATUS_IS_OK(nt_status)) {
2706 return NT_STATUS_OK;
2709 /****************************************************************************
2710 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2711 ****************************************************************************/
2713 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2714 struct sockaddr_storage *pdest_ss)
2716 struct nmb_name calling, called;
2718 make_nmb_name(&calling, srchost, 0x0);
2721 * If the called name is an IP address
2722 * then use *SMBSERVER immediately.
2725 if(is_ipaddress(desthost)) {
2726 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2728 make_nmb_name(&called, desthost, 0x20);
2731 if (!cli_session_request(*ppcli, &calling, &called)) {
2733 struct nmb_name smbservername;
2735 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2738 * If the name wasn't *SMBSERVER then
2739 * try with *SMBSERVER if the first name fails.
2742 if (nmb_name_equal(&called, &smbservername)) {
2745 * The name used was *SMBSERVER, don't bother with another name.
2748 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2749 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2754 cli_shutdown(*ppcli);
2756 *ppcli = cli_initialise();
2758 /* Out of memory... */
2762 status = cli_connect(*ppcli, desthost, pdest_ss);
2763 if (!NT_STATUS_IS_OK(status) ||
2764 !cli_session_request(*ppcli, &calling, &smbservername)) {
2765 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2766 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2774 /****************************************************************************
2775 Send an old style tcon.
2776 ****************************************************************************/
2777 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2778 const char *service, const char *pass, const char *dev,
2779 uint16 *max_xmit, uint16 *tid)
2783 if (!lp_client_plaintext_auth() && (*pass)) {
2784 DEBUG(1, ("Server requested plaintext password but 'client "
2785 "plaintext auth' is disabled\n"));
2786 return NT_STATUS_ACCESS_DENIED;
2789 memset(cli->outbuf,'\0',smb_size);
2790 memset(cli->inbuf,'\0',smb_size);
2792 cli_set_message(cli->outbuf, 0, 0, True);
2793 SCVAL(cli->outbuf,smb_com,SMBtcon);
2794 cli_setup_packet(cli);
2796 p = smb_buf(cli->outbuf);
2797 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2798 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2799 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2801 cli_setup_bcc(cli, p);
2804 if (!cli_receive_smb(cli)) {
2805 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2808 if (cli_is_error(cli)) {
2809 return cli_nt_error(cli);
2812 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2813 *tid = SVAL(cli->inbuf, smb_vwv1);
2815 return NT_STATUS_OK;
2818 /* Return a cli_state pointing at the IPC$ share for the given server */
2820 struct cli_state *get_ipc_connect(char *server,
2821 struct sockaddr_storage *server_ss,
2822 const struct user_auth_info *user_info)
2824 struct cli_state *cli;
2826 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2828 if (user_info->use_kerberos) {
2829 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2832 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2833 user_info->username ? user_info->username : "",
2835 user_info->password ? user_info->password : "",
2839 if (NT_STATUS_IS_OK(nt_status)) {
2841 } else if (is_ipaddress(server)) {
2842 /* windows 9* needs a correct NMB name for connections */
2843 fstring remote_name;
2845 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2846 cli = get_ipc_connect(remote_name, server_ss, user_info);
2855 * Given the IP address of a master browser on the network, return its
2856 * workgroup and connect to it.
2858 * This function is provided to allow additional processing beyond what
2859 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2860 * browsers and obtain each master browsers' list of domains (in case the
2861 * first master browser is recently on the network and has not yet
2862 * synchronized with other master browsers and therefore does not yet have the
2863 * entire network browse list)
2866 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2867 struct ip_service *mb_ip,
2868 const struct user_auth_info *user_info,
2869 char **pp_workgroup_out)
2871 char addr[INET6_ADDRSTRLEN];
2873 struct cli_state *cli;
2874 struct sockaddr_storage server_ss;
2876 *pp_workgroup_out = NULL;
2878 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2879 DEBUG(99, ("Looking up name of master browser %s\n",
2883 * Do a name status query to find out the name of the master browser.
2884 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2885 * master browser will not respond to a wildcard query (or, at least,
2886 * an NT4 server acting as the domain master browser will not).
2888 * We might be able to use ONLY the query on MSBROWSE, but that's not
2889 * yet been tested with all Windows versions, so until it is, leave
2890 * the original wildcard query as the first choice and fall back to
2891 * MSBROWSE if the wildcard query fails.
2893 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2894 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2896 DEBUG(99, ("Could not retrieve name status for %s\n",
2901 if (!find_master_ip(name, &server_ss)) {
2902 DEBUG(99, ("Could not find master ip for %s\n", name));
2906 *pp_workgroup_out = talloc_strdup(ctx, name);
2908 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2910 print_sockaddr(addr, sizeof(addr), &server_ss);
2911 cli = get_ipc_connect(addr, &server_ss, user_info);
2917 * Return the IP address and workgroup of a master browser on the network, and
2921 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2922 const struct user_auth_info *user_info,
2923 char **pp_workgroup_out)
2925 struct ip_service *ip_list;
2926 struct cli_state *cli;
2929 *pp_workgroup_out = NULL;
2931 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2933 /* Go looking for workgroups by broadcasting on the local network */
2935 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2937 DEBUG(99, ("No master browsers responded\n"));
2941 for (i = 0; i < count; i++) {
2942 char addr[INET6_ADDRSTRLEN];
2943 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2944 DEBUG(99, ("Found master browser %s\n", addr));
2946 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2947 user_info, pp_workgroup_out);