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),
705 /****************************************************************************
706 Send a extended security session setup blob, returning a reply blob.
707 ****************************************************************************/
709 /* The following is calculated from :
711 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
712 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
716 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
718 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
720 int32 remaining = blob.length;
722 DATA_BLOB send_blob = data_blob_null;
723 int32 max_blob_size = 0;
724 DATA_BLOB receive_blob = data_blob_null;
726 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
727 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
728 "(was %u, need minimum %u)\n",
729 (unsigned int)cli->max_xmit,
730 BASE_SESSSETUP_BLOB_PACKET_SIZE));
731 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
735 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
737 while ( remaining > 0) {
738 if (remaining >= max_blob_size) {
739 send_blob.length = max_blob_size;
740 remaining -= max_blob_size;
742 send_blob.length = remaining;
746 send_blob.data = &blob.data[cur];
747 cur += send_blob.length;
749 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
750 (unsigned int)remaining,
751 (unsigned int)send_blob.length,
752 (unsigned int)cur ));
754 if (!cli_session_setup_blob_send(cli, send_blob)) {
755 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
759 receive_blob = cli_session_setup_blob_receive(cli);
760 data_blob_free(&receive_blob);
762 if (cli_is_error(cli) &&
763 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
764 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
765 DEBUG(0, ("cli_session_setup_blob: receive failed "
766 "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
775 /****************************************************************************
776 Use in-memory credentials cache
777 ****************************************************************************/
779 static void use_in_memory_ccache(void) {
780 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
783 /****************************************************************************
784 Do a spnego/kerberos encrypted session setup.
785 ****************************************************************************/
787 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
789 DATA_BLOB negTokenTarg;
790 DATA_BLOB session_key_krb5;
794 cli_temp_set_signing(cli);
796 DEBUG(2,("Doing kerberos session setup\n"));
798 /* generate the encapsulated kerberos5 ticket */
799 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
802 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
804 return ADS_ERROR_KRB5(rc);
808 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
811 if (!cli_session_setup_blob(cli, negTokenTarg)) {
812 nt_status = cli_nt_error(cli);
816 if (cli_is_error(cli)) {
817 nt_status = cli_nt_error(cli);
818 if (NT_STATUS_IS_OK(nt_status)) {
819 nt_status = NT_STATUS_UNSUCCESSFUL;
824 cli_set_session_key(cli, session_key_krb5);
826 if (cli_simple_set_signing(
827 cli, session_key_krb5, data_blob_null)) {
829 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
830 nt_status = NT_STATUS_ACCESS_DENIED;
835 data_blob_free(&negTokenTarg);
836 data_blob_free(&session_key_krb5);
838 return ADS_ERROR_NT(NT_STATUS_OK);
841 data_blob_free(&negTokenTarg);
842 data_blob_free(&session_key_krb5);
844 return ADS_ERROR_NT(nt_status);
846 #endif /* HAVE_KRB5 */
849 /****************************************************************************
850 Do a spnego/NTLMSSP encrypted session setup.
851 ****************************************************************************/
853 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
854 const char *pass, const char *domain)
856 struct ntlmssp_state *ntlmssp_state;
860 DATA_BLOB blob = data_blob_null;
861 DATA_BLOB blob_in = data_blob_null;
862 DATA_BLOB blob_out = data_blob_null;
864 cli_temp_set_signing(cli);
866 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
869 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
871 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
874 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
877 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
882 nt_status = ntlmssp_update(ntlmssp_state,
884 data_blob_free(&blob_in);
885 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
887 /* and wrap it in a SPNEGO wrapper */
888 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
890 /* wrap it in SPNEGO */
891 msg1 = spnego_gen_auth(blob_out);
894 /* now send that blob on its way */
895 if (!cli_session_setup_blob_send(cli, msg1)) {
896 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
897 nt_status = NT_STATUS_UNSUCCESSFUL;
899 blob = cli_session_setup_blob_receive(cli);
901 nt_status = cli_nt_error(cli);
902 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
903 if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
904 nt_status = NT_STATUS_ACCESS_DENIED;
906 nt_status = NT_STATUS_UNSUCCESSFUL;
910 data_blob_free(&msg1);
914 if (NT_STATUS_IS_OK(nt_status)) {
915 nt_status = NT_STATUS_UNSUCCESSFUL;
917 } else if ((turn == 1) &&
918 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
919 DATA_BLOB tmp_blob = data_blob_null;
920 /* the server might give us back two challenges */
921 if (!spnego_parse_challenge(blob, &blob_in,
923 DEBUG(3,("Failed to parse challenges\n"));
924 nt_status = NT_STATUS_INVALID_PARAMETER;
926 data_blob_free(&tmp_blob);
928 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
930 DEBUG(3,("Failed to parse auth response\n"));
931 if (NT_STATUS_IS_OK(nt_status)
932 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
933 nt_status = NT_STATUS_INVALID_PARAMETER;
936 data_blob_free(&blob);
937 data_blob_free(&blob_out);
939 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
941 data_blob_free(&blob_in);
943 if (NT_STATUS_IS_OK(nt_status)) {
945 if (cli->server_domain[0] == '\0') {
946 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
948 cli_set_session_key(cli, ntlmssp_state->session_key);
950 if (cli_simple_set_signing(
951 cli, ntlmssp_state->session_key, data_blob_null)) {
953 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
954 nt_status = NT_STATUS_ACCESS_DENIED;
959 /* we have a reference conter on ntlmssp_state, if we are signing
960 then the state will be kept by the signing engine */
962 ntlmssp_end(&ntlmssp_state);
964 if (!NT_STATUS_IS_OK(nt_status)) {
970 /****************************************************************************
971 Do a spnego encrypted session setup.
973 user_domain: The shortname of the domain the user/machine is a member of.
974 dest_realm: The realm we're connecting to, if NULL we use our default realm.
975 ****************************************************************************/
977 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
978 const char *pass, const char *user_domain,
979 const char * dest_realm)
981 char *principal = NULL;
982 char *OIDs[ASN1_MAX_OIDS];
985 const char *p = NULL;
986 char *account = NULL;
989 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
991 /* the server might not even do spnego */
992 if (cli->secblob.length <= 16) {
993 DEBUG(3,("server didn't supply a full spnego negprot\n"));
998 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1001 /* there is 16 bytes of GUID before the real spnego packet starts */
1002 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1004 /* The server sent us the first part of the SPNEGO exchange in the
1005 * negprot reply. It is WRONG to depend on the principal sent in the
1006 * negprot reply, but right now we do it. If we don't receive one,
1007 * we try to best guess, then fall back to NTLM. */
1008 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
1009 data_blob_free(&blob);
1010 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1012 data_blob_free(&blob);
1014 /* make sure the server understands kerberos */
1015 for (i=0;OIDs[i];i++) {
1017 DEBUG(3,("got OID=%s\n", OIDs[i]));
1019 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1020 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1021 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1022 cli->got_kerberos_mechanism = True;
1024 talloc_free(OIDs[i]);
1027 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1029 status = cli_set_username(cli, user);
1030 if (!NT_STATUS_IS_OK(status)) {
1031 return ADS_ERROR_NT(status);
1035 /* If password is set we reauthenticate to kerberos server
1036 * and do not store results */
1038 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1041 if (pass && *pass) {
1044 use_in_memory_ccache();
1045 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1048 TALLOC_FREE(principal);
1049 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1050 if (cli->fallback_after_kerberos)
1052 return ADS_ERROR_KRB5(ret);
1056 /* If we get a bad principal, try to guess it if
1057 we have a valid host NetBIOS name.
1059 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1060 TALLOC_FREE(principal);
1063 if (principal == NULL &&
1064 !is_ipaddress(cli->desthost) &&
1065 !strequal(STAR_SMBSERVER,
1068 char *machine = NULL;
1070 DEBUG(3,("cli_session_setup_spnego: got a "
1071 "bad server principal, trying to guess ...\n"));
1073 host = strchr_m(cli->desthost, '.');
1075 machine = SMB_STRNDUP(cli->desthost,
1076 host - cli->desthost);
1078 machine = SMB_STRDUP(cli->desthost);
1080 if (machine == NULL) {
1081 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1085 realm = SMB_STRDUP(dest_realm);
1088 realm = kerberos_get_default_realm_from_ccache();
1090 if (realm && *realm) {
1091 principal = talloc_asprintf(NULL, "%s$@%s",
1096 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1098 DEBUG(3,("cli_session_setup_spnego: guessed "
1099 "server principal=%s\n",
1100 principal ? principal : "<null>"));
1107 rc = cli_session_setup_kerberos(cli, principal,
1109 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1110 TALLOC_FREE(principal);
1117 TALLOC_FREE(principal);
1121 account = talloc_strdup(talloc_tos(), user);
1123 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1126 /* when falling back to ntlmssp while authenticating with a machine
1127 * account strip off the realm - gd */
1129 if ((p = strchr_m(user, '@')) != NULL) {
1130 account[PTR_DIFF(p,user)] = '\0';
1133 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1136 /****************************************************************************
1137 Send a session setup. The username and workgroup is in UNIX character
1138 format and must be converted to DOS codepage format before sending. If the
1139 password is in plaintext, the same should be done.
1140 ****************************************************************************/
1142 NTSTATUS cli_session_setup(struct cli_state *cli,
1144 const char *pass, int passlen,
1145 const char *ntpass, int ntpasslen,
1146 const char *workgroup)
1152 fstrcpy(user2, user);
1161 /* allow for workgroups as part of the username */
1162 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1163 (p=strchr_m(user2,*lp_winbind_separator()))) {
1169 if (cli->protocol < PROTOCOL_LANMAN1) {
1170 return NT_STATUS_OK;
1173 /* now work out what sort of session setup we are going to
1174 do. I have split this into separate functions to make the
1175 flow a bit easier to understand (tridge) */
1177 /* if its an older server then we have to use the older request format */
1179 if (cli->protocol < PROTOCOL_NT1) {
1180 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1181 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1183 return NT_STATUS_ACCESS_DENIED;
1186 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1187 !lp_client_plaintext_auth() && (*pass)) {
1188 DEBUG(1, ("Server requested plaintext password but "
1189 "'client plaintext auth' is disabled\n"));
1190 return NT_STATUS_ACCESS_DENIED;
1193 return cli_session_setup_lanman2(cli, user, pass, passlen,
1197 /* if no user is supplied then we have to do an anonymous connection.
1198 passwords are ignored */
1200 if (!user || !*user)
1201 return cli_session_setup_guest(cli);
1203 /* if the server is share level then send a plaintext null
1204 password at this point. The password is sent in the tree
1207 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
1208 return cli_session_setup_plaintext(cli, user, "", workgroup);
1210 /* if the server doesn't support encryption then we have to use
1211 plaintext. The second password is ignored */
1213 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1214 if (!lp_client_plaintext_auth() && (*pass)) {
1215 DEBUG(1, ("Server requested plaintext password but "
1216 "'client plaintext auth' is disabled\n"));
1217 return NT_STATUS_ACCESS_DENIED;
1219 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1222 /* if the server supports extended security then use SPNEGO */
1224 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1225 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1227 if (!ADS_ERR_OK(status)) {
1228 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1229 return ads_ntstatus(status);
1234 /* otherwise do a NT1 style session setup */
1235 status = cli_session_setup_nt1(cli, user, pass, passlen,
1236 ntpass, ntpasslen, workgroup);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 DEBUG(3,("cli_session_setup: NT1 session setup "
1239 "failed: %s\n", nt_errstr(status)));
1244 if (strstr(cli->server_type, "Samba")) {
1245 cli->is_samba = True;
1248 return NT_STATUS_OK;
1251 /****************************************************************************
1253 *****************************************************************************/
1255 bool cli_ulogoff(struct cli_state *cli)
1257 memset(cli->outbuf,'\0',smb_size);
1258 cli_set_message(cli->outbuf,2,0,True);
1259 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1260 cli_setup_packet(cli);
1261 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1262 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1265 if (!cli_receive_smb(cli))
1268 if (cli_is_error(cli)) {
1276 /****************************************************************************
1278 ****************************************************************************/
1280 struct cli_tcon_andx_state {
1281 struct cli_state *cli;
1286 static void cli_tcon_andx_done(struct tevent_req *subreq);
1288 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1289 struct event_context *ev,
1290 struct cli_state *cli,
1291 const char *share, const char *dev,
1292 const char *pass, int passlen,
1293 struct tevent_req **psmbreq)
1295 struct tevent_req *req, *subreq;
1296 struct cli_tcon_andx_state *state;
1302 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1309 fstrcpy(cli->share, share);
1311 /* in user level security don't send a password now */
1312 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1315 } else if (pass == NULL) {
1316 DEBUG(1, ("Server not using user level security and no "
1317 "password supplied.\n"));
1321 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1322 *pass && passlen != 24) {
1323 if (!lp_client_lanman_auth()) {
1324 DEBUG(1, ("Server requested LANMAN password "
1325 "(share-level security) but "
1326 "'client lanman auth' is disabled\n"));
1331 * Non-encrypted passwords - convert to DOS codepage before
1335 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1337 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1338 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1340 if (!lp_client_plaintext_auth() && (*pass)) {
1341 DEBUG(1, ("Server requested plaintext "
1342 "password but 'client plaintext "
1343 "auth' is disabled\n"));
1348 * Non-encrypted passwords - convert to DOS codepage
1351 passlen = clistr_push(cli, pword, pass, sizeof(pword),
1353 if (passlen == -1) {
1354 DEBUG(1, ("clistr_push(pword) failed\n"));
1359 memcpy(pword, pass, passlen);
1364 SCVAL(vwv+0, 0, 0xFF);
1367 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1368 SSVAL(vwv+3, 0, passlen);
1371 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1373 bytes = talloc_array(state, uint8_t, 0);
1379 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1380 cli->desthost, share);
1385 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1390 * Add the devicetype
1392 tmp = talloc_strdup_upper(talloc_tos(), dev);
1397 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1400 if (bytes == NULL) {
1405 state->bytes.iov_base = (void *)bytes;
1406 state->bytes.iov_len = talloc_get_size(bytes);
1408 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1410 if (subreq == NULL) {
1414 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1419 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1420 return tevent_req_post(req, ev);
1423 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1424 struct event_context *ev,
1425 struct cli_state *cli,
1426 const char *share, const char *dev,
1427 const char *pass, int passlen)
1429 struct tevent_req *req, *subreq;
1432 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1437 status = cli_smb_req_send(subreq);
1438 if (!NT_STATUS_IS_OK(status)) {
1439 tevent_req_nterror(req, status);
1440 return tevent_req_post(req, ev);
1445 static void cli_tcon_andx_done(struct tevent_req *subreq)
1447 struct tevent_req *req = tevent_req_callback_data(
1448 subreq, struct tevent_req);
1449 struct cli_tcon_andx_state *state = tevent_req_data(
1450 req, struct cli_tcon_andx_state);
1451 struct cli_state *cli = state->cli;
1452 char *inbuf = (char *)cli_smb_inbuf(subreq);
1459 status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
1460 if (!NT_STATUS_IS_OK(status)) {
1461 TALLOC_FREE(subreq);
1462 tevent_req_nterror(req, status);
1466 clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1467 STR_TERMINATE|STR_ASCII);
1469 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1470 /* almost certainly win95 - enable bug fixes */
1475 * Make sure that we have the optional support 16-bit field. WCT > 2.
1476 * Avoids issues when connecting to Win9x boxes sharing files
1479 cli->dfsroot = false;
1481 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1482 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1485 cli->cnum = SVAL(inbuf,smb_tid);
1486 tevent_req_done(req);
1489 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1491 return tevent_req_simple_recv_ntstatus(req);
1494 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1495 const char *dev, const char *pass, int passlen)
1497 TALLOC_CTX *frame = talloc_stackframe();
1498 struct event_context *ev;
1499 struct tevent_req *req;
1500 NTSTATUS status = NT_STATUS_OK;
1502 if (cli_has_async_calls(cli)) {
1504 * Can't use sync call while an async call is in flight
1506 status = NT_STATUS_INVALID_PARAMETER;
1510 ev = event_context_init(frame);
1512 status = NT_STATUS_NO_MEMORY;
1516 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1518 status = NT_STATUS_NO_MEMORY;
1522 if (!tevent_req_poll(req, ev)) {
1523 status = map_nt_error_from_unix(errno);
1527 status = cli_tcon_andx_recv(req);
1530 if (!NT_STATUS_IS_OK(status)) {
1531 cli_set_error(cli, status);
1536 /****************************************************************************
1537 Send a tree disconnect.
1538 ****************************************************************************/
1540 bool cli_tdis(struct cli_state *cli)
1542 memset(cli->outbuf,'\0',smb_size);
1543 cli_set_message(cli->outbuf,0,0,True);
1544 SCVAL(cli->outbuf,smb_com,SMBtdis);
1545 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1546 cli_setup_packet(cli);
1549 if (!cli_receive_smb(cli))
1552 if (cli_is_error(cli)) {
1560 /****************************************************************************
1561 Send a negprot command.
1562 ****************************************************************************/
1564 void cli_negprot_sendsync(struct cli_state *cli)
1569 if (cli->protocol < PROTOCOL_NT1)
1570 cli->use_spnego = False;
1572 memset(cli->outbuf,'\0',smb_size);
1574 /* setup the protocol strings */
1575 cli_set_message(cli->outbuf,0,0,True);
1577 p = smb_buf(cli->outbuf);
1578 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1579 if (prots[numprots].prot > cli->protocol) {
1583 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1586 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1587 cli_setup_bcc(cli, p);
1588 cli_setup_packet(cli);
1590 SCVAL(smb_buf(cli->outbuf),0,2);
1595 /****************************************************************************
1596 Send a negprot command.
1597 ****************************************************************************/
1599 struct cli_negprot_state {
1600 struct cli_state *cli;
1603 static void cli_negprot_done(struct tevent_req *subreq);
1605 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1606 struct event_context *ev,
1607 struct cli_state *cli)
1609 struct tevent_req *req, *subreq;
1610 struct cli_negprot_state *state;
1611 uint8_t *bytes = NULL;
1615 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1621 if (cli->protocol < PROTOCOL_NT1)
1622 cli->use_spnego = False;
1624 /* setup the protocol strings */
1625 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1627 if (prots[numprots].prot > cli->protocol) {
1630 bytes = (uint8_t *)talloc_append_blob(
1631 state, bytes, data_blob_const(&c, sizeof(c)));
1632 if (tevent_req_nomem(bytes, req)) {
1633 return tevent_req_post(req, ev);
1635 bytes = smb_bytes_push_str(bytes, false,
1636 prots[numprots].name,
1637 strlen(prots[numprots].name)+1,
1639 if (tevent_req_nomem(bytes, req)) {
1640 return tevent_req_post(req, ev);
1647 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
1648 talloc_get_size(bytes), bytes);
1651 if (tevent_req_nomem(subreq, req)) {
1652 return tevent_req_post(req, ev);
1654 tevent_req_set_callback(subreq, cli_negprot_done, req);
1658 static void cli_negprot_done(struct tevent_req *subreq)
1660 struct tevent_req *req = tevent_req_callback_data(
1661 subreq, struct tevent_req);
1662 struct cli_negprot_state *state = tevent_req_data(
1663 req, struct cli_negprot_state);
1664 struct cli_state *cli = state->cli;
1672 status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 TALLOC_FREE(subreq);
1675 tevent_req_nterror(req, status);
1679 protnum = SVAL(vwv, 0);
1681 if ((protnum >= ARRAY_SIZE(prots))
1682 || (prots[protnum].prot > cli->protocol)) {
1683 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1687 cli->protocol = prots[protnum].prot;
1689 if ((cli->protocol < PROTOCOL_NT1) &&
1690 client_is_signing_mandatory(cli)) {
1691 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1692 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1696 if (cli->protocol >= PROTOCOL_NT1) {
1698 bool negotiated_smb_signing = false;
1701 cli->sec_mode = CVAL(vwv + 1, 0);
1702 cli->max_mux = SVAL(vwv + 1, 1);
1703 cli->max_xmit = IVAL(vwv + 3, 1);
1704 cli->sesskey = IVAL(vwv + 7, 1);
1705 cli->serverzone = SVALS(vwv + 15, 1);
1706 cli->serverzone *= 60;
1707 /* this time arrives in real GMT */
1708 ts = interpret_long_date(((char *)(vwv+11))+1);
1709 cli->servertime = ts.tv_sec;
1710 cli->secblob = data_blob(bytes, num_bytes);
1711 cli->capabilities = IVAL(vwv + 9, 1);
1712 if (cli->capabilities & CAP_RAW_MODE) {
1713 cli->readbraw_supported = True;
1714 cli->writebraw_supported = True;
1716 /* work out if they sent us a workgroup */
1717 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1718 smb_buflen(cli->inbuf) > 8) {
1719 clistr_pull(cli->inbuf, cli->server_domain,
1720 bytes+8, sizeof(cli->server_domain),
1722 STR_UNICODE|STR_NOALIGN);
1726 * As signing is slow we only turn it on if either the client or
1727 * the server require it. JRA.
1730 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1731 /* Fail if server says signing is mandatory and we don't want to support it. */
1732 if (!client_is_signing_allowed(cli)) {
1733 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1734 tevent_req_nterror(req,
1735 NT_STATUS_ACCESS_DENIED);
1738 negotiated_smb_signing = true;
1739 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
1740 /* Fail if client says signing is mandatory and the server doesn't support it. */
1741 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1742 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1743 tevent_req_nterror(req,
1744 NT_STATUS_ACCESS_DENIED);
1747 negotiated_smb_signing = true;
1748 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1749 negotiated_smb_signing = true;
1752 if (negotiated_smb_signing) {
1753 cli_set_signing_negotiated(cli);
1756 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1757 SAFE_FREE(cli->outbuf);
1758 SAFE_FREE(cli->inbuf);
1759 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1760 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1761 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1764 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1765 cli->use_spnego = False;
1766 cli->sec_mode = SVAL(vwv + 1, 0);
1767 cli->max_xmit = SVAL(vwv + 2, 0);
1768 cli->max_mux = SVAL(vwv + 3, 0);
1769 cli->sesskey = IVAL(vwv + 6, 0);
1770 cli->serverzone = SVALS(vwv + 10, 0);
1771 cli->serverzone *= 60;
1772 /* this time is converted to GMT by make_unix_date */
1773 cli->servertime = cli_make_unix_date(
1774 cli, (char *)(vwv + 8));
1775 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1776 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1777 cli->secblob = data_blob(bytes, num_bytes);
1779 /* the old core protocol */
1780 cli->use_spnego = False;
1782 cli->serverzone = get_time_zone(time(NULL));
1785 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1787 /* a way to force ascii SMB */
1788 if (getenv("CLI_FORCE_ASCII"))
1789 cli->capabilities &= ~CAP_UNICODE;
1791 tevent_req_done(req);
1794 NTSTATUS cli_negprot_recv(struct tevent_req *req)
1796 return tevent_req_simple_recv_ntstatus(req);
1799 NTSTATUS cli_negprot(struct cli_state *cli)
1801 TALLOC_CTX *frame = talloc_stackframe();
1802 struct event_context *ev;
1803 struct tevent_req *req;
1804 NTSTATUS status = NT_STATUS_OK;
1806 if (cli_has_async_calls(cli)) {
1808 * Can't use sync call while an async call is in flight
1810 status = NT_STATUS_INVALID_PARAMETER;
1814 ev = event_context_init(frame);
1816 status = NT_STATUS_NO_MEMORY;
1820 req = cli_negprot_send(frame, ev, cli);
1822 status = NT_STATUS_NO_MEMORY;
1826 if (!tevent_req_poll(req, ev)) {
1827 status = map_nt_error_from_unix(errno);
1831 status = cli_negprot_recv(req);
1834 if (!NT_STATUS_IS_OK(status)) {
1835 cli_set_error(cli, status);
1840 /****************************************************************************
1841 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1842 ****************************************************************************/
1844 bool cli_session_request(struct cli_state *cli,
1845 struct nmb_name *calling, struct nmb_name *called)
1851 /* 445 doesn't have session request */
1852 if (cli->port == 445)
1855 memcpy(&(cli->calling), calling, sizeof(*calling));
1856 memcpy(&(cli->called ), called , sizeof(*called ));
1858 /* put in the destination name */
1860 tmp = name_mangle(talloc_tos(), cli->called.name,
1861 cli->called.name_type);
1866 p = cli->outbuf+len;
1867 memcpy(p, tmp, name_len(tmp));
1868 len += name_len(tmp);
1873 tmp = name_mangle(talloc_tos(), cli->calling.name,
1874 cli->calling.name_type);
1879 p = cli->outbuf+len;
1880 memcpy(p, tmp, name_len(tmp));
1881 len += name_len(tmp);
1884 /* send a session request (RFC 1002) */
1885 /* setup the packet length
1886 * Remove four bytes from the length count, since the length
1887 * field in the NBT Session Service header counts the number
1888 * of bytes which follow. The cli_send_smb() function knows
1889 * about this and accounts for those four bytes.
1893 _smb_setlen(cli->outbuf,len);
1894 SCVAL(cli->outbuf,0,0x81);
1897 DEBUG(5,("Sent session request\n"));
1899 if (!cli_receive_smb(cli))
1902 if (CVAL(cli->inbuf,0) == 0x84) {
1903 /* C. Hoch 9/14/95 Start */
1904 /* For information, here is the response structure.
1905 * We do the byte-twiddling to for portability.
1906 struct RetargetResponse{
1908 unsigned char flags;
1914 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1915 struct in_addr dest_ip;
1918 /* SESSION RETARGET */
1919 putip((char *)&dest_ip,cli->inbuf+4);
1920 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1922 status = open_socket_out(&cli->dest_ss, port,
1923 LONG_CONNECT_TIMEOUT, &cli->fd);
1924 if (!NT_STATUS_IS_OK(status)) {
1928 DEBUG(3,("Retargeted\n"));
1930 set_socket_options(cli->fd, lp_socket_options());
1937 DEBUG(0,("Retarget recursion - failing\n"));
1941 ret = cli_session_request(cli, calling, called);
1945 } /* C. Hoch 9/14/95 End */
1947 if (CVAL(cli->inbuf,0) != 0x82) {
1948 /* This is the wrong place to put the error... JRA. */
1949 cli->rap_error = CVAL(cli->inbuf,4);
1959 static void smb_sock_connected(struct tevent_req *req)
1961 struct fd_struct *pfd = tevent_req_callback_data(
1962 req, struct fd_struct);
1966 status = open_socket_out_defer_recv(req, &fd);
1967 if (NT_STATUS_IS_OK(status)) {
1972 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1973 uint16_t *port, int timeout, int *pfd)
1975 struct event_context *ev;
1976 struct tevent_req *r139, *r445;
1977 struct fd_struct *fd139, *fd445;
1978 NTSTATUS status = NT_STATUS_NO_MEMORY;
1981 return open_socket_out(pss, *port, timeout, pfd);
1984 ev = event_context_init(talloc_tos());
1986 return NT_STATUS_NO_MEMORY;
1989 fd139 = talloc(ev, struct fd_struct);
1990 if (fd139 == NULL) {
1995 fd445 = talloc(ev, struct fd_struct);
1996 if (fd445 == NULL) {
2001 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2003 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2005 if ((r445 == NULL) || (r139 == NULL)) {
2008 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2009 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2011 while ((fd445->fd == -1) && (fd139->fd == -1)
2012 && (tevent_req_is_in_progress(r139)
2013 || tevent_req_is_in_progress(r445))) {
2014 event_loop_once(ev);
2017 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2022 if (fd445->fd != -1) {
2025 status = NT_STATUS_OK;
2028 if (fd139->fd != -1) {
2031 status = NT_STATUS_OK;
2035 status = open_socket_out_defer_recv(r445, &fd445->fd);
2041 /****************************************************************************
2042 Open the client sockets.
2043 ****************************************************************************/
2045 NTSTATUS cli_connect(struct cli_state *cli,
2047 struct sockaddr_storage *dest_ss)
2050 int name_type = 0x20;
2051 TALLOC_CTX *frame = talloc_stackframe();
2052 unsigned int num_addrs = 0;
2054 struct sockaddr_storage *ss_arr = NULL;
2057 /* reasonable default hostname */
2059 host = STAR_SMBSERVER;
2062 fstrcpy(cli->desthost, host);
2064 /* allow hostnames of the form NAME#xx and do a netbios lookup */
2065 if ((p = strchr(cli->desthost, '#'))) {
2066 name_type = strtol(p+1, NULL, 16);
2070 if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2071 NTSTATUS status =resolve_name_list(frame,
2076 if (!NT_STATUS_IS_OK(status)) {
2078 return NT_STATUS_BAD_NETWORK_NAME;
2082 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2085 return NT_STATUS_NO_MEMORY;
2090 for (i = 0; i < num_addrs; i++) {
2091 cli->dest_ss = ss_arr[i];
2092 if (getenv("LIBSMB_PROG")) {
2093 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2095 uint16_t port = cli->port;
2097 status = open_smb_socket(&cli->dest_ss, &port,
2098 cli->timeout, &cli->fd);
2099 if (NT_STATUS_IS_OK(status)) {
2103 if (cli->fd == -1) {
2104 char addr[INET6_ADDRSTRLEN];
2105 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2106 DEBUG(2,("Error connecting to %s (%s)\n",
2107 dest_ss?addr:host,strerror(errno)));
2109 /* Exit from loop on first connection. */
2114 if (cli->fd == -1) {
2116 return map_nt_error_from_unix(errno);
2120 *dest_ss = cli->dest_ss;
2123 set_socket_options(cli->fd, lp_socket_options());
2126 return NT_STATUS_OK;
2130 establishes a connection to after the negprot.
2131 @param output_cli A fully initialised cli structure, non-null only on success
2132 @param dest_host The netbios name of the remote host
2133 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2134 @param port (optional) The destination port (0 for default)
2135 @param retry bool. Did this connection fail with a retryable error ?
2138 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2139 const char *my_name,
2140 const char *dest_host,
2141 struct sockaddr_storage *dest_ss, int port,
2142 int signing_state, int flags,
2146 struct nmb_name calling;
2147 struct nmb_name called;
2148 struct cli_state *cli;
2149 struct sockaddr_storage ss;
2155 my_name = global_myname();
2157 if (!(cli = cli_initialise_ex(signing_state))) {
2158 return NT_STATUS_NO_MEMORY;
2161 make_nmb_name(&calling, my_name, 0x0);
2162 make_nmb_name(&called , dest_host, 0x20);
2164 cli_set_port(cli, port);
2165 cli_set_timeout(cli, 10000); /* 10 seconds. */
2175 DEBUG(3,("Connecting to host=%s\n", dest_host));
2177 nt_status = cli_connect(cli, dest_host, &ss);
2178 if (!NT_STATUS_IS_OK(nt_status)) {
2179 char addr[INET6_ADDRSTRLEN];
2180 print_sockaddr(addr, sizeof(addr), &ss);
2181 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2182 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2190 if (!cli_session_request(cli, &calling, &called)) {
2192 DEBUG(1,("session request to %s failed (%s)\n",
2193 called.name, cli_errstr(cli)));
2194 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2198 if (strcmp(called.name, STAR_SMBSERVER)) {
2199 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2202 return NT_STATUS_BAD_NETWORK_NAME;
2205 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2206 cli->use_spnego = False;
2207 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2208 cli->use_kerberos = True;
2210 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2211 cli->use_kerberos) {
2212 cli->fallback_after_kerberos = true;
2215 nt_status = cli_negprot(cli);
2216 if (!NT_STATUS_IS_OK(nt_status)) {
2217 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2223 return NT_STATUS_OK;
2228 establishes a connection right up to doing tconX, password specified.
2229 @param output_cli A fully initialised cli structure, non-null only on success
2230 @param dest_host The netbios name of the remote host
2231 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2232 @param port (optional) The destination port (0 for default)
2233 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2234 @param service_type The 'type' of serivice.
2235 @param user Username, unix string
2236 @param domain User's domain
2237 @param password User's password, unencrypted unix string.
2238 @param retry bool. Did this connection fail with a retryable error ?
2241 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2242 const char *my_name,
2243 const char *dest_host,
2244 struct sockaddr_storage *dest_ss, int port,
2245 const char *service, const char *service_type,
2246 const char *user, const char *domain,
2247 const char *password, int flags,
2252 struct cli_state *cli = NULL;
2253 int pw_len = password ? strlen(password)+1 : 0;
2257 if (password == NULL) {
2261 nt_status = cli_start_connection(&cli, my_name, dest_host,
2262 dest_ss, port, signing_state,
2265 if (!NT_STATUS_IS_OK(nt_status)) {
2269 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2270 cli->use_level_II_oplocks =
2271 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2273 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2275 if (!NT_STATUS_IS_OK(nt_status)) {
2277 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2278 DEBUG(1,("failed session setup with %s\n",
2279 nt_errstr(nt_status)));
2284 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2285 if (!NT_STATUS_IS_OK(nt_status)) {
2286 DEBUG(1,("anonymous failed session setup with %s\n",
2287 nt_errstr(nt_status)));
2294 nt_status = cli_tcon_andx(cli, service, service_type, password,
2296 if (!NT_STATUS_IS_OK(nt_status)) {
2297 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2299 if (NT_STATUS_IS_OK(nt_status)) {
2300 nt_status = NT_STATUS_UNSUCCESSFUL;
2306 nt_status = cli_init_creds(cli, user, domain, password);
2307 if (!NT_STATUS_IS_OK(nt_status)) {
2313 return NT_STATUS_OK;
2316 /****************************************************************************
2317 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2318 ****************************************************************************/
2320 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2321 struct sockaddr_storage *pdest_ss)
2323 struct nmb_name calling, called;
2325 make_nmb_name(&calling, srchost, 0x0);
2328 * If the called name is an IP address
2329 * then use *SMBSERVER immediately.
2332 if(is_ipaddress(desthost)) {
2333 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2335 make_nmb_name(&called, desthost, 0x20);
2338 if (!cli_session_request(*ppcli, &calling, &called)) {
2340 struct nmb_name smbservername;
2342 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2345 * If the name wasn't *SMBSERVER then
2346 * try with *SMBSERVER if the first name fails.
2349 if (nmb_name_equal(&called, &smbservername)) {
2352 * The name used was *SMBSERVER, don't bother with another name.
2355 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2356 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2361 cli_shutdown(*ppcli);
2363 *ppcli = cli_initialise();
2365 /* Out of memory... */
2369 status = cli_connect(*ppcli, desthost, pdest_ss);
2370 if (!NT_STATUS_IS_OK(status) ||
2371 !cli_session_request(*ppcli, &calling, &smbservername)) {
2372 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2373 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2381 /****************************************************************************
2382 Send an old style tcon.
2383 ****************************************************************************/
2384 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2385 const char *service, const char *pass, const char *dev,
2386 uint16 *max_xmit, uint16 *tid)
2390 if (!lp_client_plaintext_auth() && (*pass)) {
2391 DEBUG(1, ("Server requested plaintext password but 'client "
2392 "plaintext auth' is disabled\n"));
2393 return NT_STATUS_ACCESS_DENIED;
2396 memset(cli->outbuf,'\0',smb_size);
2397 memset(cli->inbuf,'\0',smb_size);
2399 cli_set_message(cli->outbuf, 0, 0, True);
2400 SCVAL(cli->outbuf,smb_com,SMBtcon);
2401 cli_setup_packet(cli);
2403 p = smb_buf(cli->outbuf);
2404 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2405 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2406 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2408 cli_setup_bcc(cli, p);
2411 if (!cli_receive_smb(cli)) {
2412 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2415 if (cli_is_error(cli)) {
2416 return cli_nt_error(cli);
2419 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2420 *tid = SVAL(cli->inbuf, smb_vwv1);
2422 return NT_STATUS_OK;
2425 /* Return a cli_state pointing at the IPC$ share for the given server */
2427 struct cli_state *get_ipc_connect(char *server,
2428 struct sockaddr_storage *server_ss,
2429 const struct user_auth_info *user_info)
2431 struct cli_state *cli;
2433 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2435 if (user_info->use_kerberos) {
2436 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2439 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2440 user_info->username ? user_info->username : "",
2442 user_info->password ? user_info->password : "",
2446 if (NT_STATUS_IS_OK(nt_status)) {
2448 } else if (is_ipaddress(server)) {
2449 /* windows 9* needs a correct NMB name for connections */
2450 fstring remote_name;
2452 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2453 cli = get_ipc_connect(remote_name, server_ss, user_info);
2462 * Given the IP address of a master browser on the network, return its
2463 * workgroup and connect to it.
2465 * This function is provided to allow additional processing beyond what
2466 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2467 * browsers and obtain each master browsers' list of domains (in case the
2468 * first master browser is recently on the network and has not yet
2469 * synchronized with other master browsers and therefore does not yet have the
2470 * entire network browse list)
2473 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2474 struct ip_service *mb_ip,
2475 const struct user_auth_info *user_info,
2476 char **pp_workgroup_out)
2478 char addr[INET6_ADDRSTRLEN];
2480 struct cli_state *cli;
2481 struct sockaddr_storage server_ss;
2483 *pp_workgroup_out = NULL;
2485 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2486 DEBUG(99, ("Looking up name of master browser %s\n",
2490 * Do a name status query to find out the name of the master browser.
2491 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2492 * master browser will not respond to a wildcard query (or, at least,
2493 * an NT4 server acting as the domain master browser will not).
2495 * We might be able to use ONLY the query on MSBROWSE, but that's not
2496 * yet been tested with all Windows versions, so until it is, leave
2497 * the original wildcard query as the first choice and fall back to
2498 * MSBROWSE if the wildcard query fails.
2500 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2501 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2503 DEBUG(99, ("Could not retrieve name status for %s\n",
2508 if (!find_master_ip(name, &server_ss)) {
2509 DEBUG(99, ("Could not find master ip for %s\n", name));
2513 *pp_workgroup_out = talloc_strdup(ctx, name);
2515 DEBUG(4, ("found master browser %s, %s\n", name, addr));
2517 print_sockaddr(addr, sizeof(addr), &server_ss);
2518 cli = get_ipc_connect(addr, &server_ss, user_info);
2524 * Return the IP address and workgroup of a master browser on the network, and
2528 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2529 const struct user_auth_info *user_info,
2530 char **pp_workgroup_out)
2532 struct ip_service *ip_list;
2533 struct cli_state *cli;
2536 *pp_workgroup_out = NULL;
2538 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2540 /* Go looking for workgroups by broadcasting on the local network */
2542 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2544 DEBUG(99, ("No master browsers responded\n"));
2548 for (i = 0; i < count; i++) {
2549 char addr[INET6_ADDRSTRLEN];
2550 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2551 DEBUG(99, ("Found master browser %s\n", addr));
2553 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2554 user_info, pp_workgroup_out);