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"},
43 /****************************************************************************
44 Do an old lanman2 style session setup.
45 ****************************************************************************/
47 static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
48 const char *pass, size_t passlen, const char *workgroup)
53 if (passlen > sizeof(pword)-1)
56 /* if in share level security then don't send a password now */
57 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
60 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
61 /* Encrypted mode needed, and non encrypted password supplied. */
63 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
64 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
65 /* Encrypted mode needed, and encrypted password supplied. */
66 memcpy(pword, pass, passlen);
67 } else if (passlen > 0) {
68 /* Plaintext mode needed, assume plaintext supplied. */
69 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
72 /* send a session setup command */
73 memset(cli->outbuf,'\0',smb_size);
74 set_message(cli->outbuf,10, 0, True);
75 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
76 cli_setup_packet(cli);
78 SCVAL(cli->outbuf,smb_vwv0,0xFF);
79 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
80 SSVAL(cli->outbuf,smb_vwv3,2);
81 SSVAL(cli->outbuf,smb_vwv4,1);
82 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
83 SSVAL(cli->outbuf,smb_vwv7,passlen);
85 p = smb_buf(cli->outbuf);
86 memcpy(p,pword,passlen);
88 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
89 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
90 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
91 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
92 cli_setup_bcc(cli, p);
95 if (!cli_receive_smb(cli))
100 if (cli_is_error(cli))
103 /* use the returned vuid from now on */
104 cli->vuid = SVAL(cli->inbuf,smb_uid);
105 fstrcpy(cli->user_name, user);
110 /****************************************************************************
111 Work out suitable capabilities to offer the server.
112 ****************************************************************************/
114 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
116 uint32 capabilities = CAP_NT_SMBS;
118 if (!cli->force_dos_errors)
119 capabilities |= CAP_STATUS32;
121 if (cli->use_level_II_oplocks)
122 capabilities |= CAP_LEVEL_II_OPLOCKS;
124 if (cli->capabilities & CAP_UNICODE)
125 capabilities |= CAP_UNICODE;
127 if (cli->capabilities & CAP_LARGE_FILES)
128 capabilities |= CAP_LARGE_FILES;
133 /****************************************************************************
134 Do a NT1 guest session setup.
135 ****************************************************************************/
137 static BOOL cli_session_setup_guest(struct cli_state *cli)
140 uint32 capabilities = cli_session_setup_capabilities(cli);
142 set_message(cli->outbuf,13,0,True);
143 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
144 cli_setup_packet(cli);
146 SCVAL(cli->outbuf,smb_vwv0,0xFF);
147 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
148 SSVAL(cli->outbuf,smb_vwv3,2);
149 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
150 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
151 SSVAL(cli->outbuf,smb_vwv7,0);
152 SSVAL(cli->outbuf,smb_vwv8,0);
153 SIVAL(cli->outbuf,smb_vwv11,capabilities);
154 p = smb_buf(cli->outbuf);
155 p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */
156 p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */
157 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
158 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
159 cli_setup_bcc(cli, p);
162 if (!cli_receive_smb(cli))
165 show_msg(cli->inbuf);
167 if (cli_is_error(cli))
170 cli->vuid = SVAL(cli->inbuf,smb_uid);
172 p = smb_buf(cli->inbuf);
173 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
174 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
175 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
177 fstrcpy(cli->user_name, "");
182 /****************************************************************************
183 Do a NT1 plaintext session setup.
184 ****************************************************************************/
186 static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
187 const char *pass, const char *workgroup)
189 uint32 capabilities = cli_session_setup_capabilities(cli);
193 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
195 set_message(cli->outbuf,13,0,True);
196 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
197 cli_setup_packet(cli);
199 SCVAL(cli->outbuf,smb_vwv0,0xFF);
200 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
201 SSVAL(cli->outbuf,smb_vwv3,2);
202 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
203 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
204 SSVAL(cli->outbuf,smb_vwv8,0);
205 SIVAL(cli->outbuf,smb_vwv11,capabilities);
206 p = smb_buf(cli->outbuf);
208 /* check wether to send the ASCII or UNICODE version of the password */
210 if ( (capabilities & CAP_UNICODE) == 0 ) {
211 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
212 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
215 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
216 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf)));
219 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
220 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
221 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
222 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
223 cli_setup_bcc(cli, p);
226 if (!cli_receive_smb(cli))
229 show_msg(cli->inbuf);
231 if (cli_is_error(cli))
234 cli->vuid = SVAL(cli->inbuf,smb_uid);
235 p = smb_buf(cli->inbuf);
236 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
237 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
238 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
239 fstrcpy(cli->user_name, user);
245 * Set the user session key for a connection
246 * @param cli The cli structure to add it too
247 * @param session_key The session key used. (A copy of this is taken for the cli struct)
251 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
253 cli->user_session_key = data_blob(session_key.data, session_key.length);
256 /****************************************************************************
257 do a NT1 NTLM/LM encrypted session setup - for when extended security
259 @param cli client state to create do session setup on
261 @param pass *either* cleartext password (passlen !=24) or LM response.
262 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
263 @param workgroup The user's domain.
264 ****************************************************************************/
266 static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
267 const char *pass, size_t passlen,
268 const char *ntpass, size_t ntpasslen,
269 const char *workgroup)
271 uint32 capabilities = cli_session_setup_capabilities(cli);
272 DATA_BLOB lm_response = data_blob(NULL, 0);
273 DATA_BLOB nt_response = data_blob(NULL, 0);
274 DATA_BLOB session_key = data_blob(NULL, 0);
279 /* do nothing - guest login */
280 } else if (passlen != 24) {
281 if (lp_client_ntlmv2_auth()) {
282 DATA_BLOB server_chal;
283 DATA_BLOB names_blob;
284 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
286 /* note that the 'workgroup' here is a best guess - we don't know
287 the server's domain at this point. The 'server name' is also
290 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
292 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
294 &lm_response, &nt_response, &session_key)) {
295 data_blob_free(&names_blob);
296 data_blob_free(&server_chal);
299 data_blob_free(&names_blob);
300 data_blob_free(&server_chal);
304 E_md4hash(pass, nt_hash);
306 nt_response = data_blob(NULL, 24);
307 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
309 /* non encrypted password supplied. Ignore ntpass. */
310 if (lp_client_lanman_auth()) {
311 lm_response = data_blob(NULL, 24);
312 SMBencrypt(pass,cli->secblob.data, lm_response.data);
314 /* LM disabled, place NT# in LM field instead */
315 lm_response = data_blob(nt_response.data, nt_response.length);
318 session_key = data_blob(NULL, 16);
319 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
321 cli_simple_set_signing(cli, session_key, nt_response);
323 /* pre-encrypted password supplied. Only used for
324 security=server, can't do
325 signing because we don't have original key */
327 lm_response = data_blob(pass, passlen);
328 nt_response = data_blob(ntpass, ntpasslen);
331 /* send a session setup command */
332 memset(cli->outbuf,'\0',smb_size);
334 set_message(cli->outbuf,13,0,True);
335 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
336 cli_setup_packet(cli);
338 SCVAL(cli->outbuf,smb_vwv0,0xFF);
339 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
340 SSVAL(cli->outbuf,smb_vwv3,2);
341 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
342 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
343 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
344 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
345 SIVAL(cli->outbuf,smb_vwv11,capabilities);
346 p = smb_buf(cli->outbuf);
347 if (lm_response.length) {
348 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
350 if (nt_response.length) {
351 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
353 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
354 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE);
355 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
356 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
357 cli_setup_bcc(cli, p);
359 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
364 /* show_msg(cli->inbuf); */
366 if (cli_is_error(cli)) {
371 /* use the returned vuid from now on */
372 cli->vuid = SVAL(cli->inbuf,smb_uid);
374 p = smb_buf(cli->inbuf);
375 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
376 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
377 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
379 fstrcpy(cli->user_name, user);
381 if (session_key.data) {
382 /* Have plaintext orginal */
383 cli_set_session_key(cli, session_key);
388 data_blob_free(&lm_response);
389 data_blob_free(&nt_response);
392 data_blob_free(&session_key);
396 /****************************************************************************
397 Send a extended security session setup blob
398 ****************************************************************************/
400 static BOOL cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
402 uint32 capabilities = cli_session_setup_capabilities(cli);
405 capabilities |= CAP_EXTENDED_SECURITY;
407 /* send a session setup command */
408 memset(cli->outbuf,'\0',smb_size);
410 set_message(cli->outbuf,12,0,True);
411 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
413 cli_setup_packet(cli);
415 SCVAL(cli->outbuf,smb_vwv0,0xFF);
416 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
417 SSVAL(cli->outbuf,smb_vwv3,2);
418 SSVAL(cli->outbuf,smb_vwv4,1);
419 SIVAL(cli->outbuf,smb_vwv5,0);
420 SSVAL(cli->outbuf,smb_vwv7,blob.length);
421 SIVAL(cli->outbuf,smb_vwv10,capabilities);
422 p = smb_buf(cli->outbuf);
423 memcpy(p, blob.data, blob.length);
425 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
426 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
427 cli_setup_bcc(cli, p);
428 return cli_send_smb(cli);
431 /****************************************************************************
432 Send a extended security session setup blob, returning a reply blob.
433 ****************************************************************************/
435 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
437 DATA_BLOB blob2 = data_blob(NULL, 0);
441 if (!cli_receive_smb(cli))
444 show_msg(cli->inbuf);
446 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
447 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
451 /* use the returned vuid from now on */
452 cli->vuid = SVAL(cli->inbuf,smb_uid);
454 p = smb_buf(cli->inbuf);
456 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
459 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
461 /* w2k with kerberos doesn't properly null terminate this field */
462 len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf));
463 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
470 /****************************************************************************
471 Send a extended security session setup blob, returning a reply blob.
472 ****************************************************************************/
474 static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
476 DATA_BLOB blob2 = data_blob(NULL, 0);
477 if (!cli_session_setup_blob_send(cli, blob)) {
481 return cli_session_setup_blob_receive(cli);
484 /****************************************************************************
485 Use in-memory credentials cache
486 ****************************************************************************/
488 static void use_in_memory_ccache(void) {
489 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
492 /****************************************************************************
493 Do a spnego/kerberos encrypted session setup.
494 ****************************************************************************/
496 static NTSTATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
498 DATA_BLOB blob2, negTokenTarg;
499 DATA_BLOB session_key_krb5;
500 DATA_BLOB null_blob = data_blob(NULL, 0);
502 DEBUG(2,("Doing kerberos session setup\n"));
504 /* generate the encapsulated kerberos5 ticket */
505 negTokenTarg = spnego_gen_negTokenTarg(principal, 0, &session_key_krb5);
507 if (!negTokenTarg.data)
508 return NT_STATUS_UNSUCCESSFUL;
511 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
514 cli_simple_set_signing(cli, session_key_krb5, null_blob);
516 blob2 = cli_session_setup_blob(cli, negTokenTarg);
518 /* we don't need this blob for kerberos */
519 data_blob_free(&blob2);
521 cli_set_session_key(cli, session_key_krb5);
523 data_blob_free(&negTokenTarg);
525 if (cli_is_error(cli)) {
526 if (NT_STATUS_IS_OK(cli_nt_error(cli))) {
527 return NT_STATUS_UNSUCCESSFUL;
532 #endif /* HAVE_KRB5 */
535 /****************************************************************************
536 Do a spnego/NTLMSSP encrypted session setup.
537 ****************************************************************************/
539 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
540 const char *pass, const char *workgroup)
542 struct ntlmssp_state *ntlmssp_state;
547 DATA_BLOB blob_in = data_blob(NULL, 0);
550 cli_temp_set_signing(cli);
552 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
556 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
559 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, workgroup))) {
562 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
567 nt_status = ntlmssp_update(ntlmssp_state,
569 data_blob_free(&blob_in);
570 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
571 DATA_BLOB null_blob = data_blob(NULL, 0);
573 /* and wrap it in a SPNEGO wrapper */
574 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
576 /* wrap it in SPNEGO */
577 msg1 = spnego_gen_auth(blob_out);
580 cli_simple_set_signing(cli,
581 data_blob(ntlmssp_state->session_key.data, ntlmssp_state->session_key.length),
584 /* now send that blob on its way */
585 if (!cli_session_setup_blob_send(cli, msg1)) {
586 DEBUG(3, ("Failed to send NTLMSSP/SPENGO blob to server!\n"));
587 nt_status = NT_STATUS_UNSUCCESSFUL;
589 data_blob_free(&msg1);
591 blob = cli_session_setup_blob_receive(cli);
593 nt_status = cli_nt_error(cli);
594 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
595 if (cli->smb_rw_error == READ_BAD_SIG) {
596 nt_status = NT_STATUS_ACCESS_DENIED;
598 nt_status = NT_STATUS_UNSUCCESSFUL;
605 if (NT_STATUS_IS_OK(nt_status)) {
606 nt_status = NT_STATUS_UNSUCCESSFUL;
608 } else if ((turn == 1) &&
609 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
610 DATA_BLOB tmp_blob = data_blob(NULL, 0);
611 /* the server might give us back two challenges */
612 if (!spnego_parse_challenge(blob, &blob_in,
614 DEBUG(3,("Failed to parse challenges\n"));
615 nt_status = NT_STATUS_INVALID_PARAMETER;
617 data_blob_free(&tmp_blob);
619 if (!spnego_parse_auth_response(blob, nt_status,
621 DEBUG(3,("Failed to parse auth response\n"));
622 if (NT_STATUS_IS_OK(nt_status)
623 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
624 nt_status = NT_STATUS_INVALID_PARAMETER;
627 data_blob_free(&blob);
628 data_blob_free(&blob_out);
630 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
632 if (NT_STATUS_IS_OK(nt_status)) {
633 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
634 cli_set_session_key(cli, ntlmssp_state->session_key);
637 /* we have a reference conter on ntlmssp_state, if we are signing
638 then the state will be kept by the signing engine */
640 ntlmssp_end(&ntlmssp_state);
645 /****************************************************************************
646 Do a spnego encrypted session setup.
647 ****************************************************************************/
649 NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
650 const char *pass, const char *workgroup)
653 char *OIDs[ASN1_MAX_OIDS];
655 BOOL got_kerberos_mechanism = False;
658 DEBUG(2,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
660 /* the server might not even do spnego */
661 if (cli->secblob.length <= 16) {
662 DEBUG(3,("server didn't supply a full spnego negprot\n"));
667 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
670 /* there is 16 bytes of GUID before the real spnego packet starts */
671 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
673 /* the server sent us the first part of the SPNEGO exchange in the negprot
675 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
676 data_blob_free(&blob);
677 return NT_STATUS_INVALID_PARAMETER;
679 data_blob_free(&blob);
681 /* make sure the server understands kerberos */
682 for (i=0;OIDs[i];i++) {
683 DEBUG(3,("got OID=%s\n", OIDs[i]));
684 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
685 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
686 got_kerberos_mechanism = True;
690 DEBUG(3,("got principal=%s\n", principal));
692 fstrcpy(cli->user_name, user);
695 /* If password is set we reauthenticate to kerberos server
696 * and do not store results */
698 if (got_kerberos_mechanism && cli->use_kerberos) {
702 use_in_memory_ccache();
703 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */);
706 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
707 return NT_STATUS_LOGON_FAILURE;
711 return cli_session_setup_kerberos(cli, principal, workgroup);
719 return cli_session_setup_ntlmssp(cli, user, pass, workgroup);
722 /****************************************************************************
723 Send a session setup. The username and workgroup is in UNIX character
724 format and must be converted to DOS codepage format before sending. If the
725 password is in plaintext, the same should be done.
726 ****************************************************************************/
728 BOOL cli_session_setup(struct cli_state *cli,
730 const char *pass, int passlen,
731 const char *ntpass, int ntpasslen,
732 const char *workgroup)
737 /* allow for workgroups as part of the username */
738 fstrcpy(user2, user);
739 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
740 (p=strchr_m(user2,*lp_winbind_separator()))) {
746 if (cli->protocol < PROTOCOL_LANMAN1)
749 /* now work out what sort of session setup we are going to
750 do. I have split this into separate functions to make the
751 flow a bit easier to understand (tridge) */
753 /* if its an older server then we have to use the older request format */
755 if (cli->protocol < PROTOCOL_NT1) {
756 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
757 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
762 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
763 !lp_client_plaintext_auth() && (*pass)) {
764 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
769 return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
772 /* if no user is supplied then we have to do an anonymous connection.
773 passwords are ignored */
776 return cli_session_setup_guest(cli);
778 /* if the server is share level then send a plaintext null
779 password at this point. The password is sent in the tree
782 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
783 return cli_session_setup_plaintext(cli, user, "", workgroup);
785 /* if the server doesn't support encryption then we have to use
786 plaintext. The second password is ignored */
788 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
789 if (!lp_client_plaintext_auth() && (*pass)) {
790 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
794 return cli_session_setup_plaintext(cli, user, pass, workgroup);
797 /* if the server supports extended security then use SPNEGO */
799 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
801 if (!NT_STATUS_IS_OK(nt_status = cli_session_setup_spnego(cli, user, pass, workgroup))) {
802 DEBUG(3, ("SPENGO login failed: %s\n", get_friendly_nt_error_msg(nt_status)));
808 /* otherwise do a NT1 style session setup */
810 return cli_session_setup_nt1(cli, user,
811 pass, passlen, ntpass, ntpasslen,
815 /****************************************************************************
817 *****************************************************************************/
819 BOOL cli_ulogoff(struct cli_state *cli)
821 memset(cli->outbuf,'\0',smb_size);
822 set_message(cli->outbuf,2,0,True);
823 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
824 cli_setup_packet(cli);
825 SSVAL(cli->outbuf,smb_vwv0,0xFF);
826 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
829 if (!cli_receive_smb(cli))
832 return !cli_is_error(cli);
835 /****************************************************************************
837 ****************************************************************************/
838 BOOL cli_send_tconX(struct cli_state *cli,
839 const char *share, const char *dev, const char *pass, int passlen)
841 fstring fullshare, pword;
843 memset(cli->outbuf,'\0',smb_size);
844 memset(cli->inbuf,'\0',smb_size);
846 fstrcpy(cli->share, share);
848 /* in user level security don't send a password now */
849 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
854 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
855 if (!lp_client_lanman_auth()) {
856 DEBUG(1, ("Server requested LANMAN password but 'client use lanman auth'"
862 * Non-encrypted passwords - convert to DOS codepage before encryption.
865 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
867 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
868 if (!lp_client_plaintext_auth() && (*pass)) {
869 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
875 * Non-encrypted passwords - convert to DOS codepage before using.
877 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
880 memcpy(pword, pass, passlen);
884 slprintf(fullshare, sizeof(fullshare)-1,
885 "\\\\%s\\%s", cli->desthost, share);
887 set_message(cli->outbuf,4, 0, True);
888 SCVAL(cli->outbuf,smb_com,SMBtconX);
889 cli_setup_packet(cli);
891 SSVAL(cli->outbuf,smb_vwv0,0xFF);
892 SSVAL(cli->outbuf,smb_vwv3,passlen);
894 p = smb_buf(cli->outbuf);
895 memcpy(p,pword,passlen);
897 p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
898 fstrcpy(p, dev); p += strlen(dev)+1;
900 cli_setup_bcc(cli, p);
903 if (!cli_receive_smb(cli))
906 if (cli_is_error(cli))
909 clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
911 if (cli->protocol >= PROTOCOL_NT1 &&
912 smb_buflen(cli->inbuf) == 3) {
913 /* almost certainly win95 - enable bug fixes */
917 cli->cnum = SVAL(cli->inbuf,smb_tid);
921 /****************************************************************************
922 Send a tree disconnect.
923 ****************************************************************************/
925 BOOL cli_tdis(struct cli_state *cli)
927 memset(cli->outbuf,'\0',smb_size);
928 set_message(cli->outbuf,0,0,True);
929 SCVAL(cli->outbuf,smb_com,SMBtdis);
930 SSVAL(cli->outbuf,smb_tid,cli->cnum);
931 cli_setup_packet(cli);
934 if (!cli_receive_smb(cli))
937 return !cli_is_error(cli);
940 /****************************************************************************
941 Send a negprot command.
942 ****************************************************************************/
944 void cli_negprot_send(struct cli_state *cli)
949 if (cli->protocol < PROTOCOL_NT1)
950 cli->use_spnego = False;
952 memset(cli->outbuf,'\0',smb_size);
954 /* setup the protocol strings */
955 set_message(cli->outbuf,0,0,True);
957 p = smb_buf(cli->outbuf);
959 prots[numprots].name && prots[numprots].prot<=cli->protocol;
962 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
965 SCVAL(cli->outbuf,smb_com,SMBnegprot);
966 cli_setup_bcc(cli, p);
967 cli_setup_packet(cli);
969 SCVAL(smb_buf(cli->outbuf),0,2);
974 /****************************************************************************
975 Send a negprot command.
976 ****************************************************************************/
978 BOOL cli_negprot(struct cli_state *cli)
984 if (cli->protocol < PROTOCOL_NT1)
985 cli->use_spnego = False;
987 memset(cli->outbuf,'\0',smb_size);
989 /* setup the protocol strings */
990 for (plength=0,numprots=0;
991 prots[numprots].name && prots[numprots].prot<=cli->protocol;
993 plength += strlen(prots[numprots].name)+2;
995 set_message(cli->outbuf,0,plength,True);
997 p = smb_buf(cli->outbuf);
999 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1002 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1005 SCVAL(cli->outbuf,smb_com,SMBnegprot);
1006 cli_setup_packet(cli);
1008 SCVAL(smb_buf(cli->outbuf),0,2);
1011 if (!cli_receive_smb(cli))
1014 show_msg(cli->inbuf);
1016 if (cli_is_error(cli) ||
1017 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1021 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
1023 if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1024 DEBUG(1,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1028 if (cli->protocol >= PROTOCOL_NT1) {
1030 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1031 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
1032 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1033 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1034 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
1035 cli->serverzone *= 60;
1036 /* this time arrives in real GMT */
1037 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
1038 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1039 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1040 if (cli->capabilities & CAP_RAW_MODE) {
1041 cli->readbraw_supported = True;
1042 cli->writebraw_supported = True;
1044 /* work out if they sent us a workgroup */
1045 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1046 smb_buflen(cli->inbuf) > 8) {
1047 clistr_pull(cli, cli->server_domain,
1048 smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1049 smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1053 * As signing is slow we only turn it on if either the client or
1054 * the server require it. JRA.
1057 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1058 /* Fail if server says signing is mandatory and we don't want to support it. */
1059 if (!cli->sign_info.allow_smb_signing) {
1060 DEBUG(1,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1063 cli->sign_info.negotiated_smb_signing = True;
1064 cli->sign_info.mandatory_signing = True;
1065 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1066 /* Fail if client says signing is mandatory and the server doesn't support it. */
1067 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1068 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1071 cli->sign_info.negotiated_smb_signing = True;
1072 cli->sign_info.mandatory_signing = True;
1075 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1076 cli->use_spnego = False;
1077 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1078 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1079 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1080 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1081 cli->serverzone *= 60;
1082 /* this time is converted to GMT by make_unix_date */
1083 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
1084 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1085 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1086 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1088 /* the old core protocol */
1089 cli->use_spnego = False;
1091 cli->serverzone = TimeDiff(time(NULL));
1094 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1096 /* a way to force ascii SMB */
1097 if (getenv("CLI_FORCE_ASCII"))
1098 cli->capabilities &= ~CAP_UNICODE;
1103 /****************************************************************************
1104 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1105 ****************************************************************************/
1107 BOOL cli_session_request(struct cli_state *cli,
1108 struct nmb_name *calling, struct nmb_name *called)
1112 extern pstring user_socket_options;
1114 memcpy(&(cli->calling), calling, sizeof(*calling));
1115 memcpy(&(cli->called ), called , sizeof(*called ));
1117 /* put in the destination name */
1118 p = cli->outbuf+len;
1119 name_mangle(cli->called .name, p, cli->called .name_type);
1123 p = cli->outbuf+len;
1124 name_mangle(cli->calling.name, p, cli->calling.name_type);
1127 /* 445 doesn't have session request */
1128 if (cli->port == 445)
1131 /* send a session request (RFC 1002) */
1132 /* setup the packet length
1133 * Remove four bytes from the length count, since the length
1134 * field in the NBT Session Service header counts the number
1135 * of bytes which follow. The cli_send_smb() function knows
1136 * about this and accounts for those four bytes.
1140 _smb_setlen(cli->outbuf,len);
1141 SCVAL(cli->outbuf,0,0x81);
1144 DEBUG(5,("Sent session request\n"));
1146 if (!cli_receive_smb(cli))
1149 if (CVAL(cli->inbuf,0) == 0x84) {
1150 /* C. Hoch 9/14/95 Start */
1151 /* For information, here is the response structure.
1152 * We do the byte-twiddling to for portability.
1153 struct RetargetResponse{
1155 unsigned char flags;
1161 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1162 /* SESSION RETARGET */
1163 putip((char *)&cli->dest_ip,cli->inbuf+4);
1165 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
1169 DEBUG(3,("Retargeted\n"));
1171 set_socket_options(cli->fd,user_socket_options);
1178 DEBUG(0,("Retarget recursion - failing\n"));
1182 ret = cli_session_request(cli, calling, called);
1186 } /* C. Hoch 9/14/95 End */
1188 if (CVAL(cli->inbuf,0) != 0x82) {
1189 /* This is the wrong place to put the error... JRA. */
1190 cli->rap_error = CVAL(cli->inbuf,4);
1196 /****************************************************************************
1197 Open the client sockets.
1198 ****************************************************************************/
1200 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
1202 extern pstring user_socket_options;
1203 int name_type = 0x20;
1206 /* reasonable default hostname */
1207 if (!host) host = "*SMBSERVER";
1209 fstrcpy(cli->desthost, host);
1211 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1212 if ((p = strchr(cli->desthost, '#'))) {
1213 name_type = strtol(p+1, NULL, 16);
1217 if (!ip || is_zero_ip(*ip)) {
1218 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
1221 if (ip) *ip = cli->dest_ip;
1226 if (getenv("LIBSMB_PROG")) {
1227 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1229 /* try 445 first, then 139 */
1230 int port = cli->port?cli->port:445;
1231 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1232 port, cli->timeout);
1233 if (cli->fd == -1 && cli->port == 0) {
1235 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1236 port, cli->timeout);
1241 if (cli->fd == -1) {
1242 DEBUG(1,("Error connecting to %s (%s)\n",
1243 ip?inet_ntoa(*ip):host,strerror(errno)));
1247 set_socket_options(cli->fd,user_socket_options);
1252 /****************************************************************************
1253 Initialise client credentials for authenticated pipe access.
1254 ****************************************************************************/
1256 void init_creds(struct ntuser_creds *creds, const char* username,
1257 const char* domain, const char* password)
1259 ZERO_STRUCTP(creds);
1261 pwd_set_cleartext(&creds->pwd, password);
1263 fstrcpy(creds->user_name, username);
1264 fstrcpy(creds->domain, domain);
1267 creds->pwd.null_pwd = True;
1272 establishes a connection to after the negprot.
1273 @param output_cli A fully initialised cli structure, non-null only on success
1274 @param dest_host The netbios name of the remote host
1275 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1276 @param port (optional) The destination port (0 for default)
1277 @param retry BOOL. Did this connection fail with a retryable error ?
1280 NTSTATUS cli_start_connection(struct cli_state **output_cli,
1281 const char *my_name,
1282 const char *dest_host,
1283 struct in_addr *dest_ip, int port,
1284 int signing_state, int flags,
1288 struct nmb_name calling;
1289 struct nmb_name called;
1290 struct cli_state *cli;
1297 my_name = global_myname();
1299 if (!(cli = cli_initialise(NULL)))
1300 return NT_STATUS_NO_MEMORY;
1302 make_nmb_name(&calling, my_name, 0x0);
1303 make_nmb_name(&called , dest_host, 0x20);
1305 if (cli_set_port(cli, port) != port) {
1307 return NT_STATUS_UNSUCCESSFUL;
1310 cli_set_timeout(cli, 10000); /* 10 seconds. */
1319 DEBUG(3,("Connecting to host=%s\n", dest_host));
1321 if (!cli_connect(cli, dest_host, &ip)) {
1322 DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
1323 nmb_namestr(&called), inet_ntoa(ip)));
1325 return NT_STATUS_UNSUCCESSFUL;
1331 if (!cli_session_request(cli, &calling, &called)) {
1333 DEBUG(1,("session request to %s failed (%s)\n",
1334 called.name, cli_errstr(cli)));
1335 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1339 if (strcmp(called.name, "*SMBSERVER")) {
1340 make_nmb_name(&called , "*SMBSERVER", 0x20);
1343 return NT_STATUS_UNSUCCESSFUL;
1346 cli_setup_signing_state(cli, signing_state);
1348 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1349 cli->use_spnego = False;
1350 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1351 cli->use_kerberos = True;
1353 if (!cli_negprot(cli)) {
1354 DEBUG(1,("failed negprot\n"));
1355 nt_status = NT_STATUS_UNSUCCESSFUL;
1361 return NT_STATUS_OK;
1366 establishes a connection right up to doing tconX, password specified.
1367 @param output_cli A fully initialised cli structure, non-null only on success
1368 @param dest_host The netbios name of the remote host
1369 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1370 @param port (optional) The destination port (0 for default)
1371 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
1372 @param service_type The 'type' of serivice.
1373 @param user Username, unix string
1374 @param domain User's domain
1375 @param password User's password, unencrypted unix string.
1376 @param retry BOOL. Did this connection fail with a retryable error ?
1379 NTSTATUS cli_full_connection(struct cli_state **output_cli,
1380 const char *my_name,
1381 const char *dest_host,
1382 struct in_addr *dest_ip, int port,
1383 const char *service, const char *service_type,
1384 const char *user, const char *domain,
1385 const char *password, int flags,
1389 struct ntuser_creds creds;
1391 struct cli_state *cli = NULL;
1393 nt_status = cli_start_connection(&cli, my_name, dest_host,
1394 dest_ip, port, signing_state, flags, retry);
1396 if (!NT_STATUS_IS_OK(nt_status)) {
1400 if (!cli_session_setup(cli, user, password, strlen(password)+1,
1401 password, strlen(password)+1,
1403 if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
1404 && cli_session_setup(cli, "", "", 0, "", 0, domain)) {
1406 nt_status = cli_nt_error(cli);
1407 DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
1409 if (NT_STATUS_IS_OK(nt_status))
1410 nt_status = NT_STATUS_UNSUCCESSFUL;
1416 if (!cli_send_tconX(cli, service, service_type,
1417 password, strlen(password)+1)) {
1418 nt_status = cli_nt_error(cli);
1419 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1421 if (NT_STATUS_IS_OK(nt_status)) {
1422 nt_status = NT_STATUS_UNSUCCESSFUL;
1428 init_creds(&creds, user, domain, password);
1429 cli_init_creds(cli, &creds);
1432 return NT_STATUS_OK;
1435 /****************************************************************************
1436 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1437 ****************************************************************************/
1439 BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
1440 struct in_addr *pdest_ip)
1442 struct nmb_name calling, called;
1444 make_nmb_name(&calling, srchost, 0x0);
1447 * If the called name is an IP address
1448 * then use *SMBSERVER immediately.
1451 if(is_ipaddress(desthost))
1452 make_nmb_name(&called, "*SMBSERVER", 0x20);
1454 make_nmb_name(&called, desthost, 0x20);
1456 if (!cli_session_request(cli, &calling, &called)) {
1457 struct nmb_name smbservername;
1459 make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
1462 * If the name wasn't *SMBSERVER then
1463 * try with *SMBSERVER if the first name fails.
1466 if (nmb_name_equal(&called, &smbservername)) {
1469 * The name used was *SMBSERVER, don't bother with another name.
1472 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1473 with error %s.\n", desthost, cli_errstr(cli) ));
1478 * We need to close the connection here but can't call cli_shutdown as
1479 * will free an allocated cli struct. cli_close_connection was invented
1480 * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
1483 cli_close_connection(cli);
1485 if (!cli_initialise(cli) ||
1486 !cli_connect(cli, desthost, pdest_ip) ||
1487 !cli_session_request(cli, &calling, &smbservername)) {
1488 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1489 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
1501 /****************************************************************************
1502 Send an old style tcon.
1503 ****************************************************************************/
1504 NTSTATUS cli_raw_tcon(struct cli_state *cli,
1505 const char *service, const char *pass, const char *dev,
1506 uint16 *max_xmit, uint16 *tid)
1510 if (!lp_client_plaintext_auth() && (*pass)) {
1511 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1513 return NT_STATUS_ACCESS_DENIED;
1516 memset(cli->outbuf,'\0',smb_size);
1517 memset(cli->inbuf,'\0',smb_size);
1519 set_message(cli->outbuf, 0, 0, True);
1520 SCVAL(cli->outbuf,smb_com,SMBtcon);
1521 cli_setup_packet(cli);
1523 p = smb_buf(cli->outbuf);
1524 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1525 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1526 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1528 cli_setup_bcc(cli, p);
1531 if (!cli_receive_smb(cli)) {
1532 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1535 if (cli_is_error(cli)) {
1536 return cli_nt_error(cli);
1539 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
1540 *tid = SVAL(cli->inbuf, smb_vwv1);
1542 return NT_STATUS_OK;
1545 /* Return a cli_state pointing at the IPC$ share for the given server */
1547 struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
1548 struct user_auth_info *user_info)
1550 struct cli_state *cli;
1556 nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC",
1557 user_info->username, lp_workgroup(), user_info->password,
1558 CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, NULL);
1560 if (NT_STATUS_IS_OK(nt_status)) {
1562 } else if (is_ipaddress(server)) {
1563 /* windows 9* needs a correct NMB name for connections */
1564 fstring remote_name;
1566 if (name_status_find("*", 0, 0, *server_ip, remote_name)) {
1567 cli = get_ipc_connect(remote_name, server_ip, user_info);
1575 /* Return the IP address and workgroup of a master browser on the
1578 struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
1580 struct ip_service *ip_list;
1581 struct cli_state *cli;
1583 struct in_addr server_ip;
1585 /* Go looking for workgroups by broadcasting on the local network */
1587 if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
1591 for (i = 0; i < count; i++) {
1592 static fstring name;
1594 if (!name_status_find("*", 0, 0x1d, ip_list[i].ip, name))
1597 if (!find_master_ip(name, &server_ip))
1600 pstrcpy(workgroup, name);
1602 DEBUG(4, ("found master browser %s, %s\n",
1603 name, inet_ntoa(ip_list[i].ip)));
1605 cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);