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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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,"Samba"},
38 {PROTOCOL_NT1,"NT LANMAN 1.0"},
39 {PROTOCOL_NT1,"NT LM 0.12"},
44 * Set the user session key for a connection
45 * @param cli The cli structure to add it too
46 * @param session_key The session key used. (A copy of this is taken for the cli struct)
50 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
52 cli->user_session_key = data_blob(session_key.data, session_key.length);
55 /****************************************************************************
56 Do an old lanman2 style session setup.
57 ****************************************************************************/
59 static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
60 const char *pass, size_t passlen, const char *workgroup)
62 DATA_BLOB session_key = data_blob(NULL, 0);
63 DATA_BLOB lm_response = data_blob(NULL, 0);
67 if (passlen > sizeof(pword)-1)
70 /* LANMAN servers predate NT status codes and Unicode and ignore those
71 smb flags so we must disable the corresponding default capabilities
72 that would otherwise cause the Unicode and NT Status flags to be
73 set (and even returned by the server) */
75 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
77 /* if in share level security then don't send a password now */
78 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
81 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
82 /* Encrypted mode needed, and non encrypted password supplied. */
83 lm_response = data_blob(NULL, 24);
84 SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data);
85 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
86 /* Encrypted mode needed, and encrypted password supplied. */
87 lm_response = data_blob(pass, passlen);
88 } else if (passlen > 0) {
89 /* Plaintext mode needed, assume plaintext supplied. */
90 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
91 lm_response = data_blob(pass, passlen);
94 /* send a session setup command */
95 memset(cli->outbuf,'\0',smb_size);
96 set_message(cli->outbuf,10, 0, True);
97 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
98 cli_setup_packet(cli);
100 SCVAL(cli->outbuf,smb_vwv0,0xFF);
101 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
102 SSVAL(cli->outbuf,smb_vwv3,2);
103 SSVAL(cli->outbuf,smb_vwv4,1);
104 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
105 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
107 p = smb_buf(cli->outbuf);
108 memcpy(p,lm_response.data,lm_response.length);
110 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
111 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
112 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
113 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
114 cli_setup_bcc(cli, p);
117 if (!cli_receive_smb(cli))
120 show_msg(cli->inbuf);
122 if (cli_is_error(cli))
125 /* use the returned vuid from now on */
126 cli->vuid = SVAL(cli->inbuf,smb_uid);
127 fstrcpy(cli->user_name, user);
129 if (session_key.data) {
130 /* Have plaintext orginal */
131 cli_set_session_key(cli, session_key);
137 /****************************************************************************
138 Work out suitable capabilities to offer the server.
139 ****************************************************************************/
141 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
143 uint32 capabilities = CAP_NT_SMBS;
145 if (!cli->force_dos_errors)
146 capabilities |= CAP_STATUS32;
148 if (cli->use_level_II_oplocks)
149 capabilities |= CAP_LEVEL_II_OPLOCKS;
151 if (cli->capabilities & CAP_UNICODE)
152 capabilities |= CAP_UNICODE;
154 if (cli->capabilities & CAP_LARGE_FILES)
155 capabilities |= CAP_LARGE_FILES;
160 /****************************************************************************
161 Do a NT1 guest session setup.
162 ****************************************************************************/
164 static BOOL cli_session_setup_guest(struct cli_state *cli)
167 uint32 capabilities = cli_session_setup_capabilities(cli);
169 set_message(cli->outbuf,13,0,True);
170 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
171 cli_setup_packet(cli);
173 SCVAL(cli->outbuf,smb_vwv0,0xFF);
174 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
175 SSVAL(cli->outbuf,smb_vwv3,2);
176 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
177 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
178 SSVAL(cli->outbuf,smb_vwv7,0);
179 SSVAL(cli->outbuf,smb_vwv8,0);
180 SIVAL(cli->outbuf,smb_vwv11,capabilities);
181 p = smb_buf(cli->outbuf);
182 p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */
183 p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */
184 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
185 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
186 cli_setup_bcc(cli, p);
189 if (!cli_receive_smb(cli))
192 show_msg(cli->inbuf);
194 if (cli_is_error(cli))
197 cli->vuid = SVAL(cli->inbuf,smb_uid);
199 p = smb_buf(cli->inbuf);
200 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
201 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
202 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
204 fstrcpy(cli->user_name, "");
209 /****************************************************************************
210 Do a NT1 plaintext session setup.
211 ****************************************************************************/
213 static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
214 const char *pass, const char *workgroup)
216 uint32 capabilities = cli_session_setup_capabilities(cli);
220 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
222 set_message(cli->outbuf,13,0,True);
223 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
224 cli_setup_packet(cli);
226 SCVAL(cli->outbuf,smb_vwv0,0xFF);
227 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
228 SSVAL(cli->outbuf,smb_vwv3,2);
229 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
230 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
231 SSVAL(cli->outbuf,smb_vwv8,0);
232 SIVAL(cli->outbuf,smb_vwv11,capabilities);
233 p = smb_buf(cli->outbuf);
235 /* check wether to send the ASCII or UNICODE version of the password */
237 if ( (capabilities & CAP_UNICODE) == 0 ) {
238 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
239 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
242 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
243 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf)));
246 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
247 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
248 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
249 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
250 cli_setup_bcc(cli, p);
253 if (!cli_receive_smb(cli))
256 show_msg(cli->inbuf);
258 if (cli_is_error(cli))
261 cli->vuid = SVAL(cli->inbuf,smb_uid);
262 p = smb_buf(cli->inbuf);
263 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
264 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
265 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
266 fstrcpy(cli->user_name, user);
271 /****************************************************************************
272 do a NT1 NTLM/LM encrypted session setup - for when extended security
274 @param cli client state to create do session setup on
276 @param pass *either* cleartext password (passlen !=24) or LM response.
277 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
278 @param workgroup The user's domain.
279 ****************************************************************************/
281 static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
282 const char *pass, size_t passlen,
283 const char *ntpass, size_t ntpasslen,
284 const char *workgroup)
286 uint32 capabilities = cli_session_setup_capabilities(cli);
287 DATA_BLOB lm_response = data_blob(NULL, 0);
288 DATA_BLOB nt_response = data_blob(NULL, 0);
289 DATA_BLOB session_key = data_blob(NULL, 0);
294 /* do nothing - guest login */
295 } else if (passlen != 24) {
296 if (lp_client_ntlmv2_auth()) {
297 DATA_BLOB server_chal;
298 DATA_BLOB names_blob;
299 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
301 /* note that the 'workgroup' here is a best guess - we don't know
302 the server's domain at this point. The 'server name' is also
305 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
307 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
309 &lm_response, &nt_response, &session_key)) {
310 data_blob_free(&names_blob);
311 data_blob_free(&server_chal);
314 data_blob_free(&names_blob);
315 data_blob_free(&server_chal);
319 E_md4hash(pass, nt_hash);
322 nt_response = data_blob(NULL, 0);
324 nt_response = data_blob(NULL, 24);
325 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
327 /* non encrypted password supplied. Ignore ntpass. */
328 if (lp_client_lanman_auth()) {
329 lm_response = data_blob(NULL, 24);
330 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
331 /* Oops, the LM response is invalid, just put
332 the NT response there instead */
333 data_blob_free(&lm_response);
334 lm_response = data_blob(nt_response.data, nt_response.length);
337 /* LM disabled, place NT# in LM field instead */
338 lm_response = data_blob(nt_response.data, nt_response.length);
341 session_key = data_blob(NULL, 16);
343 E_deshash(pass, session_key.data);
344 memset(&session_key.data[8], '\0', 8);
346 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
350 cli_simple_set_signing(cli, session_key, lm_response);
352 cli_simple_set_signing(cli, session_key, nt_response);
355 /* pre-encrypted password supplied. Only used for
356 security=server, can't do
357 signing because we don't have original key */
359 lm_response = data_blob(pass, passlen);
360 nt_response = data_blob(ntpass, ntpasslen);
363 /* send a session setup command */
364 memset(cli->outbuf,'\0',smb_size);
366 set_message(cli->outbuf,13,0,True);
367 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
368 cli_setup_packet(cli);
370 SCVAL(cli->outbuf,smb_vwv0,0xFF);
371 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
372 SSVAL(cli->outbuf,smb_vwv3,2);
373 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
374 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
375 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
376 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
377 SIVAL(cli->outbuf,smb_vwv11,capabilities);
378 p = smb_buf(cli->outbuf);
379 if (lm_response.length) {
380 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
382 if (nt_response.length) {
383 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
385 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
387 /* Upper case here might help some NTLMv2 implementations */
388 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
389 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
390 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
391 cli_setup_bcc(cli, p);
393 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
398 /* show_msg(cli->inbuf); */
400 if (cli_is_error(cli)) {
405 /* use the returned vuid from now on */
406 cli->vuid = SVAL(cli->inbuf,smb_uid);
408 p = smb_buf(cli->inbuf);
409 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
410 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
411 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
413 fstrcpy(cli->user_name, user);
415 if (session_key.data) {
416 /* Have plaintext orginal */
417 cli_set_session_key(cli, session_key);
422 data_blob_free(&lm_response);
423 data_blob_free(&nt_response);
426 data_blob_free(&session_key);
430 /****************************************************************************
431 Send a extended security session setup blob
432 ****************************************************************************/
434 static BOOL cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
436 uint32 capabilities = cli_session_setup_capabilities(cli);
439 capabilities |= CAP_EXTENDED_SECURITY;
441 /* send a session setup command */
442 memset(cli->outbuf,'\0',smb_size);
444 set_message(cli->outbuf,12,0,True);
445 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
447 cli_setup_packet(cli);
449 SCVAL(cli->outbuf,smb_vwv0,0xFF);
450 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
451 SSVAL(cli->outbuf,smb_vwv3,2);
452 SSVAL(cli->outbuf,smb_vwv4,1);
453 SIVAL(cli->outbuf,smb_vwv5,0);
454 SSVAL(cli->outbuf,smb_vwv7,blob.length);
455 SIVAL(cli->outbuf,smb_vwv10,capabilities);
456 p = smb_buf(cli->outbuf);
457 memcpy(p, blob.data, blob.length);
459 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
460 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
461 cli_setup_bcc(cli, p);
462 return cli_send_smb(cli);
465 /****************************************************************************
466 Send a extended security session setup blob, returning a reply blob.
467 ****************************************************************************/
469 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
471 DATA_BLOB blob2 = data_blob(NULL, 0);
475 if (!cli_receive_smb(cli))
478 show_msg(cli->inbuf);
480 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
481 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
485 /* use the returned vuid from now on */
486 cli->vuid = SVAL(cli->inbuf,smb_uid);
488 p = smb_buf(cli->inbuf);
490 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
493 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
495 /* w2k with kerberos doesn't properly null terminate this field */
496 len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf));
497 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
504 /****************************************************************************
505 Send a extended security session setup blob, returning a reply blob.
506 ****************************************************************************/
508 static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
510 DATA_BLOB blob2 = data_blob(NULL, 0);
511 if (!cli_session_setup_blob_send(cli, blob)) {
515 return cli_session_setup_blob_receive(cli);
518 /****************************************************************************
519 Use in-memory credentials cache
520 ****************************************************************************/
522 static void use_in_memory_ccache(void) {
523 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
526 /****************************************************************************
527 Do a spnego/kerberos encrypted session setup.
528 ****************************************************************************/
530 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
532 DATA_BLOB blob2, negTokenTarg;
533 DATA_BLOB session_key_krb5;
534 DATA_BLOB null_blob = data_blob(NULL, 0);
537 DEBUG(2,("Doing kerberos session setup\n"));
539 /* generate the encapsulated kerberos5 ticket */
540 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5);
543 DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc)));
544 return ADS_ERROR_KRB5(rc);
548 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
551 cli_simple_set_signing(cli, session_key_krb5, null_blob);
553 blob2 = cli_session_setup_blob(cli, negTokenTarg);
555 /* we don't need this blob for kerberos */
556 data_blob_free(&blob2);
558 cli_set_session_key(cli, session_key_krb5);
560 data_blob_free(&negTokenTarg);
562 if (cli_is_error(cli)) {
563 if (NT_STATUS_IS_OK(cli_nt_error(cli))) {
564 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
567 return ADS_ERROR_NT(cli_nt_error(cli));
569 #endif /* HAVE_KRB5 */
572 /****************************************************************************
573 Do a spnego/NTLMSSP encrypted session setup.
574 ****************************************************************************/
576 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
577 const char *pass, const char *domain)
579 struct ntlmssp_state *ntlmssp_state;
583 DATA_BLOB blob = data_blob(NULL, 0);
584 DATA_BLOB blob_in = data_blob(NULL, 0);
585 DATA_BLOB blob_out = data_blob(NULL, 0);
587 cli_temp_set_signing(cli);
589 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
593 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
596 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
599 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
604 nt_status = ntlmssp_update(ntlmssp_state,
606 data_blob_free(&blob_in);
607 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
609 /* and wrap it in a SPNEGO wrapper */
610 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
612 /* wrap it in SPNEGO */
613 msg1 = spnego_gen_auth(blob_out);
616 /* now send that blob on its way */
617 if (!cli_session_setup_blob_send(cli, msg1)) {
618 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
619 nt_status = NT_STATUS_UNSUCCESSFUL;
621 data_blob_free(&msg1);
623 blob = cli_session_setup_blob_receive(cli);
625 nt_status = cli_nt_error(cli);
626 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
627 if (cli->smb_rw_error == READ_BAD_SIG) {
628 nt_status = NT_STATUS_ACCESS_DENIED;
630 nt_status = NT_STATUS_UNSUCCESSFUL;
637 if (NT_STATUS_IS_OK(nt_status)) {
638 nt_status = NT_STATUS_UNSUCCESSFUL;
640 } else if ((turn == 1) &&
641 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
642 DATA_BLOB tmp_blob = data_blob(NULL, 0);
643 /* the server might give us back two challenges */
644 if (!spnego_parse_challenge(blob, &blob_in,
646 DEBUG(3,("Failed to parse challenges\n"));
647 nt_status = NT_STATUS_INVALID_PARAMETER;
649 data_blob_free(&tmp_blob);
651 if (!spnego_parse_auth_response(blob, nt_status,
653 DEBUG(3,("Failed to parse auth response\n"));
654 if (NT_STATUS_IS_OK(nt_status)
655 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
656 nt_status = NT_STATUS_INVALID_PARAMETER;
659 data_blob_free(&blob);
660 data_blob_free(&blob_out);
662 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
664 if (NT_STATUS_IS_OK(nt_status)) {
666 DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
667 ntlmssp_state->session_key.length);
668 DATA_BLOB null_blob = data_blob(NULL, 0);
670 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
671 cli_set_session_key(cli, ntlmssp_state->session_key);
673 if (cli_simple_set_signing(cli, key, null_blob)) {
675 /* 'resign' the last message, so we get the right sequence numbers
676 for checking the first reply from the server */
677 cli_calculate_sign_mac(cli);
679 if (!cli_check_sign_mac(cli, True)) {
680 nt_status = NT_STATUS_ACCESS_DENIED;
685 /* we have a reference conter on ntlmssp_state, if we are signing
686 then the state will be kept by the signing engine */
688 ntlmssp_end(&ntlmssp_state);
693 /****************************************************************************
694 Do a spnego encrypted session setup.
695 ****************************************************************************/
697 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
698 const char *pass, const char *domain)
701 char *OIDs[ASN1_MAX_OIDS];
703 BOOL got_kerberos_mechanism = False;
706 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
708 /* the server might not even do spnego */
709 if (cli->secblob.length <= 16) {
710 DEBUG(3,("server didn't supply a full spnego negprot\n"));
715 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
718 /* there is 16 bytes of GUID before the real spnego packet starts */
719 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
721 /* the server sent us the first part of the SPNEGO exchange in the negprot
723 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
724 data_blob_free(&blob);
725 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
727 data_blob_free(&blob);
729 /* make sure the server understands kerberos */
730 for (i=0;OIDs[i];i++) {
731 DEBUG(3,("got OID=%s\n", OIDs[i]));
732 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
733 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
734 got_kerberos_mechanism = True;
738 DEBUG(3,("got principal=%s\n", principal));
740 fstrcpy(cli->user_name, user);
743 /* If password is set we reauthenticate to kerberos server
744 * and do not store results */
746 if (got_kerberos_mechanism && cli->use_kerberos) {
750 use_in_memory_ccache();
751 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
754 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
755 return ADS_ERROR_KRB5(ret);
759 return cli_session_setup_kerberos(cli, principal, domain);
767 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass, domain));
770 /****************************************************************************
771 Send a session setup. The username and workgroup is in UNIX character
772 format and must be converted to DOS codepage format before sending. If the
773 password is in plaintext, the same should be done.
774 ****************************************************************************/
776 BOOL cli_session_setup(struct cli_state *cli,
778 const char *pass, int passlen,
779 const char *ntpass, int ntpasslen,
780 const char *workgroup)
785 /* allow for workgroups as part of the username */
786 fstrcpy(user2, user);
787 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
788 (p=strchr_m(user2,*lp_winbind_separator()))) {
794 if (cli->protocol < PROTOCOL_LANMAN1)
797 /* now work out what sort of session setup we are going to
798 do. I have split this into separate functions to make the
799 flow a bit easier to understand (tridge) */
801 /* if its an older server then we have to use the older request format */
803 if (cli->protocol < PROTOCOL_NT1) {
804 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
805 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
810 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
811 !lp_client_plaintext_auth() && (*pass)) {
812 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
817 return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
820 /* if no user is supplied then we have to do an anonymous connection.
821 passwords are ignored */
824 return cli_session_setup_guest(cli);
826 /* if the server is share level then send a plaintext null
827 password at this point. The password is sent in the tree
830 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
831 return cli_session_setup_plaintext(cli, user, "", workgroup);
833 /* if the server doesn't support encryption then we have to use
834 plaintext. The second password is ignored */
836 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
837 if (!lp_client_plaintext_auth() && (*pass)) {
838 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
842 return cli_session_setup_plaintext(cli, user, pass, workgroup);
845 /* if the server supports extended security then use SPNEGO */
847 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
848 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
849 if (!ADS_ERR_OK(status)) {
850 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
856 /* otherwise do a NT1 style session setup */
858 return cli_session_setup_nt1(cli, user,
859 pass, passlen, ntpass, ntpasslen,
863 /****************************************************************************
865 *****************************************************************************/
867 BOOL cli_ulogoff(struct cli_state *cli)
869 memset(cli->outbuf,'\0',smb_size);
870 set_message(cli->outbuf,2,0,True);
871 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
872 cli_setup_packet(cli);
873 SSVAL(cli->outbuf,smb_vwv0,0xFF);
874 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
877 if (!cli_receive_smb(cli))
880 return !cli_is_error(cli);
883 /****************************************************************************
885 ****************************************************************************/
886 BOOL cli_send_tconX(struct cli_state *cli,
887 const char *share, const char *dev, const char *pass, int passlen)
889 fstring fullshare, pword;
891 memset(cli->outbuf,'\0',smb_size);
892 memset(cli->inbuf,'\0',smb_size);
894 fstrcpy(cli->share, share);
896 /* in user level security don't send a password now */
897 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
902 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
903 if (!lp_client_lanman_auth()) {
904 DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
910 * Non-encrypted passwords - convert to DOS codepage before encryption.
913 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
915 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
916 if (!lp_client_plaintext_auth() && (*pass)) {
917 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
923 * Non-encrypted passwords - convert to DOS codepage before using.
925 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
928 memcpy(pword, pass, passlen);
932 slprintf(fullshare, sizeof(fullshare)-1,
933 "\\\\%s\\%s", cli->desthost, share);
935 set_message(cli->outbuf,4, 0, True);
936 SCVAL(cli->outbuf,smb_com,SMBtconX);
937 cli_setup_packet(cli);
939 SSVAL(cli->outbuf,smb_vwv0,0xFF);
940 SSVAL(cli->outbuf,smb_vwv3,passlen);
942 p = smb_buf(cli->outbuf);
943 memcpy(p,pword,passlen);
945 p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
946 p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
948 cli_setup_bcc(cli, p);
951 if (!cli_receive_smb(cli))
954 if (cli_is_error(cli))
957 clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
959 if (cli->protocol >= PROTOCOL_NT1 &&
960 smb_buflen(cli->inbuf) == 3) {
961 /* almost certainly win95 - enable bug fixes */
965 cli->cnum = SVAL(cli->inbuf,smb_tid);
969 /****************************************************************************
970 Send a tree disconnect.
971 ****************************************************************************/
973 BOOL cli_tdis(struct cli_state *cli)
975 memset(cli->outbuf,'\0',smb_size);
976 set_message(cli->outbuf,0,0,True);
977 SCVAL(cli->outbuf,smb_com,SMBtdis);
978 SSVAL(cli->outbuf,smb_tid,cli->cnum);
979 cli_setup_packet(cli);
982 if (!cli_receive_smb(cli))
985 return !cli_is_error(cli);
988 /****************************************************************************
989 Send a negprot command.
990 ****************************************************************************/
992 void cli_negprot_send(struct cli_state *cli)
997 if (cli->protocol < PROTOCOL_NT1)
998 cli->use_spnego = False;
1000 memset(cli->outbuf,'\0',smb_size);
1002 /* setup the protocol strings */
1003 set_message(cli->outbuf,0,0,True);
1005 p = smb_buf(cli->outbuf);
1007 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1010 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1013 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1014 cli_setup_bcc(cli, p);
1015 cli_setup_packet(cli);
1017 SCVAL(smb_buf(cli->outbuf),0,2);
1022 /****************************************************************************
1023 Send a negprot command.
1024 ****************************************************************************/
1026 BOOL cli_negprot(struct cli_state *cli)
1032 if (cli->protocol < PROTOCOL_NT1)
1033 cli->use_spnego = False;
1035 memset(cli->outbuf,'\0',smb_size);
1037 /* setup the protocol strings */
1038 for (plength=0,numprots=0;
1039 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1041 plength += strlen(prots[numprots].name)+2;
1043 set_message(cli->outbuf,0,plength,True);
1045 p = smb_buf(cli->outbuf);
1047 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1050 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1053 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1054 cli_setup_packet(cli);
1056 SCVAL(smb_buf(cli->outbuf),0,2);
1059 if (!cli_receive_smb(cli))
1062 show_msg(cli->inbuf);
1064 if (cli_is_error(cli) ||
1065 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1069 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
1071 if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1072 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1076 if (cli->protocol >= PROTOCOL_NT1) {
1078 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1079 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
1080 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1081 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1082 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
1083 cli->serverzone *= 60;
1084 /* this time arrives in real GMT */
1085 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
1086 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1087 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1088 if (cli->capabilities & CAP_RAW_MODE) {
1089 cli->readbraw_supported = True;
1090 cli->writebraw_supported = True;
1092 /* work out if they sent us a workgroup */
1093 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1094 smb_buflen(cli->inbuf) > 8) {
1095 clistr_pull(cli, cli->server_domain,
1096 smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1097 smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1101 * As signing is slow we only turn it on if either the client or
1102 * the server require it. JRA.
1105 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1106 /* Fail if server says signing is mandatory and we don't want to support it. */
1107 if (!cli->sign_info.allow_smb_signing) {
1108 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1111 cli->sign_info.negotiated_smb_signing = True;
1112 cli->sign_info.mandatory_signing = True;
1113 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1114 /* Fail if client says signing is mandatory and the server doesn't support it. */
1115 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1116 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1119 cli->sign_info.negotiated_smb_signing = True;
1120 cli->sign_info.mandatory_signing = True;
1121 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1122 cli->sign_info.negotiated_smb_signing = True;
1125 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1126 cli->use_spnego = False;
1127 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1128 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1129 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1130 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1131 cli->serverzone *= 60;
1132 /* this time is converted to GMT by make_unix_date */
1133 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
1134 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1135 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1136 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1138 /* the old core protocol */
1139 cli->use_spnego = False;
1141 cli->serverzone = TimeDiff(time(NULL));
1144 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1146 /* a way to force ascii SMB */
1147 if (getenv("CLI_FORCE_ASCII"))
1148 cli->capabilities &= ~CAP_UNICODE;
1153 /****************************************************************************
1154 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1155 ****************************************************************************/
1157 BOOL cli_session_request(struct cli_state *cli,
1158 struct nmb_name *calling, struct nmb_name *called)
1162 extern pstring user_socket_options;
1164 memcpy(&(cli->calling), calling, sizeof(*calling));
1165 memcpy(&(cli->called ), called , sizeof(*called ));
1167 /* put in the destination name */
1168 p = cli->outbuf+len;
1169 name_mangle(cli->called .name, p, cli->called .name_type);
1173 p = cli->outbuf+len;
1174 name_mangle(cli->calling.name, p, cli->calling.name_type);
1177 /* 445 doesn't have session request */
1178 if (cli->port == 445)
1181 /* send a session request (RFC 1002) */
1182 /* setup the packet length
1183 * Remove four bytes from the length count, since the length
1184 * field in the NBT Session Service header counts the number
1185 * of bytes which follow. The cli_send_smb() function knows
1186 * about this and accounts for those four bytes.
1190 _smb_setlen(cli->outbuf,len);
1191 SCVAL(cli->outbuf,0,0x81);
1194 DEBUG(5,("Sent session request\n"));
1196 if (!cli_receive_smb(cli))
1199 if (CVAL(cli->inbuf,0) == 0x84) {
1200 /* C. Hoch 9/14/95 Start */
1201 /* For information, here is the response structure.
1202 * We do the byte-twiddling to for portability.
1203 struct RetargetResponse{
1205 unsigned char flags;
1211 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1212 /* SESSION RETARGET */
1213 putip((char *)&cli->dest_ip,cli->inbuf+4);
1215 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
1219 DEBUG(3,("Retargeted\n"));
1221 set_socket_options(cli->fd,user_socket_options);
1228 DEBUG(0,("Retarget recursion - failing\n"));
1232 ret = cli_session_request(cli, calling, called);
1236 } /* C. Hoch 9/14/95 End */
1238 if (CVAL(cli->inbuf,0) != 0x82) {
1239 /* This is the wrong place to put the error... JRA. */
1240 cli->rap_error = CVAL(cli->inbuf,4);
1246 /****************************************************************************
1247 Open the client sockets.
1248 ****************************************************************************/
1250 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
1252 extern pstring user_socket_options;
1253 int name_type = 0x20;
1256 /* reasonable default hostname */
1257 if (!host) host = "*SMBSERVER";
1259 fstrcpy(cli->desthost, host);
1261 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1262 if ((p = strchr(cli->desthost, '#'))) {
1263 name_type = strtol(p+1, NULL, 16);
1267 if (!ip || is_zero_ip(*ip)) {
1268 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
1271 if (ip) *ip = cli->dest_ip;
1276 if (getenv("LIBSMB_PROG")) {
1277 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1279 /* try 445 first, then 139 */
1280 int port = cli->port?cli->port:445;
1281 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1282 port, cli->timeout);
1283 if (cli->fd == -1 && cli->port == 0) {
1285 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1286 port, cli->timeout);
1291 if (cli->fd == -1) {
1292 DEBUG(1,("Error connecting to %s (%s)\n",
1293 ip?inet_ntoa(*ip):host,strerror(errno)));
1297 set_socket_options(cli->fd,user_socket_options);
1302 /****************************************************************************
1303 Initialise client credentials for authenticated pipe access.
1304 ****************************************************************************/
1306 void init_creds(struct ntuser_creds *creds, const char* username,
1307 const char* domain, const char* password)
1309 ZERO_STRUCTP(creds);
1311 pwd_set_cleartext(&creds->pwd, password);
1313 fstrcpy(creds->user_name, username);
1314 fstrcpy(creds->domain, domain);
1317 creds->pwd.null_pwd = True;
1322 establishes a connection to after the negprot.
1323 @param output_cli A fully initialised cli structure, non-null only on success
1324 @param dest_host The netbios name of the remote host
1325 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1326 @param port (optional) The destination port (0 for default)
1327 @param retry BOOL. Did this connection fail with a retryable error ?
1330 NTSTATUS cli_start_connection(struct cli_state **output_cli,
1331 const char *my_name,
1332 const char *dest_host,
1333 struct in_addr *dest_ip, int port,
1334 int signing_state, int flags,
1338 struct nmb_name calling;
1339 struct nmb_name called;
1340 struct cli_state *cli;
1347 my_name = global_myname();
1349 if (!(cli = cli_initialise(NULL)))
1350 return NT_STATUS_NO_MEMORY;
1352 make_nmb_name(&calling, my_name, 0x0);
1353 make_nmb_name(&called , dest_host, 0x20);
1355 if (cli_set_port(cli, port) != port) {
1357 return NT_STATUS_UNSUCCESSFUL;
1360 cli_set_timeout(cli, 10000); /* 10 seconds. */
1369 DEBUG(3,("Connecting to host=%s\n", dest_host));
1371 if (!cli_connect(cli, dest_host, &ip)) {
1372 DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
1373 nmb_namestr(&called), inet_ntoa(ip)));
1375 return NT_STATUS_UNSUCCESSFUL;
1381 if (!cli_session_request(cli, &calling, &called)) {
1383 DEBUG(1,("session request to %s failed (%s)\n",
1384 called.name, cli_errstr(cli)));
1385 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1389 if (strcmp(called.name, "*SMBSERVER")) {
1390 make_nmb_name(&called , "*SMBSERVER", 0x20);
1393 return NT_STATUS_UNSUCCESSFUL;
1396 cli_setup_signing_state(cli, signing_state);
1398 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1399 cli->use_spnego = False;
1400 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1401 cli->use_kerberos = True;
1403 if (!cli_negprot(cli)) {
1404 DEBUG(1,("failed negprot\n"));
1405 nt_status = NT_STATUS_UNSUCCESSFUL;
1411 return NT_STATUS_OK;
1416 establishes a connection right up to doing tconX, password specified.
1417 @param output_cli A fully initialised cli structure, non-null only on success
1418 @param dest_host The netbios name of the remote host
1419 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1420 @param port (optional) The destination port (0 for default)
1421 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
1422 @param service_type The 'type' of serivice.
1423 @param user Username, unix string
1424 @param domain User's domain
1425 @param password User's password, unencrypted unix string.
1426 @param retry BOOL. Did this connection fail with a retryable error ?
1429 NTSTATUS cli_full_connection(struct cli_state **output_cli,
1430 const char *my_name,
1431 const char *dest_host,
1432 struct in_addr *dest_ip, int port,
1433 const char *service, const char *service_type,
1434 const char *user, const char *domain,
1435 const char *password, int flags,
1439 struct ntuser_creds creds;
1441 struct cli_state *cli = NULL;
1443 nt_status = cli_start_connection(&cli, my_name, dest_host,
1444 dest_ip, port, signing_state, flags, retry);
1446 if (!NT_STATUS_IS_OK(nt_status)) {
1450 if (!cli_session_setup(cli, user, password, strlen(password)+1,
1451 password, strlen(password)+1,
1453 if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
1454 && cli_session_setup(cli, "", "", 0, "", 0, domain)) {
1456 nt_status = cli_nt_error(cli);
1457 DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
1459 if (NT_STATUS_IS_OK(nt_status))
1460 nt_status = NT_STATUS_UNSUCCESSFUL;
1466 if (!cli_send_tconX(cli, service, service_type,
1467 password, strlen(password)+1)) {
1468 nt_status = cli_nt_error(cli);
1469 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1471 if (NT_STATUS_IS_OK(nt_status)) {
1472 nt_status = NT_STATUS_UNSUCCESSFUL;
1478 init_creds(&creds, user, domain, password);
1479 cli_init_creds(cli, &creds);
1482 return NT_STATUS_OK;
1485 /****************************************************************************
1486 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1487 ****************************************************************************/
1489 BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
1490 struct in_addr *pdest_ip)
1492 struct nmb_name calling, called;
1494 make_nmb_name(&calling, srchost, 0x0);
1497 * If the called name is an IP address
1498 * then use *SMBSERVER immediately.
1501 if(is_ipaddress(desthost))
1502 make_nmb_name(&called, "*SMBSERVER", 0x20);
1504 make_nmb_name(&called, desthost, 0x20);
1506 if (!cli_session_request(cli, &calling, &called)) {
1507 struct nmb_name smbservername;
1509 make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
1512 * If the name wasn't *SMBSERVER then
1513 * try with *SMBSERVER if the first name fails.
1516 if (nmb_name_equal(&called, &smbservername)) {
1519 * The name used was *SMBSERVER, don't bother with another name.
1522 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1523 with error %s.\n", desthost, cli_errstr(cli) ));
1528 * We need to close the connection here but can't call cli_shutdown as
1529 * will free an allocated cli struct. cli_close_connection was invented
1530 * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
1533 cli_close_connection(cli);
1535 if (!cli_initialise(cli) ||
1536 !cli_connect(cli, desthost, pdest_ip) ||
1537 !cli_session_request(cli, &calling, &smbservername)) {
1538 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1539 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
1551 /****************************************************************************
1552 Send an old style tcon.
1553 ****************************************************************************/
1554 NTSTATUS cli_raw_tcon(struct cli_state *cli,
1555 const char *service, const char *pass, const char *dev,
1556 uint16 *max_xmit, uint16 *tid)
1560 if (!lp_client_plaintext_auth() && (*pass)) {
1561 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1563 return NT_STATUS_ACCESS_DENIED;
1566 memset(cli->outbuf,'\0',smb_size);
1567 memset(cli->inbuf,'\0',smb_size);
1569 set_message(cli->outbuf, 0, 0, True);
1570 SCVAL(cli->outbuf,smb_com,SMBtcon);
1571 cli_setup_packet(cli);
1573 p = smb_buf(cli->outbuf);
1574 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1575 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1576 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1578 cli_setup_bcc(cli, p);
1581 if (!cli_receive_smb(cli)) {
1582 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1585 if (cli_is_error(cli)) {
1586 return cli_nt_error(cli);
1589 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
1590 *tid = SVAL(cli->inbuf, smb_vwv1);
1592 return NT_STATUS_OK;
1595 /* Return a cli_state pointing at the IPC$ share for the given server */
1597 struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
1598 struct user_auth_info *user_info)
1600 struct cli_state *cli;
1606 nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC",
1607 user_info->username, lp_workgroup(), user_info->password,
1608 CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, NULL);
1610 if (NT_STATUS_IS_OK(nt_status)) {
1612 } else if (is_ipaddress(server)) {
1613 /* windows 9* needs a correct NMB name for connections */
1614 fstring remote_name;
1616 if (name_status_find("*", 0, 0, *server_ip, remote_name)) {
1617 cli = get_ipc_connect(remote_name, server_ip, user_info);
1626 * Given the IP address of a master browser on the network, return its
1627 * workgroup and connect to it.
1629 * This function is provided to allow additional processing beyond what
1630 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
1631 * browsers and obtain each master browsers' list of domains (in case the
1632 * first master browser is recently on the network and has not yet
1633 * synchronized with other master browsers and therefore does not yet have the
1634 * entire network browse list)
1637 struct cli_state *get_ipc_connect_master_ip(struct ip_service * mb_ip, pstring workgroup, struct user_auth_info *user_info)
1639 static fstring name;
1640 struct cli_state *cli;
1641 struct in_addr server_ip;
1643 DEBUG(99, ("Looking up name of master browser %s\n",
1644 inet_ntoa(mb_ip->ip)));
1647 * Do a name status query to find out the name of the master browser.
1648 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
1649 * master browser will not respond to a wildcard query (or, at least,
1650 * an NT4 server acting as the domain master browser will not).
1652 * We might be able to use ONLY the query on MSBROWSE, but that's not
1653 * yet been tested with all Windows versions, so until it is, leave
1654 * the original wildcard query as the first choice and fall back to
1655 * MSBROWSE if the wildcard query fails.
1657 if (!name_status_find("*", 0, 0x1d, mb_ip->ip, name) &&
1658 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip->ip, name)) {
1660 DEBUG(99, ("Could not retrieve name status for %s\n",
1661 inet_ntoa(mb_ip->ip)));
1665 if (!find_master_ip(name, &server_ip)) {
1666 DEBUG(99, ("Could not find master ip for %s\n", name));
1670 pstrcpy(workgroup, name);
1672 DEBUG(4, ("found master browser %s, %s\n",
1673 name, inet_ntoa(mb_ip->ip)));
1675 cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);
1682 * Return the IP address and workgroup of a master browser on the network, and
1686 struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
1688 struct ip_service *ip_list;
1689 struct cli_state *cli;
1692 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
1694 /* Go looking for workgroups by broadcasting on the local network */
1696 if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
1697 DEBUG(99, ("No master browsers responded\n"));
1701 for (i = 0; i < count; i++) {
1702 DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip)));
1704 cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, user_info);