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"
34 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
35 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
36 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
37 {PROTOCOL_LANMAN1, "LANMAN1.0"},
38 {PROTOCOL_LANMAN2, "LM1.2X002"},
39 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
40 {PROTOCOL_LANMAN2, "LANMAN2.1"},
41 {PROTOCOL_LANMAN2, "Samba"},
42 {PROTOCOL_NT1, "NT LANMAN 1.0"},
43 {PROTOCOL_NT1, "NT LM 0.12"},
46 #define STAR_SMBSERVER "*SMBSERVER"
49 * Set the user session key for a connection
50 * @param cli The cli structure to add it too
51 * @param session_key The session key used. (A copy of this is taken for the cli struct)
55 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
57 cli->user_session_key = data_blob(session_key.data, session_key.length);
60 /****************************************************************************
61 Do an old lanman2 style session setup.
62 ****************************************************************************/
64 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
66 const char *pass, size_t passlen,
67 const char *workgroup)
69 DATA_BLOB session_key = data_blob_null;
70 DATA_BLOB lm_response = data_blob_null;
75 if (passlen > sizeof(pword)-1) {
76 return NT_STATUS_INVALID_PARAMETER;
79 /* LANMAN servers predate NT status codes and Unicode and ignore those
80 smb flags so we must disable the corresponding default capabilities
81 that would otherwise cause the Unicode and NT Status flags to be
82 set (and even returned by the server) */
84 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
86 /* if in share level security then don't send a password now */
87 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
90 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
91 /* Encrypted mode needed, and non encrypted password supplied. */
92 lm_response = data_blob(NULL, 24);
93 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
94 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
95 return NT_STATUS_ACCESS_DENIED;
97 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
98 /* Encrypted mode needed, and encrypted password supplied. */
99 lm_response = data_blob(pass, passlen);
100 } else if (passlen > 0) {
101 /* Plaintext mode needed, assume plaintext supplied. */
102 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
103 lm_response = data_blob(pass, passlen);
106 /* send a session setup command */
107 memset(cli->outbuf,'\0',smb_size);
108 cli_set_message(cli->outbuf,10, 0, True);
109 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
110 cli_setup_packet(cli);
112 SCVAL(cli->outbuf,smb_vwv0,0xFF);
113 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
114 SSVAL(cli->outbuf,smb_vwv3,2);
115 SSVAL(cli->outbuf,smb_vwv4,1);
116 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
117 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
119 p = smb_buf(cli->outbuf);
120 memcpy(p,lm_response.data,lm_response.length);
121 p += lm_response.length;
122 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
123 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
124 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
125 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
126 cli_setup_bcc(cli, p);
128 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
129 return cli_nt_error(cli);
132 show_msg(cli->inbuf);
134 if (cli_is_error(cli)) {
135 return cli_nt_error(cli);
138 /* use the returned vuid from now on */
139 cli->vuid = SVAL(cli->inbuf,smb_uid);
140 status = cli_set_username(cli, user);
141 if (!NT_STATUS_IS_OK(status)) {
145 if (session_key.data) {
146 /* Have plaintext orginal */
147 cli_set_session_key(cli, session_key);
153 /****************************************************************************
154 Work out suitable capabilities to offer the server.
155 ****************************************************************************/
157 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
159 uint32 capabilities = CAP_NT_SMBS;
161 if (!cli->force_dos_errors)
162 capabilities |= CAP_STATUS32;
164 if (cli->use_level_II_oplocks)
165 capabilities |= CAP_LEVEL_II_OPLOCKS;
167 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
171 /****************************************************************************
172 Do a NT1 guest session setup.
173 ****************************************************************************/
175 struct cli_session_setup_guest_state {
176 struct cli_state *cli;
181 static void cli_session_setup_guest_done(struct tevent_req *subreq);
183 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
184 struct event_context *ev,
185 struct cli_state *cli,
186 struct tevent_req **psmbreq)
188 struct tevent_req *req, *subreq;
189 struct cli_session_setup_guest_state *state;
193 req = tevent_req_create(mem_ctx, &state,
194 struct cli_session_setup_guest_state);
201 SCVAL(vwv+0, 0, 0xFF);
204 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
206 SSVAL(vwv+4, 0, cli->pid);
207 SIVAL(vwv+5, 0, cli->sesskey);
212 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
214 bytes = talloc_array(state, uint8_t, 0);
216 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
218 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
220 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
221 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
228 state->bytes.iov_base = (void *)bytes;
229 state->bytes.iov_len = talloc_get_size(bytes);
231 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
233 if (subreq == NULL) {
237 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
242 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
243 struct event_context *ev,
244 struct cli_state *cli)
246 struct tevent_req *req, *subreq;
249 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
254 status = cli_smb_req_send(subreq);
255 if (NT_STATUS_IS_OK(status)) {
256 tevent_req_nterror(req, status);
257 return tevent_req_post(req, ev);
262 static void cli_session_setup_guest_done(struct tevent_req *subreq)
264 struct tevent_req *req = tevent_req_callback_data(
265 subreq, struct tevent_req);
266 struct cli_session_setup_guest_state *state = tevent_req_data(
267 req, struct cli_session_setup_guest_state);
268 struct cli_state *cli = state->cli;
276 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
279 if (!NT_STATUS_IS_OK(status)) {
280 tevent_req_nterror(req, status);
287 cli->vuid = SVAL(inbuf, smb_uid);
289 p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
290 bytes+num_bytes-p, STR_TERMINATE);
291 p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
292 bytes+num_bytes-p, STR_TERMINATE);
293 p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
294 bytes+num_bytes-p, STR_TERMINATE);
296 if (strstr(cli->server_type, "Samba")) {
297 cli->is_samba = True;
300 status = cli_set_username(cli, "");
301 if (!NT_STATUS_IS_OK(status)) {
302 tevent_req_nterror(req, status);
305 tevent_req_done(req);
308 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
310 return tevent_req_simple_recv_ntstatus(req);
313 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
315 TALLOC_CTX *frame = talloc_stackframe();
316 struct event_context *ev;
317 struct tevent_req *req;
318 NTSTATUS status = NT_STATUS_OK;
320 if (cli_has_async_calls(cli)) {
322 * Can't use sync call while an async call is in flight
324 status = NT_STATUS_INVALID_PARAMETER;
328 ev = event_context_init(frame);
330 status = NT_STATUS_NO_MEMORY;
334 req = cli_session_setup_guest_send(frame, ev, cli);
336 status = NT_STATUS_NO_MEMORY;
340 if (!tevent_req_poll(req, ev)) {
341 status = map_nt_error_from_unix(errno);
345 status = cli_session_setup_guest_recv(req);
348 if (!NT_STATUS_IS_OK(status)) {
349 cli_set_error(cli, status);
354 /****************************************************************************
355 Do a NT1 plaintext session setup.
356 ****************************************************************************/
358 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
359 const char *user, const char *pass,
360 const char *workgroup)
362 uint32 capabilities = cli_session_setup_capabilities(cli);
367 fstr_sprintf( lanman, "Samba %s", samba_version_string());
369 memset(cli->outbuf, '\0', smb_size);
370 cli_set_message(cli->outbuf,13,0,True);
371 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
372 cli_setup_packet(cli);
374 SCVAL(cli->outbuf,smb_vwv0,0xFF);
375 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
376 SSVAL(cli->outbuf,smb_vwv3,2);
377 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
378 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
379 SSVAL(cli->outbuf,smb_vwv8,0);
380 SIVAL(cli->outbuf,smb_vwv11,capabilities);
381 p = smb_buf(cli->outbuf);
383 /* check wether to send the ASCII or UNICODE version of the password */
385 if ( (capabilities & CAP_UNICODE) == 0 ) {
386 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
387 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
390 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
391 * the space taken by the unicode password to be one byte too
392 * long (as we're on an odd byte boundary here). Reduce the
393 * count by 1 to cope with this. Fixes smbclient against NetApp
394 * servers which can't cope. Fix from
395 * bryan.kolodziej@allenlund.com in bug #3840.
397 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
398 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
401 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
402 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
403 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
404 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
405 cli_setup_bcc(cli, p);
407 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
408 return cli_nt_error(cli);
411 show_msg(cli->inbuf);
413 if (cli_is_error(cli)) {
414 return cli_nt_error(cli);
417 cli->vuid = SVAL(cli->inbuf,smb_uid);
418 p = smb_buf(cli->inbuf);
419 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
421 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
423 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
425 status = cli_set_username(cli, user);
426 if (!NT_STATUS_IS_OK(status)) {
429 if (strstr(cli->server_type, "Samba")) {
430 cli->is_samba = True;
436 /****************************************************************************
437 do a NT1 NTLM/LM encrypted session setup - for when extended security
439 @param cli client state to create do session setup on
441 @param pass *either* cleartext password (passlen !=24) or LM response.
442 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
443 @param workgroup The user's domain.
444 ****************************************************************************/
446 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
447 const char *pass, size_t passlen,
448 const char *ntpass, size_t ntpasslen,
449 const char *workgroup)
451 uint32 capabilities = cli_session_setup_capabilities(cli);
452 DATA_BLOB lm_response = data_blob_null;
453 DATA_BLOB nt_response = data_blob_null;
454 DATA_BLOB session_key = data_blob_null;
460 /* do nothing - guest login */
461 } else if (passlen != 24) {
462 if (lp_client_ntlmv2_auth()) {
463 DATA_BLOB server_chal;
464 DATA_BLOB names_blob;
465 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
467 /* note that the 'workgroup' here is a best guess - we don't know
468 the server's domain at this point. The 'server name' is also
471 names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup);
473 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal,
475 &lm_response, &nt_response, NULL, &session_key)) {
476 data_blob_free(&names_blob);
477 data_blob_free(&server_chal);
478 return NT_STATUS_ACCESS_DENIED;
480 data_blob_free(&names_blob);
481 data_blob_free(&server_chal);
485 E_md4hash(pass, nt_hash);
488 nt_response = data_blob_null;
490 nt_response = data_blob(NULL, 24);
491 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
493 /* non encrypted password supplied. Ignore ntpass. */
494 if (lp_client_lanman_auth()) {
495 lm_response = data_blob(NULL, 24);
496 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
497 /* Oops, the LM response is invalid, just put
498 the NT response there instead */
499 data_blob_free(&lm_response);
500 lm_response = data_blob(nt_response.data, nt_response.length);
503 /* LM disabled, place NT# in LM field instead */
504 lm_response = data_blob(nt_response.data, nt_response.length);
507 session_key = data_blob(NULL, 16);
509 E_deshash(pass, session_key.data);
510 memset(&session_key.data[8], '\0', 8);
512 SMBsesskeygen_ntv1(nt_hash, session_key.data);
515 cli_temp_set_signing(cli);
517 /* pre-encrypted password supplied. Only used for
518 security=server, can't do
519 signing because we don't have original key */
521 lm_response = data_blob(pass, passlen);
522 nt_response = data_blob(ntpass, ntpasslen);
525 /* send a session setup command */
526 memset(cli->outbuf,'\0',smb_size);
528 cli_set_message(cli->outbuf,13,0,True);
529 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
530 cli_setup_packet(cli);
532 SCVAL(cli->outbuf,smb_vwv0,0xFF);
533 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
534 SSVAL(cli->outbuf,smb_vwv3,2);
535 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
536 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
537 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
538 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
539 SIVAL(cli->outbuf,smb_vwv11,capabilities);
540 p = smb_buf(cli->outbuf);
541 if (lm_response.length) {
542 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
544 if (nt_response.length) {
545 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
547 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
549 /* Upper case here might help some NTLMv2 implementations */
550 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
551 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
552 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
553 cli_setup_bcc(cli, p);
555 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
556 result = cli_nt_error(cli);
560 /* show_msg(cli->inbuf); */
562 if (cli_is_error(cli)) {
563 result = cli_nt_error(cli);
568 ok = cli_simple_set_signing(cli, session_key, lm_response);
570 ok = cli_simple_set_signing(cli, session_key, nt_response);
573 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
574 result = NT_STATUS_ACCESS_DENIED;
579 /* use the returned vuid from now on */
580 cli->vuid = SVAL(cli->inbuf,smb_uid);
582 p = smb_buf(cli->inbuf);
583 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
585 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
587 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
590 if (strstr(cli->server_type, "Samba")) {
591 cli->is_samba = True;
594 result = cli_set_username(cli, user);
595 if (!NT_STATUS_IS_OK(result)) {
599 if (session_key.data) {
600 /* Have plaintext orginal */
601 cli_set_session_key(cli, session_key);
604 result = NT_STATUS_OK;
606 data_blob_free(&lm_response);
607 data_blob_free(&nt_response);
608 data_blob_free(&session_key);
612 /* The following is calculated from :
614 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
615 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
619 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
621 struct cli_sesssetup_blob_state {
622 struct tevent_context *ev;
623 struct cli_state *cli;
625 uint16_t max_blob_size;
634 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
635 struct tevent_req **psubreq);
636 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
638 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
639 struct tevent_context *ev,
640 struct cli_state *cli,
643 struct tevent_req *req, *subreq;
644 struct cli_sesssetup_blob_state *state;
646 req = tevent_req_create(mem_ctx, &state,
647 struct cli_sesssetup_blob_state);
655 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
656 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
657 "(was %u, need minimum %u)\n",
658 (unsigned int)cli->max_xmit,
659 BASE_SESSSETUP_BLOB_PACKET_SIZE));
660 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
661 return tevent_req_post(req, ev);
663 state->max_blob_size =
664 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
666 if (!cli_sesssetup_blob_next(state, &subreq)) {
667 tevent_req_nomem(NULL, req);
668 return tevent_req_post(req, ev);
670 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
674 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
675 struct tevent_req **psubreq)
677 struct tevent_req *subreq;
680 SCVAL(state->vwv+0, 0, 0xFF);
681 SCVAL(state->vwv+0, 1, 0);
682 SSVAL(state->vwv+1, 0, 0);
683 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
684 SSVAL(state->vwv+3, 0, 2);
685 SSVAL(state->vwv+4, 0, 1);
686 SIVAL(state->vwv+5, 0, 0);
688 thistime = MIN(state->blob.length, state->max_blob_size);
689 SSVAL(state->vwv+7, 0, thistime);
691 SSVAL(state->vwv+8, 0, 0);
692 SSVAL(state->vwv+9, 0, 0);
693 SIVAL(state->vwv+10, 0,
694 cli_session_setup_capabilities(state->cli)
695 | CAP_EXTENDED_SECURITY);
697 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
699 if (state->buf == NULL) {
702 state->blob.data += thistime;
703 state->blob.length -= thistime;
705 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
707 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
709 if (state->buf == NULL) {
712 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
714 talloc_get_size(state->buf), state->buf);
715 if (subreq == NULL) {
722 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
724 struct tevent_req *req = tevent_req_callback_data(
725 subreq, struct tevent_req);
726 struct cli_sesssetup_blob_state *state = tevent_req_data(
727 req, struct cli_sesssetup_blob_state);
728 struct cli_state *cli = state->cli;
735 uint16_t blob_length;
738 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
741 if (!NT_STATUS_IS_OK(status)
742 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
743 tevent_req_nterror(req, status);
747 state->status = status;
748 TALLOC_FREE(state->buf);
750 state->inbuf = (char *)inbuf;
751 cli->vuid = SVAL(state->inbuf, smb_uid);
753 blob_length = SVAL(vwv+3, 0);
754 if (blob_length > num_bytes) {
755 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
758 state->ret_blob = data_blob_const(bytes, blob_length);
760 p = bytes + blob_length;
762 p += clistr_pull(state->inbuf, cli->server_os,
763 (char *)p, sizeof(fstring),
764 bytes+num_bytes-p, STR_TERMINATE);
765 p += clistr_pull(state->inbuf, cli->server_type,
766 (char *)p, sizeof(fstring),
767 bytes+num_bytes-p, STR_TERMINATE);
768 p += clistr_pull(state->inbuf, cli->server_domain,
769 (char *)p, sizeof(fstring),
770 bytes+num_bytes-p, STR_TERMINATE);
772 if (strstr(cli->server_type, "Samba")) {
773 cli->is_samba = True;
776 if (state->blob.length != 0) {
780 if (!cli_sesssetup_blob_next(state, &subreq)) {
781 tevent_req_nomem(NULL, req);
784 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
787 tevent_req_done(req);
790 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
795 struct cli_sesssetup_blob_state *state = tevent_req_data(
796 req, struct cli_sesssetup_blob_state);
800 if (tevent_req_is_nterror(req, &status)) {
801 state->cli->vuid = 0;
805 inbuf = talloc_move(mem_ctx, &state->inbuf);
807 *pblob = state->ret_blob;
809 if (pinbuf != NULL) {
812 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
813 return state->status;
818 /****************************************************************************
819 Use in-memory credentials cache
820 ****************************************************************************/
822 static void use_in_memory_ccache(void) {
823 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
826 /****************************************************************************
827 Do a spnego/kerberos encrypted session setup.
828 ****************************************************************************/
830 struct cli_session_setup_kerberos_state {
831 struct cli_state *cli;
832 DATA_BLOB negTokenTarg;
833 DATA_BLOB session_key_krb5;
834 ADS_STATUS ads_status;
837 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
839 static struct tevent_req *cli_session_setup_kerberos_send(
840 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
841 const char *principal, const char *workgroup)
843 struct tevent_req *req, *subreq;
844 struct cli_session_setup_kerberos_state *state;
847 DEBUG(2,("Doing kerberos session setup\n"));
849 req = tevent_req_create(mem_ctx, &state,
850 struct cli_session_setup_kerberos_state);
855 state->ads_status = ADS_SUCCESS;
857 cli_temp_set_signing(cli);
860 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
861 * we have to acquire a ticket. To be fixed later :-)
863 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
864 &state->session_key_krb5, 0, NULL);
866 DEBUG(1, ("cli_session_setup_kerberos: "
867 "spnego_gen_krb5_negTokenInit failed: %s\n",
869 state->ads_status = ADS_ERROR_KRB5(rc);
870 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
871 return tevent_req_post(req, ev);
875 file_save("negTokenTarg.dat", state->negTokenTarg.data,
876 state->negTokenTarg.length);
879 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
880 if (tevent_req_nomem(subreq, req)) {
881 return tevent_req_post(req, ev);
883 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
887 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
889 struct tevent_req *req = tevent_req_callback_data(
890 subreq, struct tevent_req);
891 struct cli_session_setup_kerberos_state *state = tevent_req_data(
892 req, struct cli_session_setup_kerberos_state);
896 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
897 if (!NT_STATUS_IS_OK(status)) {
899 tevent_req_nterror(req, status);
903 cli_set_session_key(state->cli, state->session_key_krb5);
905 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
907 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
909 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
913 tevent_req_done(req);
916 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
918 struct cli_session_setup_kerberos_state *state = tevent_req_data(
919 req, struct cli_session_setup_kerberos_state);
922 if (tevent_req_is_nterror(req, &status)) {
923 return ADS_ERROR_NT(status);
925 return state->ads_status;
928 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
929 const char *principal,
930 const char *workgroup)
932 struct tevent_context *ev;
933 struct tevent_req *req;
934 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
936 if (cli_has_async_calls(cli)) {
937 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
939 ev = tevent_context_init(talloc_tos());
943 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
948 if (!tevent_req_poll(req, ev)) {
949 status = ADS_ERROR_SYSTEM(errno);
952 status = cli_session_setup_kerberos_recv(req);
957 #endif /* HAVE_KRB5 */
959 /****************************************************************************
960 Do a spnego/NTLMSSP encrypted session setup.
961 ****************************************************************************/
963 struct cli_session_setup_ntlmssp_state {
964 struct tevent_context *ev;
965 struct cli_state *cli;
966 struct ntlmssp_state *ntlmssp_state;
971 static int cli_session_setup_ntlmssp_state_destructor(
972 struct cli_session_setup_ntlmssp_state *state)
974 if (state->ntlmssp_state != NULL) {
975 TALLOC_FREE(state->ntlmssp_state);
980 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
982 static struct tevent_req *cli_session_setup_ntlmssp_send(
983 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
984 const char *user, const char *pass, const char *domain)
986 struct tevent_req *req, *subreq;
987 struct cli_session_setup_ntlmssp_state *state;
990 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
992 req = tevent_req_create(mem_ctx, &state,
993 struct cli_session_setup_ntlmssp_state);
1001 state->ntlmssp_state = NULL;
1002 talloc_set_destructor(
1003 state, cli_session_setup_ntlmssp_state_destructor);
1005 cli_temp_set_signing(cli);
1007 status = ntlmssp_client_start(state,
1010 lp_client_ntlmv2_auth(),
1011 &state->ntlmssp_state);
1012 if (!NT_STATUS_IS_OK(status)) {
1015 ntlmssp_want_feature(state->ntlmssp_state,
1016 NTLMSSP_FEATURE_SESSION_KEY);
1017 if (cli->use_ccache) {
1018 ntlmssp_want_feature(state->ntlmssp_state,
1019 NTLMSSP_FEATURE_CCACHE);
1021 status = ntlmssp_set_username(state->ntlmssp_state, user);
1022 if (!NT_STATUS_IS_OK(status)) {
1025 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1026 if (!NT_STATUS_IS_OK(status)) {
1029 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1030 if (!NT_STATUS_IS_OK(status)) {
1033 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1035 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1039 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1040 data_blob_free(&blob_out);
1042 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1043 if (tevent_req_nomem(subreq, req)) {
1044 return tevent_req_post(req, ev);
1046 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1049 tevent_req_nterror(req, status);
1050 return tevent_req_post(req, ev);
1053 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1055 struct tevent_req *req = tevent_req_callback_data(
1056 subreq, struct tevent_req);
1057 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1058 req, struct cli_session_setup_ntlmssp_state);
1059 DATA_BLOB blob_in, msg_in, blob_out;
1064 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1066 TALLOC_FREE(subreq);
1067 data_blob_free(&state->blob_out);
1069 if (NT_STATUS_IS_OK(status)) {
1070 if (state->cli->server_domain[0] == '\0') {
1071 fstrcpy(state->cli->server_domain,
1072 state->ntlmssp_state->server.netbios_domain);
1074 cli_set_session_key(
1075 state->cli, state->ntlmssp_state->session_key);
1077 if (cli_simple_set_signing(
1078 state->cli, state->ntlmssp_state->session_key,
1080 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1081 TALLOC_FREE(subreq);
1082 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1085 TALLOC_FREE(subreq);
1086 TALLOC_FREE(state->ntlmssp_state);
1087 tevent_req_done(req);
1090 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1091 tevent_req_nterror(req, status);
1095 if (blob_in.length == 0) {
1096 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1100 if ((state->turn == 1)
1101 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1102 DATA_BLOB tmp_blob = data_blob_null;
1103 /* the server might give us back two challenges */
1104 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1106 data_blob_free(&tmp_blob);
1108 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1109 OID_NTLMSSP, &msg_in);
1114 DEBUG(3,("Failed to parse auth response\n"));
1115 if (NT_STATUS_IS_OK(status)
1116 || NT_STATUS_EQUAL(status,
1117 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1119 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1124 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1126 if (!NT_STATUS_IS_OK(status)
1127 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1128 TALLOC_FREE(subreq);
1129 TALLOC_FREE(state->ntlmssp_state);
1130 tevent_req_nterror(req, status);
1134 state->blob_out = spnego_gen_auth(state, blob_out);
1135 TALLOC_FREE(subreq);
1136 if (tevent_req_nomem(state->blob_out.data, req)) {
1140 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1142 if (tevent_req_nomem(subreq, req)) {
1145 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1148 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1150 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1151 req, struct cli_session_setup_ntlmssp_state);
1154 if (tevent_req_is_nterror(req, &status)) {
1155 state->cli->vuid = 0;
1158 return NT_STATUS_OK;
1161 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1166 struct tevent_context *ev;
1167 struct tevent_req *req;
1168 NTSTATUS status = NT_STATUS_NO_MEMORY;
1170 if (cli_has_async_calls(cli)) {
1171 return NT_STATUS_INVALID_PARAMETER;
1173 ev = tevent_context_init(talloc_tos());
1177 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1181 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1184 status = cli_session_setup_ntlmssp_recv(req);
1187 if (!NT_STATUS_IS_OK(status)) {
1188 cli_set_error(cli, status);
1193 /****************************************************************************
1194 Do a spnego encrypted session setup.
1196 user_domain: The shortname of the domain the user/machine is a member of.
1197 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1198 ****************************************************************************/
1200 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1201 const char *pass, const char *user_domain,
1202 const char * dest_realm)
1204 char *principal = NULL;
1205 char *OIDs[ASN1_MAX_OIDS];
1208 const char *p = NULL;
1209 char *account = NULL;
1212 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1214 /* the server might not even do spnego */
1215 if (cli->secblob.length <= 16) {
1216 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1221 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1224 /* there is 16 bytes of GUID before the real spnego packet starts */
1225 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1227 /* The server sent us the first part of the SPNEGO exchange in the
1228 * negprot reply. It is WRONG to depend on the principal sent in the
1229 * negprot reply, but right now we do it. If we don't receive one,
1230 * we try to best guess, then fall back to NTLM. */
1231 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL)) {
1232 data_blob_free(&blob);
1233 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1235 data_blob_free(&blob);
1237 /* make sure the server understands kerberos */
1238 for (i=0;OIDs[i];i++) {
1240 DEBUG(3,("got OID=%s\n", OIDs[i]));
1242 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1243 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1244 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1245 cli->got_kerberos_mechanism = True;
1247 talloc_free(OIDs[i]);
1250 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1252 status = cli_set_username(cli, user);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 TALLOC_FREE(principal);
1255 return ADS_ERROR_NT(status);
1259 /* If password is set we reauthenticate to kerberos server
1260 * and do not store results */
1262 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1265 if (pass && *pass) {
1268 use_in_memory_ccache();
1269 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1272 TALLOC_FREE(principal);
1273 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1274 if (cli->fallback_after_kerberos)
1276 return ADS_ERROR_KRB5(ret);
1280 /* If we get a bad principal, try to guess it if
1281 we have a valid host NetBIOS name.
1283 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1284 TALLOC_FREE(principal);
1287 if (principal == NULL &&
1288 !is_ipaddress(cli->desthost) &&
1289 !strequal(STAR_SMBSERVER,
1292 char *machine = NULL;
1294 DEBUG(3,("cli_session_setup_spnego: got a "
1295 "bad server principal, trying to guess ...\n"));
1297 host = strchr_m(cli->desthost, '.');
1299 /* We had a '.' in the name. */
1300 machine = SMB_STRNDUP(cli->desthost,
1301 host - cli->desthost);
1303 machine = SMB_STRDUP(cli->desthost);
1305 if (machine == NULL) {
1306 TALLOC_FREE(principal);
1307 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1311 realm = SMB_STRDUP(dest_realm);
1316 realm = kerberos_get_realm_from_hostname(cli->desthost);
1318 /* NetBIOS name - use our realm. */
1319 realm = kerberos_get_default_realm_from_ccache();
1323 if (realm && *realm) {
1326 principal = talloc_asprintf(talloc_tos(),
1331 /* NetBIOS name, use machine account. */
1332 principal = talloc_asprintf(talloc_tos(),
1340 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1342 DEBUG(3,("cli_session_setup_spnego: guessed "
1343 "server principal=%s\n",
1344 principal ? principal : "<null>"));
1351 rc = cli_session_setup_kerberos(cli, principal,
1353 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1354 TALLOC_FREE(principal);
1361 TALLOC_FREE(principal);
1365 account = talloc_strdup(talloc_tos(), user);
1367 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1370 /* when falling back to ntlmssp while authenticating with a machine
1371 * account strip off the realm - gd */
1373 if ((p = strchr_m(user, '@')) != NULL) {
1374 account[PTR_DIFF(p,user)] = '\0';
1377 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1380 /****************************************************************************
1381 Send a session setup. The username and workgroup is in UNIX character
1382 format and must be converted to DOS codepage format before sending. If the
1383 password is in plaintext, the same should be done.
1384 ****************************************************************************/
1386 NTSTATUS cli_session_setup(struct cli_state *cli,
1388 const char *pass, int passlen,
1389 const char *ntpass, int ntpasslen,
1390 const char *workgroup)
1396 fstrcpy(user2, user);
1405 /* allow for workgroups as part of the username */
1406 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1407 (p=strchr_m(user2,*lp_winbind_separator()))) {
1413 if (cli->protocol < PROTOCOL_LANMAN1) {
1414 return NT_STATUS_OK;
1417 /* now work out what sort of session setup we are going to
1418 do. I have split this into separate functions to make the
1419 flow a bit easier to understand (tridge) */
1421 /* if its an older server then we have to use the older request format */
1423 if (cli->protocol < PROTOCOL_NT1) {
1424 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1425 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1427 return NT_STATUS_ACCESS_DENIED;
1430 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1431 !lp_client_plaintext_auth() && (*pass)) {
1432 DEBUG(1, ("Server requested plaintext password but "
1433 "'client plaintext auth' is disabled\n"));
1434 return NT_STATUS_ACCESS_DENIED;
1437 return cli_session_setup_lanman2(cli, user, pass, passlen,
1441 /* if no user is supplied then we have to do an anonymous connection.
1442 passwords are ignored */
1444 if (!user || !*user)
1445 return cli_session_setup_guest(cli);
1447 /* if the server is share level then send a plaintext null
1448 password at this point. The password is sent in the tree
1451 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1452 return cli_session_setup_plaintext(cli, user, "", workgroup);
1454 /* if the server doesn't support encryption then we have to use
1455 plaintext. The second password is ignored */
1457 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1458 if (!lp_client_plaintext_auth() && (*pass)) {
1459 DEBUG(1, ("Server requested plaintext password but "
1460 "'client plaintext auth' is disabled\n"));
1461 return NT_STATUS_ACCESS_DENIED;
1463 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1466 /* if the server supports extended security then use SPNEGO */
1468 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1469 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1471 if (!ADS_ERR_OK(status)) {
1472 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1473 return ads_ntstatus(status);
1478 /* otherwise do a NT1 style session setup */
1479 status = cli_session_setup_nt1(cli, user, pass, passlen,
1480 ntpass, ntpasslen, workgroup);
1481 if (!NT_STATUS_IS_OK(status)) {
1482 DEBUG(3,("cli_session_setup: NT1 session setup "
1483 "failed: %s\n", nt_errstr(status)));
1488 if (strstr(cli->server_type, "Samba")) {
1489 cli->is_samba = True;
1492 return NT_STATUS_OK;
1495 /****************************************************************************
1497 *****************************************************************************/
1499 struct cli_ulogoff_state {
1500 struct cli_state *cli;
1504 static void cli_ulogoff_done(struct tevent_req *subreq);
1506 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1507 struct tevent_context *ev,
1508 struct cli_state *cli)
1510 struct tevent_req *req, *subreq;
1511 struct cli_ulogoff_state *state;
1513 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1519 SCVAL(state->vwv+0, 0, 0xFF);
1520 SCVAL(state->vwv+1, 0, 0);
1521 SSVAL(state->vwv+2, 0, 0);
1523 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
1525 if (tevent_req_nomem(subreq, req)) {
1526 return tevent_req_post(req, ev);
1528 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1532 static void cli_ulogoff_done(struct tevent_req *subreq)
1534 struct tevent_req *req = tevent_req_callback_data(
1535 subreq, struct tevent_req);
1536 struct cli_ulogoff_state *state = tevent_req_data(
1537 req, struct cli_ulogoff_state);
1540 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 tevent_req_nterror(req, status);
1545 state->cli->vuid = -1;
1546 tevent_req_done(req);
1549 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1551 return tevent_req_simple_recv_ntstatus(req);
1554 NTSTATUS cli_ulogoff(struct cli_state *cli)
1556 struct tevent_context *ev;
1557 struct tevent_req *req;
1558 NTSTATUS status = NT_STATUS_NO_MEMORY;
1560 if (cli_has_async_calls(cli)) {
1561 return NT_STATUS_INVALID_PARAMETER;
1563 ev = tevent_context_init(talloc_tos());
1567 req = cli_ulogoff_send(ev, ev, cli);
1571 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1574 status = cli_ulogoff_recv(req);
1577 if (!NT_STATUS_IS_OK(status)) {
1578 cli_set_error(cli, status);
1583 /****************************************************************************
1585 ****************************************************************************/
1587 struct cli_tcon_andx_state {
1588 struct cli_state *cli;
1593 static void cli_tcon_andx_done(struct tevent_req *subreq);
1595 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1596 struct event_context *ev,
1597 struct cli_state *cli,
1598 const char *share, const char *dev,
1599 const char *pass, int passlen,
1600 struct tevent_req **psmbreq)
1602 struct tevent_req *req, *subreq;
1603 struct cli_tcon_andx_state *state;
1611 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1618 fstrcpy(cli->share, share);
1620 /* in user level security don't send a password now */
1621 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1624 } else if (pass == NULL) {
1625 DEBUG(1, ("Server not using user level security and no "
1626 "password supplied.\n"));
1630 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1631 *pass && passlen != 24) {
1632 if (!lp_client_lanman_auth()) {
1633 DEBUG(1, ("Server requested LANMAN password "
1634 "(share-level security) but "
1635 "'client lanman auth' is disabled\n"));
1640 * Non-encrypted passwords - convert to DOS codepage before
1644 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1646 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1647 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1649 if (!lp_client_plaintext_auth() && (*pass)) {
1650 DEBUG(1, ("Server requested plaintext "
1651 "password but 'client plaintext "
1652 "auth' is disabled\n"));
1657 * Non-encrypted passwords - convert to DOS codepage
1660 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1662 if (passlen == -1) {
1663 DEBUG(1, ("clistr_push(pword) failed\n"));
1668 memcpy(pword, pass, passlen);
1673 SCVAL(vwv+0, 0, 0xFF);
1676 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1677 SSVAL(vwv+3, 0, passlen);
1680 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1682 bytes = talloc_array(state, uint8_t, 0);
1688 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1689 cli->desthost, share);
1694 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1699 * Add the devicetype
1701 tmp = talloc_strdup_upper(talloc_tos(), dev);
1706 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1709 if (bytes == NULL) {
1714 state->bytes.iov_base = (void *)bytes;
1715 state->bytes.iov_len = talloc_get_size(bytes);
1717 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1719 if (subreq == NULL) {
1723 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1728 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1729 return tevent_req_post(req, ev);
1732 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1733 struct event_context *ev,
1734 struct cli_state *cli,
1735 const char *share, const char *dev,
1736 const char *pass, int passlen)
1738 struct tevent_req *req, *subreq;
1741 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1746 if (subreq == NULL) {
1749 status = cli_smb_req_send(subreq);
1750 if (!NT_STATUS_IS_OK(status)) {
1751 tevent_req_nterror(req, status);
1752 return tevent_req_post(req, ev);
1757 static void cli_tcon_andx_done(struct tevent_req *subreq)
1759 struct tevent_req *req = tevent_req_callback_data(
1760 subreq, struct tevent_req);
1761 struct cli_tcon_andx_state *state = tevent_req_data(
1762 req, struct cli_tcon_andx_state);
1763 struct cli_state *cli = state->cli;
1772 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
1773 &num_bytes, &bytes);
1774 TALLOC_FREE(subreq);
1775 if (!NT_STATUS_IS_OK(status)) {
1776 tevent_req_nterror(req, status);
1782 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1783 STR_TERMINATE|STR_ASCII);
1785 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1786 /* almost certainly win95 - enable bug fixes */
1791 * Make sure that we have the optional support 16-bit field. WCT > 2.
1792 * Avoids issues when connecting to Win9x boxes sharing files
1795 cli->dfsroot = false;
1797 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1798 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1801 cli->cnum = SVAL(inbuf,smb_tid);
1802 tevent_req_done(req);
1805 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1807 return tevent_req_simple_recv_ntstatus(req);
1810 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1811 const char *dev, const char *pass, int passlen)
1813 TALLOC_CTX *frame = talloc_stackframe();
1814 struct event_context *ev;
1815 struct tevent_req *req;
1816 NTSTATUS status = NT_STATUS_OK;
1818 if (cli_has_async_calls(cli)) {
1820 * Can't use sync call while an async call is in flight
1822 status = NT_STATUS_INVALID_PARAMETER;
1826 ev = event_context_init(frame);
1828 status = NT_STATUS_NO_MEMORY;
1832 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1834 status = NT_STATUS_NO_MEMORY;
1838 if (!tevent_req_poll(req, ev)) {
1839 status = map_nt_error_from_unix(errno);
1843 status = cli_tcon_andx_recv(req);
1846 if (!NT_STATUS_IS_OK(status)) {
1847 cli_set_error(cli, status);
1852 /****************************************************************************
1853 Send a tree disconnect.
1854 ****************************************************************************/
1856 struct cli_tdis_state {
1857 struct cli_state *cli;
1860 static void cli_tdis_done(struct tevent_req *subreq);
1862 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
1863 struct tevent_context *ev,
1864 struct cli_state *cli)
1866 struct tevent_req *req, *subreq;
1867 struct cli_tdis_state *state;
1869 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
1875 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
1876 if (tevent_req_nomem(subreq, req)) {
1877 return tevent_req_post(req, ev);
1879 tevent_req_set_callback(subreq, cli_tdis_done, req);
1883 static void cli_tdis_done(struct tevent_req *subreq)
1885 struct tevent_req *req = tevent_req_callback_data(
1886 subreq, struct tevent_req);
1887 struct cli_tdis_state *state = tevent_req_data(
1888 req, struct cli_tdis_state);
1891 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1892 TALLOC_FREE(subreq);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 tevent_req_nterror(req, status);
1897 state->cli->cnum = -1;
1898 tevent_req_done(req);
1901 NTSTATUS cli_tdis_recv(struct tevent_req *req)
1903 return tevent_req_simple_recv_ntstatus(req);
1906 NTSTATUS cli_tdis(struct cli_state *cli)
1908 struct tevent_context *ev;
1909 struct tevent_req *req;
1910 NTSTATUS status = NT_STATUS_NO_MEMORY;
1912 if (cli_has_async_calls(cli)) {
1913 return NT_STATUS_INVALID_PARAMETER;
1915 ev = tevent_context_init(talloc_tos());
1919 req = cli_tdis_send(ev, ev, cli);
1923 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1926 status = cli_tdis_recv(req);
1929 if (!NT_STATUS_IS_OK(status)) {
1930 cli_set_error(cli, status);
1935 /****************************************************************************
1936 Send a negprot command.
1937 ****************************************************************************/
1939 void cli_negprot_sendsync(struct cli_state *cli)
1944 if (cli->protocol < PROTOCOL_NT1)
1945 cli->use_spnego = False;
1947 memset(cli->outbuf,'\0',smb_size);
1949 /* setup the protocol strings */
1950 cli_set_message(cli->outbuf,0,0,True);
1952 p = smb_buf(cli->outbuf);
1953 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1954 if (prots[numprots].prot > cli->protocol) {
1958 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1961 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1962 cli_setup_bcc(cli, p);
1963 cli_setup_packet(cli);
1965 SCVAL(smb_buf(cli->outbuf),0,2);
1970 /****************************************************************************
1971 Send a negprot command.
1972 ****************************************************************************/
1974 struct cli_negprot_state {
1975 struct cli_state *cli;
1978 static void cli_negprot_done(struct tevent_req *subreq);
1980 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1981 struct event_context *ev,
1982 struct cli_state *cli)
1984 struct tevent_req *req, *subreq;
1985 struct cli_negprot_state *state;
1986 uint8_t *bytes = NULL;
1990 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1996 if (cli->protocol < PROTOCOL_NT1)
1997 cli->use_spnego = False;
1999 /* setup the protocol strings */
2000 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2002 if (prots[numprots].prot > cli->protocol) {
2005 bytes = (uint8_t *)talloc_append_blob(
2006 state, bytes, data_blob_const(&c, sizeof(c)));
2007 if (tevent_req_nomem(bytes, req)) {
2008 return tevent_req_post(req, ev);
2010 bytes = smb_bytes_push_str(bytes, false,
2011 prots[numprots].name,
2012 strlen(prots[numprots].name)+1,
2014 if (tevent_req_nomem(bytes, req)) {
2015 return tevent_req_post(req, ev);
2022 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2023 talloc_get_size(bytes), bytes);
2026 if (tevent_req_nomem(subreq, req)) {
2027 return tevent_req_post(req, ev);
2029 tevent_req_set_callback(subreq, cli_negprot_done, req);
2033 static void cli_negprot_done(struct tevent_req *subreq)
2035 struct tevent_req *req = tevent_req_callback_data(
2036 subreq, struct tevent_req);
2037 struct cli_negprot_state *state = tevent_req_data(
2038 req, struct cli_negprot_state);
2039 struct cli_state *cli = state->cli;
2048 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2049 &num_bytes, &bytes);
2050 TALLOC_FREE(subreq);
2051 if (!NT_STATUS_IS_OK(status)) {
2052 tevent_req_nterror(req, status);
2056 protnum = SVAL(vwv, 0);
2058 if ((protnum >= ARRAY_SIZE(prots))
2059 || (prots[protnum].prot > cli->protocol)) {
2060 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2064 cli->protocol = prots[protnum].prot;
2066 if ((cli->protocol < PROTOCOL_NT1) &&
2067 client_is_signing_mandatory(cli)) {
2068 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2069 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2073 if (cli->protocol >= PROTOCOL_NT1) {
2075 bool negotiated_smb_signing = false;
2078 cli->sec_mode = CVAL(vwv + 1, 0);
2079 cli->max_mux = SVAL(vwv + 1, 1);
2080 cli->max_xmit = IVAL(vwv + 3, 1);
2081 cli->sesskey = IVAL(vwv + 7, 1);
2082 cli->serverzone = SVALS(vwv + 15, 1);
2083 cli->serverzone *= 60;
2084 /* this time arrives in real GMT */
2085 ts = interpret_long_date(((char *)(vwv+11))+1);
2086 cli->servertime = ts.tv_sec;
2087 cli->secblob = data_blob(bytes, num_bytes);
2088 cli->capabilities = IVAL(vwv + 9, 1);
2089 if (cli->capabilities & CAP_RAW_MODE) {
2090 cli->readbraw_supported = True;
2091 cli->writebraw_supported = True;
2093 /* work out if they sent us a workgroup */
2094 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2095 smb_buflen(cli->inbuf) > 8) {
2096 clistr_pull(cli->inbuf, cli->server_domain,
2097 bytes+8, sizeof(cli->server_domain),
2099 STR_UNICODE|STR_NOALIGN);
2103 * As signing is slow we only turn it on if either the client or
2104 * the server require it. JRA.
2107 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2108 /* Fail if server says signing is mandatory and we don't want to support it. */
2109 if (!client_is_signing_allowed(cli)) {
2110 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2111 tevent_req_nterror(req,
2112 NT_STATUS_ACCESS_DENIED);
2115 negotiated_smb_signing = true;
2116 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2117 /* Fail if client says signing is mandatory and the server doesn't support it. */
2118 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2119 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2120 tevent_req_nterror(req,
2121 NT_STATUS_ACCESS_DENIED);
2124 negotiated_smb_signing = true;
2125 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2126 negotiated_smb_signing = true;
2129 if (negotiated_smb_signing) {
2130 cli_set_signing_negotiated(cli);
2133 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2134 SAFE_FREE(cli->outbuf);
2135 SAFE_FREE(cli->inbuf);
2136 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2137 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2138 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2141 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2142 cli->use_spnego = False;
2143 cli->sec_mode = SVAL(vwv + 1, 0);
2144 cli->max_xmit = SVAL(vwv + 2, 0);
2145 cli->max_mux = SVAL(vwv + 3, 0);
2146 cli->sesskey = IVAL(vwv + 6, 0);
2147 cli->serverzone = SVALS(vwv + 10, 0);
2148 cli->serverzone *= 60;
2149 /* this time is converted to GMT by make_unix_date */
2150 cli->servertime = make_unix_date(
2151 (char *)(vwv + 8), cli->serverzone);
2152 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2153 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2154 cli->secblob = data_blob(bytes, num_bytes);
2156 /* the old core protocol */
2157 cli->use_spnego = False;
2159 cli->serverzone = get_time_zone(time(NULL));
2162 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2164 /* a way to force ascii SMB */
2165 if (getenv("CLI_FORCE_ASCII"))
2166 cli->capabilities &= ~CAP_UNICODE;
2168 tevent_req_done(req);
2171 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2173 return tevent_req_simple_recv_ntstatus(req);
2176 NTSTATUS cli_negprot(struct cli_state *cli)
2178 TALLOC_CTX *frame = talloc_stackframe();
2179 struct event_context *ev;
2180 struct tevent_req *req;
2181 NTSTATUS status = NT_STATUS_OK;
2183 if (cli_has_async_calls(cli)) {
2185 * Can't use sync call while an async call is in flight
2187 status = NT_STATUS_INVALID_PARAMETER;
2191 ev = event_context_init(frame);
2193 status = NT_STATUS_NO_MEMORY;
2197 req = cli_negprot_send(frame, ev, cli);
2199 status = NT_STATUS_NO_MEMORY;
2203 if (!tevent_req_poll(req, ev)) {
2204 status = map_nt_error_from_unix(errno);
2208 status = cli_negprot_recv(req);
2211 if (!NT_STATUS_IS_OK(status)) {
2212 cli_set_error(cli, status);
2217 /****************************************************************************
2218 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2219 ****************************************************************************/
2221 bool cli_session_request(struct cli_state *cli,
2222 struct nmb_name *calling, struct nmb_name *called)
2228 /* 445 doesn't have session request */
2229 if (cli->port == 445)
2232 memcpy(&(cli->calling), calling, sizeof(*calling));
2233 memcpy(&(cli->called ), called , sizeof(*called ));
2235 /* put in the destination name */
2237 tmp = name_mangle(talloc_tos(), cli->called.name,
2238 cli->called.name_type);
2243 p = cli->outbuf+len;
2244 memcpy(p, tmp, name_len(tmp));
2245 len += name_len(tmp);
2250 tmp = name_mangle(talloc_tos(), cli->calling.name,
2251 cli->calling.name_type);
2256 p = cli->outbuf+len;
2257 memcpy(p, tmp, name_len(tmp));
2258 len += name_len(tmp);
2261 /* send a session request (RFC 1002) */
2262 /* setup the packet length
2263 * Remove four bytes from the length count, since the length
2264 * field in the NBT Session Service header counts the number
2265 * of bytes which follow. The cli_send_smb() function knows
2266 * about this and accounts for those four bytes.
2270 _smb_setlen(cli->outbuf,len);
2271 SCVAL(cli->outbuf,0,0x81);
2274 DEBUG(5,("Sent session request\n"));
2276 if (!cli_receive_smb(cli))
2279 if (CVAL(cli->inbuf,0) == 0x84) {
2280 /* C. Hoch 9/14/95 Start */
2281 /* For information, here is the response structure.
2282 * We do the byte-twiddling to for portability.
2283 struct RetargetResponse{
2285 unsigned char flags;
2291 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2292 struct in_addr dest_ip;
2295 /* SESSION RETARGET */
2296 putip((char *)&dest_ip,cli->inbuf+4);
2297 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2299 status = open_socket_out(&cli->dest_ss, port,
2300 LONG_CONNECT_TIMEOUT, &cli->fd);
2301 if (!NT_STATUS_IS_OK(status)) {
2305 DEBUG(3,("Retargeted\n"));
2307 set_socket_options(cli->fd, lp_socket_options());
2314 DEBUG(0,("Retarget recursion - failing\n"));
2318 ret = cli_session_request(cli, calling, called);
2322 } /* C. Hoch 9/14/95 End */
2324 if (CVAL(cli->inbuf,0) != 0x82) {
2325 /* This is the wrong place to put the error... JRA. */
2326 cli->rap_error = CVAL(cli->inbuf,4);
2336 static void smb_sock_connected(struct tevent_req *req)
2338 struct fd_struct *pfd = tevent_req_callback_data(
2339 req, struct fd_struct);
2343 status = open_socket_out_defer_recv(req, &fd);
2344 if (NT_STATUS_IS_OK(status)) {
2349 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2350 uint16_t *port, int timeout, int *pfd)
2352 struct event_context *ev;
2353 struct tevent_req *r139, *r445;
2354 struct fd_struct *fd139, *fd445;
2355 NTSTATUS status = NT_STATUS_NO_MEMORY;
2358 return open_socket_out(pss, *port, timeout, pfd);
2361 ev = event_context_init(talloc_tos());
2363 return NT_STATUS_NO_MEMORY;
2366 fd139 = talloc(ev, struct fd_struct);
2367 if (fd139 == NULL) {
2372 fd445 = talloc(ev, struct fd_struct);
2373 if (fd445 == NULL) {
2378 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2380 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2382 if ((r445 == NULL) || (r139 == NULL)) {
2385 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2386 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2388 while ((fd445->fd == -1) && (fd139->fd == -1)
2389 && (tevent_req_is_in_progress(r139)
2390 || tevent_req_is_in_progress(r445))) {
2391 event_loop_once(ev);
2394 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2399 if (fd445->fd != -1) {
2402 status = NT_STATUS_OK;
2405 if (fd139->fd != -1) {
2408 status = NT_STATUS_OK;
2412 status = open_socket_out_defer_recv(r445, &fd445->fd);
2418 /****************************************************************************
2419 Open the client sockets.
2420 ****************************************************************************/
2422 NTSTATUS cli_connect(struct cli_state *cli,
2424 struct sockaddr_storage *dest_ss)
2427 int name_type = 0x20;
2428 TALLOC_CTX *frame = talloc_stackframe();
2429 unsigned int num_addrs = 0;
2431 struct sockaddr_storage *ss_arr = NULL;
2434 /* reasonable default hostname */
2436 host = STAR_SMBSERVER;
2439 fstrcpy(cli->desthost, host);
2441 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2442 if ((p = strchr(cli->desthost, '#'))) {
2443 name_type = strtol(p+1, NULL, 16);
2447 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2448 NTSTATUS status =resolve_name_list(frame,
2453 if (!NT_STATUS_IS_OK(status)) {
2455 return NT_STATUS_BAD_NETWORK_NAME;
2459 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2462 return NT_STATUS_NO_MEMORY;
2467 for (i = 0; i < num_addrs; i++) {
2468 cli->dest_ss = ss_arr[i];
2469 if (getenv("LIBSMB_PROG")) {
2470 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2472 uint16_t port = cli->port;
2474 status = open_smb_socket(&cli->dest_ss, &port,
2475 cli->timeout, &cli->fd);
2476 if (NT_STATUS_IS_OK(status)) {
2480 if (cli->fd == -1) {
2481 char addr[INET6_ADDRSTRLEN];
2482 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2483 DEBUG(2,("Error connecting to %s (%s)\n",
2484 dest_ss?addr:host,strerror(errno)));
2486 /* Exit from loop on first connection. */
2491 if (cli->fd == -1) {
2493 return map_nt_error_from_unix(errno);
2497 *dest_ss = cli->dest_ss;
2500 set_socket_options(cli->fd, lp_socket_options());
2503 return NT_STATUS_OK;
2507 establishes a connection to after the negprot.
2508 @param output_cli A fully initialised cli structure, non-null only on success
2509 @param dest_host The netbios name of the remote host
2510 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2511 @param port (optional) The destination port (0 for default)
2512 @param retry bool. Did this connection fail with a retryable error ?
2515 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2516 const char *my_name,
2517 const char *dest_host,
2518 struct sockaddr_storage *dest_ss, int port,
2519 int signing_state, int flags,
2523 struct nmb_name calling;
2524 struct nmb_name called;
2525 struct cli_state *cli;
2526 struct sockaddr_storage ss;
2532 my_name = global_myname();
2534 if (!(cli = cli_initialise_ex(signing_state))) {
2535 return NT_STATUS_NO_MEMORY;
2538 make_nmb_name(&calling, my_name, 0x0);
2539 make_nmb_name(&called , dest_host, 0x20);
2541 cli_set_port(cli, port);
2542 cli_set_timeout(cli, 10000); /* 10 seconds. */
2552 DEBUG(3,("Connecting to host=%s\n", dest_host));
2554 nt_status = cli_connect(cli, dest_host, &ss);
2555 if (!NT_STATUS_IS_OK(nt_status)) {
2556 char addr[INET6_ADDRSTRLEN];
2557 print_sockaddr(addr, sizeof(addr), &ss);
2558 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2559 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2567 if (!cli_session_request(cli, &calling, &called)) {
2569 DEBUG(1,("session request to %s failed (%s)\n",
2570 called.name, cli_errstr(cli)));
2571 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2575 if (strcmp(called.name, STAR_SMBSERVER)) {
2576 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2579 return NT_STATUS_BAD_NETWORK_NAME;
2582 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2583 cli->use_spnego = False;
2584 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2585 cli->use_kerberos = True;
2587 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2588 cli->use_kerberos) {
2589 cli->fallback_after_kerberos = true;
2591 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2592 cli->use_ccache = true;
2595 nt_status = cli_negprot(cli);
2596 if (!NT_STATUS_IS_OK(nt_status)) {
2597 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2603 return NT_STATUS_OK;
2608 establishes a connection right up to doing tconX, password specified.
2609 @param output_cli A fully initialised cli structure, non-null only on success
2610 @param dest_host The netbios name of the remote host
2611 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2612 @param port (optional) The destination port (0 for default)
2613 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2614 @param service_type The 'type' of serivice.
2615 @param user Username, unix string
2616 @param domain User's domain
2617 @param password User's password, unencrypted unix string.
2618 @param retry bool. Did this connection fail with a retryable error ?
2621 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2622 const char *my_name,
2623 const char *dest_host,
2624 struct sockaddr_storage *dest_ss, int port,
2625 const char *service, const char *service_type,
2626 const char *user, const char *domain,
2627 const char *password, int flags,
2632 struct cli_state *cli = NULL;
2633 int pw_len = password ? strlen(password)+1 : 0;
2637 if (password == NULL) {
2641 nt_status = cli_start_connection(&cli, my_name, dest_host,
2642 dest_ss, port, signing_state,
2645 if (!NT_STATUS_IS_OK(nt_status)) {
2649 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2650 cli->use_level_II_oplocks =
2651 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2653 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2655 if (!NT_STATUS_IS_OK(nt_status)) {
2657 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2658 DEBUG(1,("failed session setup with %s\n",
2659 nt_errstr(nt_status)));
2664 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2665 if (!NT_STATUS_IS_OK(nt_status)) {
2666 DEBUG(1,("anonymous failed session setup with %s\n",
2667 nt_errstr(nt_status)));
2674 nt_status = cli_tcon_andx(cli, service, service_type, password,
2676 if (!NT_STATUS_IS_OK(nt_status)) {
2677 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2679 if (NT_STATUS_IS_OK(nt_status)) {
2680 nt_status = NT_STATUS_UNSUCCESSFUL;
2686 nt_status = cli_init_creds(cli, user, domain, password);
2687 if (!NT_STATUS_IS_OK(nt_status)) {
2693 return NT_STATUS_OK;
2696 /****************************************************************************
2697 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2698 ****************************************************************************/
2700 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2701 struct sockaddr_storage *pdest_ss)
2703 struct nmb_name calling, called;
2705 make_nmb_name(&calling, srchost, 0x0);
2708 * If the called name is an IP address
2709 * then use *SMBSERVER immediately.
2712 if(is_ipaddress(desthost)) {
2713 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2715 make_nmb_name(&called, desthost, 0x20);
2718 if (!cli_session_request(*ppcli, &calling, &called)) {
2720 struct nmb_name smbservername;
2722 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2725 * If the name wasn't *SMBSERVER then
2726 * try with *SMBSERVER if the first name fails.
2729 if (nmb_name_equal(&called, &smbservername)) {
2732 * The name used was *SMBSERVER, don't bother with another name.
2735 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2736 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2741 cli_shutdown(*ppcli);
2743 *ppcli = cli_initialise();
2745 /* Out of memory... */
2749 status = cli_connect(*ppcli, desthost, pdest_ss);
2750 if (!NT_STATUS_IS_OK(status) ||
2751 !cli_session_request(*ppcli, &calling, &smbservername)) {
2752 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2753 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2761 /****************************************************************************
2762 Send an old style tcon.
2763 ****************************************************************************/
2764 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2765 const char *service, const char *pass, const char *dev,
2766 uint16 *max_xmit, uint16 *tid)
2770 if (!lp_client_plaintext_auth() && (*pass)) {
2771 DEBUG(1, ("Server requested plaintext password but 'client "
2772 "plaintext auth' is disabled\n"));
2773 return NT_STATUS_ACCESS_DENIED;
2776 memset(cli->outbuf,'\0',smb_size);
2777 memset(cli->inbuf,'\0',smb_size);
2779 cli_set_message(cli->outbuf, 0, 0, True);
2780 SCVAL(cli->outbuf,smb_com,SMBtcon);
2781 cli_setup_packet(cli);
2783 p = smb_buf(cli->outbuf);
2784 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2785 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2786 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2788 cli_setup_bcc(cli, p);
2791 if (!cli_receive_smb(cli)) {
2792 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2795 if (cli_is_error(cli)) {
2796 return cli_nt_error(cli);
2799 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2800 *tid = SVAL(cli->inbuf, smb_vwv1);
2802 return NT_STATUS_OK;
2805 /* Return a cli_state pointing at the IPC$ share for the given server */
2807 struct cli_state *get_ipc_connect(char *server,
2808 struct sockaddr_storage *server_ss,
2809 const struct user_auth_info *user_info)
2811 struct cli_state *cli;
2813 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2815 if (user_info->use_kerberos) {
2816 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2819 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2820 user_info->username ? user_info->username : "",
2822 user_info->password ? user_info->password : "",
2826 if (NT_STATUS_IS_OK(nt_status)) {
2828 } else if (is_ipaddress(server)) {
2829 /* windows 9* needs a correct NMB name for connections */
2830 fstring remote_name;
2832 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2833 cli = get_ipc_connect(remote_name, server_ss, user_info);
2842 * Given the IP address of a master browser on the network, return its
2843 * workgroup and connect to it.
2845 * This function is provided to allow additional processing beyond what
2846 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2847 * browsers and obtain each master browsers' list of domains (in case the
2848 * first master browser is recently on the network and has not yet
2849 * synchronized with other master browsers and therefore does not yet have the
2850 * entire network browse list)
2853 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2854 struct ip_service *mb_ip,
2855 const struct user_auth_info *user_info,
2856 char **pp_workgroup_out)
2858 char addr[INET6_ADDRSTRLEN];
2860 struct cli_state *cli;
2861 struct sockaddr_storage server_ss;
2863 *pp_workgroup_out = NULL;
2865 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2866 DEBUG(99, ("Looking up name of master browser %s\n",
2870 * Do a name status query to find out the name of the master browser.
2871 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2872 * master browser will not respond to a wildcard query (or, at least,
2873 * an NT4 server acting as the domain master browser will not).
2875 * We might be able to use ONLY the query on MSBROWSE, but that's not
2876 * yet been tested with all Windows versions, so until it is, leave
2877 * the original wildcard query as the first choice and fall back to
2878 * MSBROWSE if the wildcard query fails.
2880 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2881 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2883 DEBUG(99, ("Could not retrieve name status for %s\n",
2888 if (!find_master_ip(name, &server_ss)) {
2889 DEBUG(99, ("Could not find master ip for %s\n", name));
2893 *pp_workgroup_out = talloc_strdup(ctx, name);
2895 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2897 print_sockaddr(addr, sizeof(addr), &server_ss);
2898 cli = get_ipc_connect(addr, &server_ss, user_info);
2904 * Return the IP address and workgroup of a master browser on the network, and
2908 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2909 const struct user_auth_info *user_info,
2910 char **pp_workgroup_out)
2912 struct ip_service *ip_list;
2913 struct cli_state *cli;
2916 *pp_workgroup_out = NULL;
2918 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2920 /* Go looking for workgroups by broadcasting on the local network */
2922 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2924 DEBUG(99, ("No master browsers responded\n"));
2928 for (i = 0; i < count; i++) {
2929 char addr[INET6_ADDRSTRLEN];
2930 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2931 DEBUG(99, ("Found master browser %s\n", addr));
2933 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2934 user_info, pp_workgroup_out);