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 "../libcli/auth/libcli_auth.h"
23 #include "../libcli/auth/spnego.h"
31 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
32 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
33 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
34 {PROTOCOL_LANMAN1, "LANMAN1.0"},
35 {PROTOCOL_LANMAN2, "LM1.2X002"},
36 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
37 {PROTOCOL_LANMAN2, "LANMAN2.1"},
38 {PROTOCOL_LANMAN2, "Samba"},
39 {PROTOCOL_NT1, "NT LANMAN 1.0"},
40 {PROTOCOL_NT1, "NT LM 0.12"},
43 #define STAR_SMBSERVER "*SMBSERVER"
46 * Set the user session key for a connection
47 * @param cli The cli structure to add it too
48 * @param session_key The session key used. (A copy of this is taken for the cli struct)
52 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
54 cli->user_session_key = data_blob(session_key.data, session_key.length);
57 /****************************************************************************
58 Do an old lanman2 style session setup.
59 ****************************************************************************/
61 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
63 const char *pass, size_t passlen,
64 const char *workgroup)
66 DATA_BLOB session_key = data_blob_null;
67 DATA_BLOB lm_response = data_blob_null;
72 if (passlen > sizeof(pword)-1) {
73 return NT_STATUS_INVALID_PARAMETER;
76 /* LANMAN servers predate NT status codes and Unicode and ignore those
77 smb flags so we must disable the corresponding default capabilities
78 that would otherwise cause the Unicode and NT Status flags to be
79 set (and even returned by the server) */
81 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
83 /* if in share level security then don't send a password now */
84 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
87 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
88 /* Encrypted mode needed, and non encrypted password supplied. */
89 lm_response = data_blob(NULL, 24);
90 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
91 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
92 return NT_STATUS_ACCESS_DENIED;
94 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
95 /* Encrypted mode needed, and encrypted password supplied. */
96 lm_response = data_blob(pass, passlen);
97 } else if (passlen > 0) {
98 /* Plaintext mode needed, assume plaintext supplied. */
99 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
100 lm_response = data_blob(pass, passlen);
103 /* send a session setup command */
104 memset(cli->outbuf,'\0',smb_size);
105 cli_set_message(cli->outbuf,10, 0, True);
106 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
107 cli_setup_packet(cli);
109 SCVAL(cli->outbuf,smb_vwv0,0xFF);
110 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
111 SSVAL(cli->outbuf,smb_vwv3,2);
112 SSVAL(cli->outbuf,smb_vwv4,1);
113 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
114 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
116 p = smb_buf(cli->outbuf);
117 memcpy(p,lm_response.data,lm_response.length);
118 p += lm_response.length;
119 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
120 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
121 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
122 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
123 cli_setup_bcc(cli, p);
125 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
126 return cli_nt_error(cli);
129 show_msg(cli->inbuf);
131 if (cli_is_error(cli)) {
132 return cli_nt_error(cli);
135 /* use the returned vuid from now on */
136 cli->vuid = SVAL(cli->inbuf,smb_uid);
137 status = cli_set_username(cli, user);
138 if (!NT_STATUS_IS_OK(status)) {
142 if (session_key.data) {
143 /* Have plaintext orginal */
144 cli_set_session_key(cli, session_key);
150 /****************************************************************************
151 Work out suitable capabilities to offer the server.
152 ****************************************************************************/
154 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
156 uint32 capabilities = CAP_NT_SMBS;
158 if (!cli->force_dos_errors)
159 capabilities |= CAP_STATUS32;
161 if (cli->use_level_II_oplocks)
162 capabilities |= CAP_LEVEL_II_OPLOCKS;
164 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
168 /****************************************************************************
169 Do a NT1 guest session setup.
170 ****************************************************************************/
172 struct cli_session_setup_guest_state {
173 struct cli_state *cli;
178 static void cli_session_setup_guest_done(struct tevent_req *subreq);
180 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
181 struct event_context *ev,
182 struct cli_state *cli,
183 struct tevent_req **psmbreq)
185 struct tevent_req *req, *subreq;
186 struct cli_session_setup_guest_state *state;
190 req = tevent_req_create(mem_ctx, &state,
191 struct cli_session_setup_guest_state);
198 SCVAL(vwv+0, 0, 0xFF);
201 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
203 SSVAL(vwv+4, 0, cli->pid);
204 SIVAL(vwv+5, 0, cli->sesskey);
209 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
211 bytes = talloc_array(state, uint8_t, 0);
213 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
215 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
217 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
218 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
225 state->bytes.iov_base = (void *)bytes;
226 state->bytes.iov_len = talloc_get_size(bytes);
228 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
230 if (subreq == NULL) {
234 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
239 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
240 struct event_context *ev,
241 struct cli_state *cli)
243 struct tevent_req *req, *subreq;
246 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
251 status = cli_smb_req_send(subreq);
252 if (NT_STATUS_IS_OK(status)) {
253 tevent_req_nterror(req, status);
254 return tevent_req_post(req, ev);
259 static void cli_session_setup_guest_done(struct tevent_req *subreq)
261 struct tevent_req *req = tevent_req_callback_data(
262 subreq, struct tevent_req);
263 struct cli_session_setup_guest_state *state = tevent_req_data(
264 req, struct cli_session_setup_guest_state);
265 struct cli_state *cli = state->cli;
272 status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes);
273 if (!NT_STATUS_IS_OK(status)) {
275 tevent_req_nterror(req, status);
279 inbuf = (char *)cli_smb_inbuf(subreq);
282 cli->vuid = SVAL(inbuf, smb_uid);
284 p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
285 bytes+num_bytes-p, STR_TERMINATE);
286 p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
287 bytes+num_bytes-p, STR_TERMINATE);
288 p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
289 bytes+num_bytes-p, STR_TERMINATE);
291 if (strstr(cli->server_type, "Samba")) {
292 cli->is_samba = True;
297 status = cli_set_username(cli, "");
298 if (!NT_STATUS_IS_OK(status)) {
299 tevent_req_nterror(req, status);
302 tevent_req_done(req);
305 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
307 return tevent_req_simple_recv_ntstatus(req);
310 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
312 TALLOC_CTX *frame = talloc_stackframe();
313 struct event_context *ev;
314 struct tevent_req *req;
315 NTSTATUS status = NT_STATUS_OK;
317 if (cli_has_async_calls(cli)) {
319 * Can't use sync call while an async call is in flight
321 status = NT_STATUS_INVALID_PARAMETER;
325 ev = event_context_init(frame);
327 status = NT_STATUS_NO_MEMORY;
331 req = cli_session_setup_guest_send(frame, ev, cli);
333 status = NT_STATUS_NO_MEMORY;
337 if (!tevent_req_poll(req, ev)) {
338 status = map_nt_error_from_unix(errno);
342 status = cli_session_setup_guest_recv(req);
345 if (!NT_STATUS_IS_OK(status)) {
346 cli_set_error(cli, status);
351 /****************************************************************************
352 Do a NT1 plaintext session setup.
353 ****************************************************************************/
355 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
356 const char *user, const char *pass,
357 const char *workgroup)
359 uint32 capabilities = cli_session_setup_capabilities(cli);
364 fstr_sprintf( lanman, "Samba %s", samba_version_string());
366 memset(cli->outbuf, '\0', smb_size);
367 cli_set_message(cli->outbuf,13,0,True);
368 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
369 cli_setup_packet(cli);
371 SCVAL(cli->outbuf,smb_vwv0,0xFF);
372 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
373 SSVAL(cli->outbuf,smb_vwv3,2);
374 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
375 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
376 SSVAL(cli->outbuf,smb_vwv8,0);
377 SIVAL(cli->outbuf,smb_vwv11,capabilities);
378 p = smb_buf(cli->outbuf);
380 /* check wether to send the ASCII or UNICODE version of the password */
382 if ( (capabilities & CAP_UNICODE) == 0 ) {
383 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
384 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
387 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
388 * the space taken by the unicode password to be one byte too
389 * long (as we're on an odd byte boundary here). Reduce the
390 * count by 1 to cope with this. Fixes smbclient against NetApp
391 * servers which can't cope. Fix from
392 * bryan.kolodziej@allenlund.com in bug #3840.
394 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
395 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
398 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
399 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
400 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
401 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
402 cli_setup_bcc(cli, p);
404 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
405 return cli_nt_error(cli);
408 show_msg(cli->inbuf);
410 if (cli_is_error(cli)) {
411 return cli_nt_error(cli);
414 cli->vuid = SVAL(cli->inbuf,smb_uid);
415 p = smb_buf(cli->inbuf);
416 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
418 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
420 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
422 status = cli_set_username(cli, user);
423 if (!NT_STATUS_IS_OK(status)) {
426 if (strstr(cli->server_type, "Samba")) {
427 cli->is_samba = True;
433 /****************************************************************************
434 do a NT1 NTLM/LM encrypted session setup - for when extended security
436 @param cli client state to create do session setup on
438 @param pass *either* cleartext password (passlen !=24) or LM response.
439 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
440 @param workgroup The user's domain.
441 ****************************************************************************/
443 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
444 const char *pass, size_t passlen,
445 const char *ntpass, size_t ntpasslen,
446 const char *workgroup)
448 uint32 capabilities = cli_session_setup_capabilities(cli);
449 DATA_BLOB lm_response = data_blob_null;
450 DATA_BLOB nt_response = data_blob_null;
451 DATA_BLOB session_key = data_blob_null;
457 /* do nothing - guest login */
458 } else if (passlen != 24) {
459 if (lp_client_ntlmv2_auth()) {
460 DATA_BLOB server_chal;
461 DATA_BLOB names_blob;
462 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
464 /* note that the 'workgroup' here is a best guess - we don't know
465 the server's domain at this point. The 'server name' is also
468 names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup);
470 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal,
472 &lm_response, &nt_response, NULL, &session_key)) {
473 data_blob_free(&names_blob);
474 data_blob_free(&server_chal);
475 return NT_STATUS_ACCESS_DENIED;
477 data_blob_free(&names_blob);
478 data_blob_free(&server_chal);
482 E_md4hash(pass, nt_hash);
485 nt_response = data_blob_null;
487 nt_response = data_blob(NULL, 24);
488 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
490 /* non encrypted password supplied. Ignore ntpass. */
491 if (lp_client_lanman_auth()) {
492 lm_response = data_blob(NULL, 24);
493 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
494 /* Oops, the LM response is invalid, just put
495 the NT response there instead */
496 data_blob_free(&lm_response);
497 lm_response = data_blob(nt_response.data, nt_response.length);
500 /* LM disabled, place NT# in LM field instead */
501 lm_response = data_blob(nt_response.data, nt_response.length);
504 session_key = data_blob(NULL, 16);
506 E_deshash(pass, session_key.data);
507 memset(&session_key.data[8], '\0', 8);
509 SMBsesskeygen_ntv1(nt_hash, session_key.data);
512 cli_temp_set_signing(cli);
514 /* pre-encrypted password supplied. Only used for
515 security=server, can't do
516 signing because we don't have original key */
518 lm_response = data_blob(pass, passlen);
519 nt_response = data_blob(ntpass, ntpasslen);
522 /* send a session setup command */
523 memset(cli->outbuf,'\0',smb_size);
525 cli_set_message(cli->outbuf,13,0,True);
526 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
527 cli_setup_packet(cli);
529 SCVAL(cli->outbuf,smb_vwv0,0xFF);
530 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
531 SSVAL(cli->outbuf,smb_vwv3,2);
532 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
533 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
534 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
535 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
536 SIVAL(cli->outbuf,smb_vwv11,capabilities);
537 p = smb_buf(cli->outbuf);
538 if (lm_response.length) {
539 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
541 if (nt_response.length) {
542 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
544 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
546 /* Upper case here might help some NTLMv2 implementations */
547 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
548 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
549 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
550 cli_setup_bcc(cli, p);
552 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
553 result = cli_nt_error(cli);
557 /* show_msg(cli->inbuf); */
559 if (cli_is_error(cli)) {
560 result = cli_nt_error(cli);
565 ok = cli_simple_set_signing(cli, session_key, lm_response);
567 ok = cli_simple_set_signing(cli, session_key, nt_response);
570 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
571 result = NT_STATUS_ACCESS_DENIED;
576 /* use the returned vuid from now on */
577 cli->vuid = SVAL(cli->inbuf,smb_uid);
579 p = smb_buf(cli->inbuf);
580 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
582 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
584 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
587 if (strstr(cli->server_type, "Samba")) {
588 cli->is_samba = True;
591 result = cli_set_username(cli, user);
592 if (!NT_STATUS_IS_OK(result)) {
596 if (session_key.data) {
597 /* Have plaintext orginal */
598 cli_set_session_key(cli, session_key);
601 result = NT_STATUS_OK;
603 data_blob_free(&lm_response);
604 data_blob_free(&nt_response);
605 data_blob_free(&session_key);
609 /****************************************************************************
610 Send a extended security session setup blob
611 ****************************************************************************/
613 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
615 uint32 capabilities = cli_session_setup_capabilities(cli);
618 capabilities |= CAP_EXTENDED_SECURITY;
620 /* send a session setup command */
621 memset(cli->outbuf,'\0',smb_size);
623 cli_set_message(cli->outbuf,12,0,True);
624 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
626 cli_setup_packet(cli);
628 SCVAL(cli->outbuf,smb_vwv0,0xFF);
629 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
630 SSVAL(cli->outbuf,smb_vwv3,2);
631 SSVAL(cli->outbuf,smb_vwv4,1);
632 SIVAL(cli->outbuf,smb_vwv5,0);
633 SSVAL(cli->outbuf,smb_vwv7,blob.length);
634 SIVAL(cli->outbuf,smb_vwv10,capabilities);
635 p = smb_buf(cli->outbuf);
636 memcpy(p, blob.data, blob.length);
638 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
639 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
640 cli_setup_bcc(cli, p);
641 return cli_send_smb(cli);
644 /****************************************************************************
645 Send a extended security session setup blob, returning a reply blob.
646 ****************************************************************************/
648 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
650 DATA_BLOB blob2 = data_blob_null;
654 if (!cli_receive_smb(cli))
657 show_msg(cli->inbuf);
659 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
660 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
664 /* use the returned vuid from now on */
665 cli->vuid = SVAL(cli->inbuf,smb_uid);
667 p = smb_buf(cli->inbuf);
669 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
672 p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
675 /* w2k with kerberos doesn't properly null terminate this field */
676 len = smb_bufrem(cli->inbuf, p);
677 if (p + len < cli->inbuf + cli->bufsize+SAFETY_MARGIN - 2) {
678 char *end_of_buf = p + len;
681 /* Now it's null terminated. */
682 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
685 * See if there's another string. If so it's the
686 * server domain (part of the 'standard' Samba
689 if (p < end_of_buf) {
690 p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
695 * No room to null terminate so we can't see if there
696 * is another string (server_domain) afterwards.
698 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
704 /* The following is calculated from :
706 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
707 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
711 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
713 struct cli_sesssetup_blob_state {
714 struct tevent_context *ev;
715 struct cli_state *cli;
717 uint16_t max_blob_size;
726 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
727 struct tevent_req **psubreq);
728 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
730 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
731 struct tevent_context *ev,
732 struct cli_state *cli,
735 struct tevent_req *req, *subreq;
736 struct cli_sesssetup_blob_state *state;
738 req = tevent_req_create(mem_ctx, &state,
739 struct cli_sesssetup_blob_state);
747 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
748 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
749 "(was %u, need minimum %u)\n",
750 (unsigned int)cli->max_xmit,
751 BASE_SESSSETUP_BLOB_PACKET_SIZE));
752 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
753 return tevent_req_post(req, ev);
755 state->max_blob_size =
756 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
758 if (!cli_sesssetup_blob_next(state, &subreq)) {
759 tevent_req_nomem(NULL, req);
760 return tevent_req_post(req, ev);
762 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
766 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
767 struct tevent_req **psubreq)
769 struct tevent_req *subreq;
772 SCVAL(state->vwv+0, 0, 0xFF);
773 SCVAL(state->vwv+0, 1, 0);
774 SSVAL(state->vwv+1, 0, 0);
775 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
776 SSVAL(state->vwv+3, 0, 2);
777 SSVAL(state->vwv+4, 0, 1);
778 SIVAL(state->vwv+5, 0, 0);
780 thistime = MIN(state->blob.length, state->max_blob_size);
781 SSVAL(state->vwv+7, 0, thistime);
783 SSVAL(state->vwv+8, 0, 0);
784 SSVAL(state->vwv+9, 0, 0);
785 SIVAL(state->vwv+10, 0,
786 cli_session_setup_capabilities(state->cli)
787 | CAP_EXTENDED_SECURITY);
789 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
791 if (state->buf == NULL) {
794 state->blob.data += thistime;
795 state->blob.length -= thistime;
797 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
799 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
801 if (state->buf == NULL) {
804 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
806 talloc_get_size(state->buf), state->buf);
807 if (subreq == NULL) {
814 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
816 struct tevent_req *req = tevent_req_callback_data(
817 subreq, struct tevent_req);
818 struct cli_sesssetup_blob_state *state = tevent_req_data(
819 req, struct cli_sesssetup_blob_state);
820 struct cli_state *cli = state->cli;
827 uint16_t blob_length;
829 status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
830 if (!NT_STATUS_IS_OK(status)
831 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
833 tevent_req_nterror(req, status);
837 state->status = status;
838 TALLOC_FREE(state->buf);
840 state->inbuf = (char *)cli_smb_inbuf(subreq);
841 cli->vuid = SVAL(state->inbuf, smb_uid);
843 blob_length = SVAL(vwv+3, 0);
844 if (blob_length > num_bytes) {
846 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
849 state->ret_blob = data_blob_const(bytes, blob_length);
851 p = bytes + blob_length;
853 p += clistr_pull(state->inbuf, cli->server_os,
854 (char *)p, sizeof(fstring),
855 bytes+num_bytes-p, STR_TERMINATE);
856 p += clistr_pull(state->inbuf, cli->server_type,
857 (char *)p, sizeof(fstring),
858 bytes+num_bytes-p, STR_TERMINATE);
859 p += clistr_pull(state->inbuf, cli->server_domain,
860 (char *)p, sizeof(fstring),
861 bytes+num_bytes-p, STR_TERMINATE);
863 if (strstr(cli->server_type, "Samba")) {
864 cli->is_samba = True;
867 if (state->blob.length != 0) {
872 if (!cli_sesssetup_blob_next(state, &subreq)) {
873 tevent_req_nomem(NULL, req);
876 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
879 tevent_req_done(req);
882 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
887 struct cli_sesssetup_blob_state *state = tevent_req_data(
888 req, struct cli_sesssetup_blob_state);
892 if (tevent_req_is_nterror(req, &status)) {
893 state->cli->vuid = 0;
897 inbuf = talloc_move(mem_ctx, &state->inbuf);
899 *pblob = state->ret_blob;
901 if (pinbuf != NULL) {
904 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
905 return state->status;
910 /****************************************************************************
911 Use in-memory credentials cache
912 ****************************************************************************/
914 static void use_in_memory_ccache(void) {
915 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
918 /****************************************************************************
919 Do a spnego/kerberos encrypted session setup.
920 ****************************************************************************/
922 struct cli_session_setup_kerberos_state {
923 struct cli_state *cli;
924 DATA_BLOB negTokenTarg;
925 DATA_BLOB session_key_krb5;
926 ADS_STATUS ads_status;
929 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
931 static struct tevent_req *cli_session_setup_kerberos_send(
932 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
933 const char *principal, const char *workgroup)
935 struct tevent_req *req, *subreq;
936 struct cli_session_setup_kerberos_state *state;
939 DEBUG(2,("Doing kerberos session setup\n"));
941 req = tevent_req_create(mem_ctx, &state,
942 struct cli_session_setup_kerberos_state);
947 state->ads_status = ADS_SUCCESS;
949 cli_temp_set_signing(cli);
952 * Ok, this is cheated: spnego_gen_negTokenTarg can block if
953 * we have to acquire a ticket. To be fixed later :-)
955 rc = spnego_gen_negTokenTarg(principal, 0, &state->negTokenTarg,
956 &state->session_key_krb5, 0, NULL);
958 DEBUG(1, ("cli_session_setup_kerberos: "
959 "spnego_gen_negTokenTarg failed: %s\n",
961 state->ads_status = ADS_ERROR_KRB5(rc);
962 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
963 return tevent_req_post(req, ev);
967 file_save("negTokenTarg.dat", state->negTokenTarg.data,
968 state->negTokenTarg.length);
971 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
972 if (tevent_req_nomem(subreq, req)) {
973 return tevent_req_post(req, ev);
975 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
979 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
981 struct tevent_req *req = tevent_req_callback_data(
982 subreq, struct tevent_req);
983 struct cli_session_setup_kerberos_state *state = tevent_req_data(
984 req, struct cli_session_setup_kerberos_state);
988 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
989 if (!NT_STATUS_IS_OK(status)) {
991 tevent_req_nterror(req, status);
995 cli_set_session_key(state->cli, state->session_key_krb5);
997 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
999 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1000 TALLOC_FREE(subreq);
1001 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1004 TALLOC_FREE(subreq);
1005 tevent_req_done(req);
1008 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1010 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1011 req, struct cli_session_setup_kerberos_state);
1014 if (tevent_req_is_nterror(req, &status)) {
1015 return ADS_ERROR_NT(status);
1017 return state->ads_status;
1020 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1021 const char *principal,
1022 const char *workgroup)
1024 struct tevent_context *ev;
1025 struct tevent_req *req;
1026 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1028 if (cli_has_async_calls(cli)) {
1029 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1031 ev = tevent_context_init(talloc_tos());
1035 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
1040 if (!tevent_req_poll(req, ev)) {
1041 status = ADS_ERROR_SYSTEM(errno);
1044 status = cli_session_setup_kerberos_recv(req);
1049 #endif /* HAVE_KRB5 */
1051 /****************************************************************************
1052 Do a spnego/NTLMSSP encrypted session setup.
1053 ****************************************************************************/
1055 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
1056 const char *pass, const char *domain)
1058 struct ntlmssp_state *ntlmssp_state;
1062 DATA_BLOB blob = data_blob_null;
1063 DATA_BLOB blob_in = data_blob_null;
1064 DATA_BLOB blob_out = data_blob_null;
1066 cli_temp_set_signing(cli);
1068 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
1071 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
1073 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
1076 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
1079 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
1084 nt_status = ntlmssp_update(ntlmssp_state,
1085 blob_in, &blob_out);
1086 data_blob_free(&blob_in);
1087 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
1089 /* and wrap it in a SPNEGO wrapper */
1090 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
1092 /* wrap it in SPNEGO */
1093 msg1 = spnego_gen_auth(blob_out);
1096 /* now send that blob on its way */
1097 if (!cli_session_setup_blob_send(cli, msg1)) {
1098 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
1099 nt_status = NT_STATUS_UNSUCCESSFUL;
1101 blob = cli_session_setup_blob_receive(cli);
1103 nt_status = cli_nt_error(cli);
1104 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
1105 if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
1106 nt_status = NT_STATUS_ACCESS_DENIED;
1108 nt_status = NT_STATUS_UNSUCCESSFUL;
1112 data_blob_free(&msg1);
1116 if (NT_STATUS_IS_OK(nt_status)) {
1117 nt_status = NT_STATUS_UNSUCCESSFUL;
1119 } else if ((turn == 1) &&
1120 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1121 DATA_BLOB tmp_blob = data_blob_null;
1122 /* the server might give us back two challenges */
1123 if (!spnego_parse_challenge(blob, &blob_in,
1125 DEBUG(3,("Failed to parse challenges\n"));
1126 nt_status = NT_STATUS_INVALID_PARAMETER;
1128 data_blob_free(&tmp_blob);
1130 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
1132 DEBUG(3,("Failed to parse auth response\n"));
1133 if (NT_STATUS_IS_OK(nt_status)
1134 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1135 nt_status = NT_STATUS_INVALID_PARAMETER;
1138 data_blob_free(&blob);
1139 data_blob_free(&blob_out);
1141 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
1143 data_blob_free(&blob_in);
1145 if (NT_STATUS_IS_OK(nt_status)) {
1147 if (cli->server_domain[0] == '\0') {
1148 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
1150 cli_set_session_key(cli, ntlmssp_state->session_key);
1152 if (cli_simple_set_signing(
1153 cli, ntlmssp_state->session_key, data_blob_null)) {
1155 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
1156 nt_status = NT_STATUS_ACCESS_DENIED;
1161 /* we have a reference conter on ntlmssp_state, if we are signing
1162 then the state will be kept by the signing engine */
1164 ntlmssp_end(&ntlmssp_state);
1166 if (!NT_STATUS_IS_OK(nt_status)) {
1172 /****************************************************************************
1173 Do a spnego encrypted session setup.
1175 user_domain: The shortname of the domain the user/machine is a member of.
1176 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1177 ****************************************************************************/
1179 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1180 const char *pass, const char *user_domain,
1181 const char * dest_realm)
1183 char *principal = NULL;
1184 char *OIDs[ASN1_MAX_OIDS];
1187 const char *p = NULL;
1188 char *account = NULL;
1191 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1193 /* the server might not even do spnego */
1194 if (cli->secblob.length <= 16) {
1195 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1200 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1203 /* there is 16 bytes of GUID before the real spnego packet starts */
1204 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1206 /* The server sent us the first part of the SPNEGO exchange in the
1207 * negprot reply. It is WRONG to depend on the principal sent in the
1208 * negprot reply, but right now we do it. If we don't receive one,
1209 * we try to best guess, then fall back to NTLM. */
1210 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
1211 data_blob_free(&blob);
1212 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1214 data_blob_free(&blob);
1216 /* make sure the server understands kerberos */
1217 for (i=0;OIDs[i];i++) {
1219 DEBUG(3,("got OID=%s\n", OIDs[i]));
1221 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1222 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1223 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1224 cli->got_kerberos_mechanism = True;
1226 talloc_free(OIDs[i]);
1229 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1231 status = cli_set_username(cli, user);
1232 if (!NT_STATUS_IS_OK(status)) {
1233 return ADS_ERROR_NT(status);
1237 /* If password is set we reauthenticate to kerberos server
1238 * and do not store results */
1240 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1243 if (pass && *pass) {
1246 use_in_memory_ccache();
1247 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1250 TALLOC_FREE(principal);
1251 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1252 if (cli->fallback_after_kerberos)
1254 return ADS_ERROR_KRB5(ret);
1258 /* If we get a bad principal, try to guess it if
1259 we have a valid host NetBIOS name.
1261 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1262 TALLOC_FREE(principal);
1265 if (principal == NULL &&
1266 !is_ipaddress(cli->desthost) &&
1267 !strequal(STAR_SMBSERVER,
1270 char *machine = NULL;
1272 DEBUG(3,("cli_session_setup_spnego: got a "
1273 "bad server principal, trying to guess ...\n"));
1275 host = strchr_m(cli->desthost, '.');
1277 machine = SMB_STRNDUP(cli->desthost,
1278 host - cli->desthost);
1280 machine = SMB_STRDUP(cli->desthost);
1282 if (machine == NULL) {
1283 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1287 realm = SMB_STRDUP(dest_realm);
1290 realm = kerberos_get_default_realm_from_ccache();
1292 if (realm && *realm) {
1293 principal = talloc_asprintf(NULL, "%s$@%s",
1298 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1300 DEBUG(3,("cli_session_setup_spnego: guessed "
1301 "server principal=%s\n",
1302 principal ? principal : "<null>"));
1309 rc = cli_session_setup_kerberos(cli, principal,
1311 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1312 TALLOC_FREE(principal);
1319 TALLOC_FREE(principal);
1323 account = talloc_strdup(talloc_tos(), user);
1325 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1328 /* when falling back to ntlmssp while authenticating with a machine
1329 * account strip off the realm - gd */
1331 if ((p = strchr_m(user, '@')) != NULL) {
1332 account[PTR_DIFF(p,user)] = '\0';
1335 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1338 /****************************************************************************
1339 Send a session setup. The username and workgroup is in UNIX character
1340 format and must be converted to DOS codepage format before sending. If the
1341 password is in plaintext, the same should be done.
1342 ****************************************************************************/
1344 NTSTATUS cli_session_setup(struct cli_state *cli,
1346 const char *pass, int passlen,
1347 const char *ntpass, int ntpasslen,
1348 const char *workgroup)
1354 fstrcpy(user2, user);
1363 /* allow for workgroups as part of the username */
1364 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1365 (p=strchr_m(user2,*lp_winbind_separator()))) {
1371 if (cli->protocol < PROTOCOL_LANMAN1) {
1372 return NT_STATUS_OK;
1375 /* now work out what sort of session setup we are going to
1376 do. I have split this into separate functions to make the
1377 flow a bit easier to understand (tridge) */
1379 /* if its an older server then we have to use the older request format */
1381 if (cli->protocol < PROTOCOL_NT1) {
1382 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1383 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1385 return NT_STATUS_ACCESS_DENIED;
1388 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1389 !lp_client_plaintext_auth() && (*pass)) {
1390 DEBUG(1, ("Server requested plaintext password but "
1391 "'client plaintext auth' is disabled\n"));
1392 return NT_STATUS_ACCESS_DENIED;
1395 return cli_session_setup_lanman2(cli, user, pass, passlen,
1399 /* if no user is supplied then we have to do an anonymous connection.
1400 passwords are ignored */
1402 if (!user || !*user)
1403 return cli_session_setup_guest(cli);
1405 /* if the server is share level then send a plaintext null
1406 password at this point. The password is sent in the tree
1409 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1410 return cli_session_setup_plaintext(cli, user, "", workgroup);
1412 /* if the server doesn't support encryption then we have to use
1413 plaintext. The second password is ignored */
1415 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1416 if (!lp_client_plaintext_auth() && (*pass)) {
1417 DEBUG(1, ("Server requested plaintext password but "
1418 "'client plaintext auth' is disabled\n"));
1419 return NT_STATUS_ACCESS_DENIED;
1421 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1424 /* if the server supports extended security then use SPNEGO */
1426 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1427 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1429 if (!ADS_ERR_OK(status)) {
1430 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1431 return ads_ntstatus(status);
1436 /* otherwise do a NT1 style session setup */
1437 status = cli_session_setup_nt1(cli, user, pass, passlen,
1438 ntpass, ntpasslen, workgroup);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 DEBUG(3,("cli_session_setup: NT1 session setup "
1441 "failed: %s\n", nt_errstr(status)));
1446 if (strstr(cli->server_type, "Samba")) {
1447 cli->is_samba = True;
1450 return NT_STATUS_OK;
1453 /****************************************************************************
1455 *****************************************************************************/
1457 bool cli_ulogoff(struct cli_state *cli)
1459 memset(cli->outbuf,'\0',smb_size);
1460 cli_set_message(cli->outbuf,2,0,True);
1461 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1462 cli_setup_packet(cli);
1463 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1464 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1467 if (!cli_receive_smb(cli))
1470 if (cli_is_error(cli)) {
1478 /****************************************************************************
1480 ****************************************************************************/
1482 struct cli_tcon_andx_state {
1483 struct cli_state *cli;
1488 static void cli_tcon_andx_done(struct tevent_req *subreq);
1490 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1491 struct event_context *ev,
1492 struct cli_state *cli,
1493 const char *share, const char *dev,
1494 const char *pass, int passlen,
1495 struct tevent_req **psmbreq)
1497 struct tevent_req *req, *subreq;
1498 struct cli_tcon_andx_state *state;
1504 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1511 fstrcpy(cli->share, share);
1513 /* in user level security don't send a password now */
1514 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1517 } else if (pass == NULL) {
1518 DEBUG(1, ("Server not using user level security and no "
1519 "password supplied.\n"));
1523 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1524 *pass && passlen != 24) {
1525 if (!lp_client_lanman_auth()) {
1526 DEBUG(1, ("Server requested LANMAN password "
1527 "(share-level security) but "
1528 "'client lanman auth' is disabled\n"));
1533 * Non-encrypted passwords - convert to DOS codepage before
1537 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1539 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1540 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1542 if (!lp_client_plaintext_auth() && (*pass)) {
1543 DEBUG(1, ("Server requested plaintext "
1544 "password but 'client plaintext "
1545 "auth' is disabled\n"));
1550 * Non-encrypted passwords - convert to DOS codepage
1553 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1555 if (passlen == -1) {
1556 DEBUG(1, ("clistr_push(pword) failed\n"));
1561 memcpy(pword, pass, passlen);
1566 SCVAL(vwv+0, 0, 0xFF);
1569 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1570 SSVAL(vwv+3, 0, passlen);
1573 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1575 bytes = talloc_array(state, uint8_t, 0);
1581 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1582 cli->desthost, share);
1587 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1592 * Add the devicetype
1594 tmp = talloc_strdup_upper(talloc_tos(), dev);
1599 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1602 if (bytes == NULL) {
1607 state->bytes.iov_base = (void *)bytes;
1608 state->bytes.iov_len = talloc_get_size(bytes);
1610 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1612 if (subreq == NULL) {
1616 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1621 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1622 return tevent_req_post(req, ev);
1625 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1626 struct event_context *ev,
1627 struct cli_state *cli,
1628 const char *share, const char *dev,
1629 const char *pass, int passlen)
1631 struct tevent_req *req, *subreq;
1634 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1639 status = cli_smb_req_send(subreq);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 tevent_req_nterror(req, status);
1642 return tevent_req_post(req, ev);
1647 static void cli_tcon_andx_done(struct tevent_req *subreq)
1649 struct tevent_req *req = tevent_req_callback_data(
1650 subreq, struct tevent_req);
1651 struct cli_tcon_andx_state *state = tevent_req_data(
1652 req, struct cli_tcon_andx_state);
1653 struct cli_state *cli = state->cli;
1654 char *inbuf = (char *)cli_smb_inbuf(subreq);
1661 status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
1662 if (!NT_STATUS_IS_OK(status)) {
1663 TALLOC_FREE(subreq);
1664 tevent_req_nterror(req, status);
1668 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1669 STR_TERMINATE|STR_ASCII);
1671 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1672 /* almost certainly win95 - enable bug fixes */
1677 * Make sure that we have the optional support 16-bit field. WCT > 2.
1678 * Avoids issues when connecting to Win9x boxes sharing files
1681 cli->dfsroot = false;
1683 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1684 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1687 cli->cnum = SVAL(inbuf,smb_tid);
1688 tevent_req_done(req);
1691 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1693 return tevent_req_simple_recv_ntstatus(req);
1696 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1697 const char *dev, const char *pass, int passlen)
1699 TALLOC_CTX *frame = talloc_stackframe();
1700 struct event_context *ev;
1701 struct tevent_req *req;
1702 NTSTATUS status = NT_STATUS_OK;
1704 if (cli_has_async_calls(cli)) {
1706 * Can't use sync call while an async call is in flight
1708 status = NT_STATUS_INVALID_PARAMETER;
1712 ev = event_context_init(frame);
1714 status = NT_STATUS_NO_MEMORY;
1718 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1720 status = NT_STATUS_NO_MEMORY;
1724 if (!tevent_req_poll(req, ev)) {
1725 status = map_nt_error_from_unix(errno);
1729 status = cli_tcon_andx_recv(req);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 cli_set_error(cli, status);
1738 /****************************************************************************
1739 Send a tree disconnect.
1740 ****************************************************************************/
1742 bool cli_tdis(struct cli_state *cli)
1744 memset(cli->outbuf,'\0',smb_size);
1745 cli_set_message(cli->outbuf,0,0,True);
1746 SCVAL(cli->outbuf,smb_com,SMBtdis);
1747 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1748 cli_setup_packet(cli);
1751 if (!cli_receive_smb(cli))
1754 if (cli_is_error(cli)) {
1762 /****************************************************************************
1763 Send a negprot command.
1764 ****************************************************************************/
1766 void cli_negprot_sendsync(struct cli_state *cli)
1771 if (cli->protocol < PROTOCOL_NT1)
1772 cli->use_spnego = False;
1774 memset(cli->outbuf,'\0',smb_size);
1776 /* setup the protocol strings */
1777 cli_set_message(cli->outbuf,0,0,True);
1779 p = smb_buf(cli->outbuf);
1780 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1781 if (prots[numprots].prot > cli->protocol) {
1785 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1788 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1789 cli_setup_bcc(cli, p);
1790 cli_setup_packet(cli);
1792 SCVAL(smb_buf(cli->outbuf),0,2);
1797 /****************************************************************************
1798 Send a negprot command.
1799 ****************************************************************************/
1801 struct cli_negprot_state {
1802 struct cli_state *cli;
1805 static void cli_negprot_done(struct tevent_req *subreq);
1807 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1808 struct event_context *ev,
1809 struct cli_state *cli)
1811 struct tevent_req *req, *subreq;
1812 struct cli_negprot_state *state;
1813 uint8_t *bytes = NULL;
1817 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1823 if (cli->protocol < PROTOCOL_NT1)
1824 cli->use_spnego = False;
1826 /* setup the protocol strings */
1827 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1829 if (prots[numprots].prot > cli->protocol) {
1832 bytes = (uint8_t *)talloc_append_blob(
1833 state, bytes, data_blob_const(&c, sizeof(c)));
1834 if (tevent_req_nomem(bytes, req)) {
1835 return tevent_req_post(req, ev);
1837 bytes = smb_bytes_push_str(bytes, false,
1838 prots[numprots].name,
1839 strlen(prots[numprots].name)+1,
1841 if (tevent_req_nomem(bytes, req)) {
1842 return tevent_req_post(req, ev);
1849 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
1850 talloc_get_size(bytes), bytes);
1853 if (tevent_req_nomem(subreq, req)) {
1854 return tevent_req_post(req, ev);
1856 tevent_req_set_callback(subreq, cli_negprot_done, req);
1860 static void cli_negprot_done(struct tevent_req *subreq)
1862 struct tevent_req *req = tevent_req_callback_data(
1863 subreq, struct tevent_req);
1864 struct cli_negprot_state *state = tevent_req_data(
1865 req, struct cli_negprot_state);
1866 struct cli_state *cli = state->cli;
1874 status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
1875 if (!NT_STATUS_IS_OK(status)) {
1876 TALLOC_FREE(subreq);
1877 tevent_req_nterror(req, status);
1881 protnum = SVAL(vwv, 0);
1883 if ((protnum >= ARRAY_SIZE(prots))
1884 || (prots[protnum].prot > cli->protocol)) {
1885 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1889 cli->protocol = prots[protnum].prot;
1891 if ((cli->protocol < PROTOCOL_NT1) &&
1892 client_is_signing_mandatory(cli)) {
1893 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1894 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1898 if (cli->protocol >= PROTOCOL_NT1) {
1900 bool negotiated_smb_signing = false;
1903 cli->sec_mode = CVAL(vwv + 1, 0);
1904 cli->max_mux = SVAL(vwv + 1, 1);
1905 cli->max_xmit = IVAL(vwv + 3, 1);
1906 cli->sesskey = IVAL(vwv + 7, 1);
1907 cli->serverzone = SVALS(vwv + 15, 1);
1908 cli->serverzone *= 60;
1909 /* this time arrives in real GMT */
1910 ts = interpret_long_date(((char *)(vwv+11))+1);
1911 cli->servertime = ts.tv_sec;
1912 cli->secblob = data_blob(bytes, num_bytes);
1913 cli->capabilities = IVAL(vwv + 9, 1);
1914 if (cli->capabilities & CAP_RAW_MODE) {
1915 cli->readbraw_supported = True;
1916 cli->writebraw_supported = True;
1918 /* work out if they sent us a workgroup */
1919 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1920 smb_buflen(cli->inbuf) > 8) {
1921 clistr_pull(cli->inbuf, cli->server_domain,
1922 bytes+8, sizeof(cli->server_domain),
1924 STR_UNICODE|STR_NOALIGN);
1928 * As signing is slow we only turn it on if either the client or
1929 * the server require it. JRA.
1932 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1933 /* Fail if server says signing is mandatory and we don't want to support it. */
1934 if (!client_is_signing_allowed(cli)) {
1935 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1936 tevent_req_nterror(req,
1937 NT_STATUS_ACCESS_DENIED);
1940 negotiated_smb_signing = true;
1941 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
1942 /* Fail if client says signing is mandatory and the server doesn't support it. */
1943 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1944 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1945 tevent_req_nterror(req,
1946 NT_STATUS_ACCESS_DENIED);
1949 negotiated_smb_signing = true;
1950 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1951 negotiated_smb_signing = true;
1954 if (negotiated_smb_signing) {
1955 cli_set_signing_negotiated(cli);
1958 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1959 SAFE_FREE(cli->outbuf);
1960 SAFE_FREE(cli->inbuf);
1961 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1962 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1963 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1966 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1967 cli->use_spnego = False;
1968 cli->sec_mode = SVAL(vwv + 1, 0);
1969 cli->max_xmit = SVAL(vwv + 2, 0);
1970 cli->max_mux = SVAL(vwv + 3, 0);
1971 cli->sesskey = IVAL(vwv + 6, 0);
1972 cli->serverzone = SVALS(vwv + 10, 0);
1973 cli->serverzone *= 60;
1974 /* this time is converted to GMT by make_unix_date */
1975 cli->servertime = cli_make_unix_date(
1976 cli, (char *)(vwv + 8));
1977 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1978 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1979 cli->secblob = data_blob(bytes, num_bytes);
1981 /* the old core protocol */
1982 cli->use_spnego = False;
1984 cli->serverzone = get_time_zone(time(NULL));
1987 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1989 /* a way to force ascii SMB */
1990 if (getenv("CLI_FORCE_ASCII"))
1991 cli->capabilities &= ~CAP_UNICODE;
1993 tevent_req_done(req);
1996 NTSTATUS cli_negprot_recv(struct tevent_req *req)
1998 return tevent_req_simple_recv_ntstatus(req);
2001 NTSTATUS cli_negprot(struct cli_state *cli)
2003 TALLOC_CTX *frame = talloc_stackframe();
2004 struct event_context *ev;
2005 struct tevent_req *req;
2006 NTSTATUS status = NT_STATUS_OK;
2008 if (cli_has_async_calls(cli)) {
2010 * Can't use sync call while an async call is in flight
2012 status = NT_STATUS_INVALID_PARAMETER;
2016 ev = event_context_init(frame);
2018 status = NT_STATUS_NO_MEMORY;
2022 req = cli_negprot_send(frame, ev, cli);
2024 status = NT_STATUS_NO_MEMORY;
2028 if (!tevent_req_poll(req, ev)) {
2029 status = map_nt_error_from_unix(errno);
2033 status = cli_negprot_recv(req);
2036 if (!NT_STATUS_IS_OK(status)) {
2037 cli_set_error(cli, status);
2042 /****************************************************************************
2043 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2044 ****************************************************************************/
2046 bool cli_session_request(struct cli_state *cli,
2047 struct nmb_name *calling, struct nmb_name *called)
2053 /* 445 doesn't have session request */
2054 if (cli->port == 445)
2057 memcpy(&(cli->calling), calling, sizeof(*calling));
2058 memcpy(&(cli->called ), called , sizeof(*called ));
2060 /* put in the destination name */
2062 tmp = name_mangle(talloc_tos(), cli->called.name,
2063 cli->called.name_type);
2068 p = cli->outbuf+len;
2069 memcpy(p, tmp, name_len(tmp));
2070 len += name_len(tmp);
2075 tmp = name_mangle(talloc_tos(), cli->calling.name,
2076 cli->calling.name_type);
2081 p = cli->outbuf+len;
2082 memcpy(p, tmp, name_len(tmp));
2083 len += name_len(tmp);
2086 /* send a session request (RFC 1002) */
2087 /* setup the packet length
2088 * Remove four bytes from the length count, since the length
2089 * field in the NBT Session Service header counts the number
2090 * of bytes which follow. The cli_send_smb() function knows
2091 * about this and accounts for those four bytes.
2095 _smb_setlen(cli->outbuf,len);
2096 SCVAL(cli->outbuf,0,0x81);
2099 DEBUG(5,("Sent session request\n"));
2101 if (!cli_receive_smb(cli))
2104 if (CVAL(cli->inbuf,0) == 0x84) {
2105 /* C. Hoch 9/14/95 Start */
2106 /* For information, here is the response structure.
2107 * We do the byte-twiddling to for portability.
2108 struct RetargetResponse{
2110 unsigned char flags;
2116 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2117 struct in_addr dest_ip;
2120 /* SESSION RETARGET */
2121 putip((char *)&dest_ip,cli->inbuf+4);
2122 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2124 status = open_socket_out(&cli->dest_ss, port,
2125 LONG_CONNECT_TIMEOUT, &cli->fd);
2126 if (!NT_STATUS_IS_OK(status)) {
2130 DEBUG(3,("Retargeted\n"));
2132 set_socket_options(cli->fd, lp_socket_options());
2139 DEBUG(0,("Retarget recursion - failing\n"));
2143 ret = cli_session_request(cli, calling, called);
2147 } /* C. Hoch 9/14/95 End */
2149 if (CVAL(cli->inbuf,0) != 0x82) {
2150 /* This is the wrong place to put the error... JRA. */
2151 cli->rap_error = CVAL(cli->inbuf,4);
2161 static void smb_sock_connected(struct tevent_req *req)
2163 struct fd_struct *pfd = tevent_req_callback_data(
2164 req, struct fd_struct);
2168 status = open_socket_out_defer_recv(req, &fd);
2169 if (NT_STATUS_IS_OK(status)) {
2174 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2175 uint16_t *port, int timeout, int *pfd)
2177 struct event_context *ev;
2178 struct tevent_req *r139, *r445;
2179 struct fd_struct *fd139, *fd445;
2180 NTSTATUS status = NT_STATUS_NO_MEMORY;
2183 return open_socket_out(pss, *port, timeout, pfd);
2186 ev = event_context_init(talloc_tos());
2188 return NT_STATUS_NO_MEMORY;
2191 fd139 = talloc(ev, struct fd_struct);
2192 if (fd139 == NULL) {
2197 fd445 = talloc(ev, struct fd_struct);
2198 if (fd445 == NULL) {
2203 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2205 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2207 if ((r445 == NULL) || (r139 == NULL)) {
2210 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2211 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2213 while ((fd445->fd == -1) && (fd139->fd == -1)
2214 && (tevent_req_is_in_progress(r139)
2215 || tevent_req_is_in_progress(r445))) {
2216 event_loop_once(ev);
2219 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2224 if (fd445->fd != -1) {
2227 status = NT_STATUS_OK;
2230 if (fd139->fd != -1) {
2233 status = NT_STATUS_OK;
2237 status = open_socket_out_defer_recv(r445, &fd445->fd);
2243 /****************************************************************************
2244 Open the client sockets.
2245 ****************************************************************************/
2247 NTSTATUS cli_connect(struct cli_state *cli,
2249 struct sockaddr_storage *dest_ss)
2252 int name_type = 0x20;
2253 TALLOC_CTX *frame = talloc_stackframe();
2254 unsigned int num_addrs = 0;
2256 struct sockaddr_storage *ss_arr = NULL;
2259 /* reasonable default hostname */
2261 host = STAR_SMBSERVER;
2264 fstrcpy(cli->desthost, host);
2266 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2267 if ((p = strchr(cli->desthost, '#'))) {
2268 name_type = strtol(p+1, NULL, 16);
2272 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2273 NTSTATUS status =resolve_name_list(frame,
2278 if (!NT_STATUS_IS_OK(status)) {
2280 return NT_STATUS_BAD_NETWORK_NAME;
2284 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2287 return NT_STATUS_NO_MEMORY;
2292 for (i = 0; i < num_addrs; i++) {
2293 cli->dest_ss = ss_arr[i];
2294 if (getenv("LIBSMB_PROG")) {
2295 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2297 uint16_t port = cli->port;
2299 status = open_smb_socket(&cli->dest_ss, &port,
2300 cli->timeout, &cli->fd);
2301 if (NT_STATUS_IS_OK(status)) {
2305 if (cli->fd == -1) {
2306 char addr[INET6_ADDRSTRLEN];
2307 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2308 DEBUG(2,("Error connecting to %s (%s)\n",
2309 dest_ss?addr:host,strerror(errno)));
2311 /* Exit from loop on first connection. */
2316 if (cli->fd == -1) {
2318 return map_nt_error_from_unix(errno);
2322 *dest_ss = cli->dest_ss;
2325 set_socket_options(cli->fd, lp_socket_options());
2328 return NT_STATUS_OK;
2332 establishes a connection to after the negprot.
2333 @param output_cli A fully initialised cli structure, non-null only on success
2334 @param dest_host The netbios name of the remote host
2335 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2336 @param port (optional) The destination port (0 for default)
2337 @param retry bool. Did this connection fail with a retryable error ?
2340 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2341 const char *my_name,
2342 const char *dest_host,
2343 struct sockaddr_storage *dest_ss, int port,
2344 int signing_state, int flags,
2348 struct nmb_name calling;
2349 struct nmb_name called;
2350 struct cli_state *cli;
2351 struct sockaddr_storage ss;
2357 my_name = global_myname();
2359 if (!(cli = cli_initialise_ex(signing_state))) {
2360 return NT_STATUS_NO_MEMORY;
2363 make_nmb_name(&calling, my_name, 0x0);
2364 make_nmb_name(&called , dest_host, 0x20);
2366 cli_set_port(cli, port);
2367 cli_set_timeout(cli, 10000); /* 10 seconds. */
2377 DEBUG(3,("Connecting to host=%s\n", dest_host));
2379 nt_status = cli_connect(cli, dest_host, &ss);
2380 if (!NT_STATUS_IS_OK(nt_status)) {
2381 char addr[INET6_ADDRSTRLEN];
2382 print_sockaddr(addr, sizeof(addr), &ss);
2383 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2384 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2392 if (!cli_session_request(cli, &calling, &called)) {
2394 DEBUG(1,("session request to %s failed (%s)\n",
2395 called.name, cli_errstr(cli)));
2396 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2400 if (strcmp(called.name, STAR_SMBSERVER)) {
2401 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2404 return NT_STATUS_BAD_NETWORK_NAME;
2407 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2408 cli->use_spnego = False;
2409 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2410 cli->use_kerberos = True;
2412 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2413 cli->use_kerberos) {
2414 cli->fallback_after_kerberos = true;
2417 nt_status = cli_negprot(cli);
2418 if (!NT_STATUS_IS_OK(nt_status)) {
2419 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2425 return NT_STATUS_OK;
2430 establishes a connection right up to doing tconX, password specified.
2431 @param output_cli A fully initialised cli structure, non-null only on success
2432 @param dest_host The netbios name of the remote host
2433 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2434 @param port (optional) The destination port (0 for default)
2435 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2436 @param service_type The 'type' of serivice.
2437 @param user Username, unix string
2438 @param domain User's domain
2439 @param password User's password, unencrypted unix string.
2440 @param retry bool. Did this connection fail with a retryable error ?
2443 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2444 const char *my_name,
2445 const char *dest_host,
2446 struct sockaddr_storage *dest_ss, int port,
2447 const char *service, const char *service_type,
2448 const char *user, const char *domain,
2449 const char *password, int flags,
2454 struct cli_state *cli = NULL;
2455 int pw_len = password ? strlen(password)+1 : 0;
2459 if (password == NULL) {
2463 nt_status = cli_start_connection(&cli, my_name, dest_host,
2464 dest_ss, port, signing_state,
2467 if (!NT_STATUS_IS_OK(nt_status)) {
2471 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2472 cli->use_level_II_oplocks =
2473 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2475 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2477 if (!NT_STATUS_IS_OK(nt_status)) {
2479 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2480 DEBUG(1,("failed session setup with %s\n",
2481 nt_errstr(nt_status)));
2486 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2487 if (!NT_STATUS_IS_OK(nt_status)) {
2488 DEBUG(1,("anonymous failed session setup with %s\n",
2489 nt_errstr(nt_status)));
2496 nt_status = cli_tcon_andx(cli, service, service_type, password,
2498 if (!NT_STATUS_IS_OK(nt_status)) {
2499 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2501 if (NT_STATUS_IS_OK(nt_status)) {
2502 nt_status = NT_STATUS_UNSUCCESSFUL;
2508 nt_status = cli_init_creds(cli, user, domain, password);
2509 if (!NT_STATUS_IS_OK(nt_status)) {
2515 return NT_STATUS_OK;
2518 /****************************************************************************
2519 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2520 ****************************************************************************/
2522 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2523 struct sockaddr_storage *pdest_ss)
2525 struct nmb_name calling, called;
2527 make_nmb_name(&calling, srchost, 0x0);
2530 * If the called name is an IP address
2531 * then use *SMBSERVER immediately.
2534 if(is_ipaddress(desthost)) {
2535 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2537 make_nmb_name(&called, desthost, 0x20);
2540 if (!cli_session_request(*ppcli, &calling, &called)) {
2542 struct nmb_name smbservername;
2544 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2547 * If the name wasn't *SMBSERVER then
2548 * try with *SMBSERVER if the first name fails.
2551 if (nmb_name_equal(&called, &smbservername)) {
2554 * The name used was *SMBSERVER, don't bother with another name.
2557 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2558 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2563 cli_shutdown(*ppcli);
2565 *ppcli = cli_initialise();
2567 /* Out of memory... */
2571 status = cli_connect(*ppcli, desthost, pdest_ss);
2572 if (!NT_STATUS_IS_OK(status) ||
2573 !cli_session_request(*ppcli, &calling, &smbservername)) {
2574 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2575 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2583 /****************************************************************************
2584 Send an old style tcon.
2585 ****************************************************************************/
2586 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2587 const char *service, const char *pass, const char *dev,
2588 uint16 *max_xmit, uint16 *tid)
2592 if (!lp_client_plaintext_auth() && (*pass)) {
2593 DEBUG(1, ("Server requested plaintext password but 'client "
2594 "plaintext auth' is disabled\n"));
2595 return NT_STATUS_ACCESS_DENIED;
2598 memset(cli->outbuf,'\0',smb_size);
2599 memset(cli->inbuf,'\0',smb_size);
2601 cli_set_message(cli->outbuf, 0, 0, True);
2602 SCVAL(cli->outbuf,smb_com,SMBtcon);
2603 cli_setup_packet(cli);
2605 p = smb_buf(cli->outbuf);
2606 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2607 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2608 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2610 cli_setup_bcc(cli, p);
2613 if (!cli_receive_smb(cli)) {
2614 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2617 if (cli_is_error(cli)) {
2618 return cli_nt_error(cli);
2621 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2622 *tid = SVAL(cli->inbuf, smb_vwv1);
2624 return NT_STATUS_OK;
2627 /* Return a cli_state pointing at the IPC$ share for the given server */
2629 struct cli_state *get_ipc_connect(char *server,
2630 struct sockaddr_storage *server_ss,
2631 const struct user_auth_info *user_info)
2633 struct cli_state *cli;
2635 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2637 if (user_info->use_kerberos) {
2638 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2641 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2642 user_info->username ? user_info->username : "",
2644 user_info->password ? user_info->password : "",
2648 if (NT_STATUS_IS_OK(nt_status)) {
2650 } else if (is_ipaddress(server)) {
2651 /* windows 9* needs a correct NMB name for connections */
2652 fstring remote_name;
2654 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2655 cli = get_ipc_connect(remote_name, server_ss, user_info);
2664 * Given the IP address of a master browser on the network, return its
2665 * workgroup and connect to it.
2667 * This function is provided to allow additional processing beyond what
2668 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2669 * browsers and obtain each master browsers' list of domains (in case the
2670 * first master browser is recently on the network and has not yet
2671 * synchronized with other master browsers and therefore does not yet have the
2672 * entire network browse list)
2675 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2676 struct ip_service *mb_ip,
2677 const struct user_auth_info *user_info,
2678 char **pp_workgroup_out)
2680 char addr[INET6_ADDRSTRLEN];
2682 struct cli_state *cli;
2683 struct sockaddr_storage server_ss;
2685 *pp_workgroup_out = NULL;
2687 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2688 DEBUG(99, ("Looking up name of master browser %s\n",
2692 * Do a name status query to find out the name of the master browser.
2693 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2694 * master browser will not respond to a wildcard query (or, at least,
2695 * an NT4 server acting as the domain master browser will not).
2697 * We might be able to use ONLY the query on MSBROWSE, but that's not
2698 * yet been tested with all Windows versions, so until it is, leave
2699 * the original wildcard query as the first choice and fall back to
2700 * MSBROWSE if the wildcard query fails.
2702 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2703 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2705 DEBUG(99, ("Could not retrieve name status for %s\n",
2710 if (!find_master_ip(name, &server_ss)) {
2711 DEBUG(99, ("Could not find master ip for %s\n", name));
2715 *pp_workgroup_out = talloc_strdup(ctx, name);
2717 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2719 print_sockaddr(addr, sizeof(addr), &server_ss);
2720 cli = get_ipc_connect(addr, &server_ss, user_info);
2726 * Return the IP address and workgroup of a master browser on the network, and
2730 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2731 const struct user_auth_info *user_info,
2732 char **pp_workgroup_out)
2734 struct ip_service *ip_list;
2735 struct cli_state *cli;
2738 *pp_workgroup_out = NULL;
2740 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2742 /* Go looking for workgroups by broadcasting on the local network */
2744 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2746 DEBUG(99, ("No master browsers responded\n"));
2750 for (i = 0; i < count; i++) {
2751 char addr[INET6_ADDRSTRLEN];
2752 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2753 DEBUG(99, ("Found master browser %s\n", addr));
2755 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2756 user_info, pp_workgroup_out);