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 snprintf( lanman, sizeof(lanman), "Samba %s", VERSION );
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);
244 static void set_cli_session_key (struct cli_state *cli, DATA_BLOB session_key)
246 memcpy(cli->user_session_key, session_key.data, MIN(session_key.length, sizeof(cli->user_session_key)));
249 /****************************************************************************
250 do a NT1 NTLM/LM encrypted session setup
251 @param cli client state to create do session setup on
253 @param pass *either* cleartext password (passlen !=24) or LM response.
254 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
255 @param workgroup The user's domain.
256 ****************************************************************************/
258 static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
259 const char *pass, size_t passlen,
260 const char *ntpass, size_t ntpasslen,
261 const char *workgroup)
263 uint32 capabilities = cli_session_setup_capabilities(cli);
264 DATA_BLOB lm_response = data_blob(NULL, 0);
265 DATA_BLOB nt_response = data_blob(NULL, 0);
266 DATA_BLOB session_key = data_blob(NULL, 0);
271 if (lp_client_ntlmv2_auth()) {
272 DATA_BLOB server_chal;
273 DATA_BLOB names_blob;
274 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
276 /* note that the 'workgroup' here is a best guess - we don't know
277 the server's domain at this point. The 'server name' is also
280 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
282 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
284 &lm_response, &nt_response, &session_key)) {
285 data_blob_free(&names_blob);
286 data_blob_free(&server_chal);
289 data_blob_free(&names_blob);
290 data_blob_free(&server_chal);
294 E_md4hash(pass, nt_hash);
296 nt_response = data_blob(NULL, 24);
297 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
299 /* non encrypted password supplied. Ignore ntpass. */
300 if (lp_client_lanman_auth()) {
301 lm_response = data_blob(NULL, 24);
302 SMBencrypt(pass,cli->secblob.data, lm_response.data);
304 /* LM disabled, place NT# in LM field instead */
305 lm_response = data_blob(nt_response.data, nt_response.length);
308 session_key = data_blob(NULL, 16);
309 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
311 cli_simple_set_signing(cli, session_key.data, nt_response);
313 /* pre-encrypted password supplied. Only used for
314 security=server, can't do
315 signing because we don't have original key */
317 lm_response = data_blob(pass, passlen);
318 nt_response = data_blob(ntpass, ntpasslen);
321 /* send a session setup command */
322 memset(cli->outbuf,'\0',smb_size);
324 set_message(cli->outbuf,13,0,True);
325 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
326 cli_setup_packet(cli);
328 SCVAL(cli->outbuf,smb_vwv0,0xFF);
329 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
330 SSVAL(cli->outbuf,smb_vwv3,2);
331 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
332 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
333 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
334 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
335 SIVAL(cli->outbuf,smb_vwv11,capabilities);
336 p = smb_buf(cli->outbuf);
337 if (lm_response.length) {
338 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
340 if (nt_response.length) {
341 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
343 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
344 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE);
345 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
346 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
347 cli_setup_bcc(cli, p);
349 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
354 show_msg(cli->inbuf);
356 if (cli_is_error(cli)) {
361 /* use the returned vuid from now on */
362 cli->vuid = SVAL(cli->inbuf,smb_uid);
364 p = smb_buf(cli->inbuf);
365 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
366 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
367 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
369 fstrcpy(cli->user_name, user);
371 if (session_key.data) {
372 /* Have plaintext orginal */
373 set_cli_session_key(cli, session_key);
378 data_blob_free(&lm_response);
379 data_blob_free(&nt_response);
380 data_blob_free(&session_key);
384 /****************************************************************************
385 Send a extended security session setup blob
386 ****************************************************************************/
388 static BOOL cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
390 uint32 capabilities = cli_session_setup_capabilities(cli);
393 capabilities |= CAP_EXTENDED_SECURITY;
395 /* send a session setup command */
396 memset(cli->outbuf,'\0',smb_size);
398 set_message(cli->outbuf,12,0,True);
399 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
401 cli_setup_packet(cli);
403 SCVAL(cli->outbuf,smb_vwv0,0xFF);
404 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
405 SSVAL(cli->outbuf,smb_vwv3,2);
406 SSVAL(cli->outbuf,smb_vwv4,1);
407 SIVAL(cli->outbuf,smb_vwv5,0);
408 SSVAL(cli->outbuf,smb_vwv7,blob.length);
409 SIVAL(cli->outbuf,smb_vwv10,capabilities);
410 p = smb_buf(cli->outbuf);
411 memcpy(p, blob.data, blob.length);
413 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
414 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
415 cli_setup_bcc(cli, p);
416 return cli_send_smb(cli);
419 /****************************************************************************
420 Send a extended security session setup blob, returning a reply blob.
421 ****************************************************************************/
423 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
425 DATA_BLOB blob2 = data_blob(NULL, 0);
429 if (!cli_receive_smb(cli))
432 show_msg(cli->inbuf);
434 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
435 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
439 /* use the returned vuid from now on */
440 cli->vuid = SVAL(cli->inbuf,smb_uid);
442 p = smb_buf(cli->inbuf);
444 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
447 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
449 /* w2k with kerberos doesn't properly null terminate this field */
450 len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf));
451 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
458 /****************************************************************************
459 Send a extended security session setup blob, returning a reply blob.
460 ****************************************************************************/
462 static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
464 DATA_BLOB blob2 = data_blob(NULL, 0);
465 if (!cli_session_setup_blob_send(cli, blob)) {
469 return cli_session_setup_blob_receive(cli);
472 /****************************************************************************
473 Use in-memory credentials cache
474 ****************************************************************************/
475 static void use_in_memory_ccache(void) {
476 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
479 /****************************************************************************
480 Do a spnego/kerberos encrypted session setup.
481 ****************************************************************************/
483 static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
485 DATA_BLOB blob2, negTokenTarg;
487 DEBUG(2,("Doing kerberos session setup\n"));
489 /* generate the encapsulated kerberos5 ticket */
490 negTokenTarg = spnego_gen_negTokenTarg(principal, 0);
492 if (!negTokenTarg.data) return False;
495 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
498 blob2 = cli_session_setup_blob(cli, negTokenTarg);
500 /* we don't need this blob for kerberos */
501 data_blob_free(&blob2);
503 data_blob_free(&negTokenTarg);
505 return !cli_is_error(cli);
507 #endif /* HAVE_KRB5 */
510 /****************************************************************************
511 Do a spnego/NTLMSSP encrypted session setup.
512 ****************************************************************************/
514 static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
515 const char *pass, const char *workgroup)
517 struct ntlmssp_client_state *ntlmssp_state;
522 DATA_BLOB blob_in = data_blob(NULL, 0);
525 cli_temp_set_signing(cli);
527 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
531 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
534 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, workgroup))) {
537 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
541 ntlmssp_state->use_ntlmv2 = lp_client_ntlmv2_auth();
543 if (cli->sign_info.negotiated_smb_signing
544 || cli->sign_info.mandatory_signing) {
545 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
546 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
550 nt_status = ntlmssp_client_update(ntlmssp_state,
552 data_blob_free(&blob_in);
553 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
554 DATA_BLOB null = data_blob(NULL, 0);
556 /* and wrap it in a SPNEGO wrapper */
557 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
559 /* wrap it in SPNEGO */
560 msg1 = spnego_gen_auth(blob_out);
563 cli_simple_set_signing(cli,
564 ntlmssp_state->session_key.data,
567 /* now send that blob on its way */
568 if (!cli_session_setup_blob_send(cli, msg1)) {
571 data_blob_free(&msg1);
573 blob = cli_session_setup_blob_receive(cli);
575 nt_status = cli_nt_error(cli);
579 if (NT_STATUS_IS_OK(nt_status)) {
580 nt_status = NT_STATUS_UNSUCCESSFUL;
582 } else if ((turn == 1) &&
583 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
584 DATA_BLOB tmp_blob = data_blob(NULL, 0);
585 /* the server might give us back two challenges */
586 if (!spnego_parse_challenge(blob, &blob_in,
588 DEBUG(3,("Failed to parse challenges\n"));
589 nt_status = NT_STATUS_INVALID_PARAMETER;
591 data_blob_free(&tmp_blob);
593 if (!spnego_parse_auth_response(blob, nt_status,
595 DEBUG(3,("Failed to parse auth response\n"));
596 if (NT_STATUS_IS_OK(nt_status)
597 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
598 nt_status = NT_STATUS_INVALID_PARAMETER;
601 data_blob_free(&blob);
602 data_blob_free(&blob_out);
604 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
606 if (NT_STATUS_IS_OK(nt_status)) {
607 set_cli_session_key(cli, ntlmssp_state->session_key);
610 /* we have a reference conter on ntlmssp_state, if we are signing
611 then the state will be kept by the signing engine */
613 if (!NT_STATUS_IS_OK(ntlmssp_client_end(&ntlmssp_state))) {
617 return (NT_STATUS_IS_OK(nt_status));
620 /****************************************************************************
621 Do a spnego encrypted session setup.
622 ****************************************************************************/
624 static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
625 const char *pass, const char *workgroup)
628 char *OIDs[ASN1_MAX_OIDS];
630 BOOL got_kerberos_mechanism = False;
633 DEBUG(2,("Doing spnego session setup (blob length=%d)\n", cli->secblob.length));
635 /* the server might not even do spnego */
636 if (cli->secblob.length <= 16) {
637 DEBUG(3,("server didn't supply a full spnego negprot\n"));
642 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
645 /* there is 16 bytes of GUID before the real spnego packet starts */
646 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
648 /* the server sent us the first part of the SPNEGO exchange in the negprot
650 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
651 data_blob_free(&blob);
654 data_blob_free(&blob);
656 /* make sure the server understands kerberos */
657 for (i=0;OIDs[i];i++) {
658 DEBUG(3,("got OID=%s\n", OIDs[i]));
659 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
660 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
661 got_kerberos_mechanism = True;
665 DEBUG(3,("got principal=%s\n", principal));
667 fstrcpy(cli->user_name, user);
670 /* If password is set we reauthenticate to kerberos server
671 * and do not store results */
673 if (got_kerberos_mechanism && cli->use_kerberos) {
677 use_in_memory_ccache();
678 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */);
681 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
686 return cli_session_setup_kerberos(cli, principal, workgroup);
694 return cli_session_setup_ntlmssp(cli, user, pass, workgroup);
697 /****************************************************************************
698 Send a session setup. The username and workgroup is in UNIX character
699 format and must be converted to DOS codepage format before sending. If the
700 password is in plaintext, the same should be done.
701 ****************************************************************************/
703 BOOL cli_session_setup(struct cli_state *cli,
705 const char *pass, int passlen,
706 const char *ntpass, int ntpasslen,
707 const char *workgroup)
712 /* allow for workgroups as part of the username */
713 fstrcpy(user2, user);
714 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
715 (p=strchr_m(user2,*lp_winbind_separator()))) {
721 if (cli->protocol < PROTOCOL_LANMAN1)
724 /* now work out what sort of session setup we are going to
725 do. I have split this into separate functions to make the
726 flow a bit easier to understand (tridge) */
728 /* if its an older server then we have to use the older request format */
730 if (cli->protocol < PROTOCOL_NT1) {
731 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
732 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
737 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
738 !lp_client_plaintext_auth() && (*pass)) {
739 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
744 return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
747 /* if no user is supplied then we have to do an anonymous connection.
748 passwords are ignored */
751 return cli_session_setup_guest(cli);
753 /* if the server is share level then send a plaintext null
754 password at this point. The password is sent in the tree
757 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
758 return cli_session_setup_plaintext(cli, user, "", workgroup);
760 /* if the server doesn't support encryption then we have to use
761 plaintext. The second password is ignored */
763 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
764 if (!lp_client_plaintext_auth() && (*pass)) {
765 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
769 return cli_session_setup_plaintext(cli, user, pass, workgroup);
772 /* if the server supports extended security then use SPNEGO */
774 if (cli->capabilities & CAP_EXTENDED_SECURITY)
775 return cli_session_setup_spnego(cli, user, pass, workgroup);
777 /* otherwise do a NT1 style session setup */
779 return cli_session_setup_nt1(cli, user,
780 pass, passlen, ntpass, ntpasslen,
784 /****************************************************************************
786 *****************************************************************************/
788 BOOL cli_ulogoff(struct cli_state *cli)
790 memset(cli->outbuf,'\0',smb_size);
791 set_message(cli->outbuf,2,0,True);
792 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
793 cli_setup_packet(cli);
794 SSVAL(cli->outbuf,smb_vwv0,0xFF);
795 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
798 if (!cli_receive_smb(cli))
801 return !cli_is_error(cli);
804 /****************************************************************************
806 ****************************************************************************/
807 BOOL cli_send_tconX(struct cli_state *cli,
808 const char *share, const char *dev, const char *pass, int passlen)
810 fstring fullshare, pword;
812 memset(cli->outbuf,'\0',smb_size);
813 memset(cli->inbuf,'\0',smb_size);
815 fstrcpy(cli->share, share);
817 /* in user level security don't send a password now */
818 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
823 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
824 if (!lp_client_lanman_auth()) {
825 DEBUG(1, ("Server requested LANMAN password but 'client use lanman auth'"
831 * Non-encrypted passwords - convert to DOS codepage before encryption.
834 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
836 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
837 if (!lp_client_plaintext_auth() && (*pass)) {
838 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
844 * Non-encrypted passwords - convert to DOS codepage before using.
846 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
849 memcpy(pword, pass, passlen);
853 slprintf(fullshare, sizeof(fullshare)-1,
854 "\\\\%s\\%s", cli->desthost, share);
856 set_message(cli->outbuf,4, 0, True);
857 SCVAL(cli->outbuf,smb_com,SMBtconX);
858 cli_setup_packet(cli);
860 SSVAL(cli->outbuf,smb_vwv0,0xFF);
861 SSVAL(cli->outbuf,smb_vwv3,passlen);
863 p = smb_buf(cli->outbuf);
864 memcpy(p,pword,passlen);
866 p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
867 fstrcpy(p, dev); p += strlen(dev)+1;
869 cli_setup_bcc(cli, p);
872 if (!cli_receive_smb(cli))
875 if (cli_is_error(cli))
878 clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
880 if (cli->protocol >= PROTOCOL_NT1 &&
881 smb_buflen(cli->inbuf) == 3) {
882 /* almost certainly win95 - enable bug fixes */
886 cli->cnum = SVAL(cli->inbuf,smb_tid);
890 /****************************************************************************
891 Send a tree disconnect.
892 ****************************************************************************/
894 BOOL cli_tdis(struct cli_state *cli)
896 memset(cli->outbuf,'\0',smb_size);
897 set_message(cli->outbuf,0,0,True);
898 SCVAL(cli->outbuf,smb_com,SMBtdis);
899 SSVAL(cli->outbuf,smb_tid,cli->cnum);
900 cli_setup_packet(cli);
903 if (!cli_receive_smb(cli))
906 return !cli_is_error(cli);
909 /****************************************************************************
910 Send a negprot command.
911 ****************************************************************************/
913 void cli_negprot_send(struct cli_state *cli)
918 if (cli->protocol < PROTOCOL_NT1)
919 cli->use_spnego = False;
921 memset(cli->outbuf,'\0',smb_size);
923 /* setup the protocol strings */
924 set_message(cli->outbuf,0,0,True);
926 p = smb_buf(cli->outbuf);
928 prots[numprots].name && prots[numprots].prot<=cli->protocol;
931 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
934 SCVAL(cli->outbuf,smb_com,SMBnegprot);
935 cli_setup_bcc(cli, p);
936 cli_setup_packet(cli);
938 SCVAL(smb_buf(cli->outbuf),0,2);
943 /****************************************************************************
944 Send a negprot command.
945 ****************************************************************************/
947 BOOL cli_negprot(struct cli_state *cli)
953 if (cli->protocol < PROTOCOL_NT1)
954 cli->use_spnego = False;
956 memset(cli->outbuf,'\0',smb_size);
958 /* setup the protocol strings */
959 for (plength=0,numprots=0;
960 prots[numprots].name && prots[numprots].prot<=cli->protocol;
962 plength += strlen(prots[numprots].name)+2;
964 set_message(cli->outbuf,0,plength,True);
966 p = smb_buf(cli->outbuf);
968 prots[numprots].name && prots[numprots].prot<=cli->protocol;
971 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
974 SCVAL(cli->outbuf,smb_com,SMBnegprot);
975 cli_setup_packet(cli);
977 SCVAL(smb_buf(cli->outbuf),0,2);
980 if (!cli_receive_smb(cli))
983 show_msg(cli->inbuf);
985 if (cli_is_error(cli) ||
986 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
990 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
992 if (cli->protocol >= PROTOCOL_NT1) {
994 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
995 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
996 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
997 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
998 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
999 cli->serverzone *= 60;
1000 /* this time arrives in real GMT */
1001 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
1002 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1003 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1004 if (cli->capabilities & CAP_RAW_MODE) {
1005 cli->readbraw_supported = True;
1006 cli->writebraw_supported = True;
1008 /* work out if they sent us a workgroup */
1009 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1010 smb_buflen(cli->inbuf) > 8) {
1011 clistr_pull(cli, cli->server_domain,
1012 smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1013 smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1016 if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)) {
1017 /* Fail if signing is mandatory and we don't want to support it. */
1018 if (!lp_client_signing()) {
1019 DEBUG(1,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1022 cli->sign_info.negotiated_smb_signing = True;
1025 if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && cli->sign_info.allow_smb_signing)
1026 cli->sign_info.negotiated_smb_signing = True;
1028 /* Fail if signing is mandatory and the server doesn't support it. */
1029 if (cli->sign_info.mandatory_signing && !(cli->sign_info.negotiated_smb_signing)) {
1030 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1034 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1035 cli->use_spnego = False;
1036 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1037 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1038 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1039 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1040 cli->serverzone *= 60;
1041 /* this time is converted to GMT by make_unix_date */
1042 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
1043 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1044 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1045 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1047 /* the old core protocol */
1048 cli->use_spnego = False;
1050 cli->serverzone = TimeDiff(time(NULL));
1053 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1055 /* a way to force ascii SMB */
1056 if (getenv("CLI_FORCE_ASCII"))
1057 cli->capabilities &= ~CAP_UNICODE;
1062 /****************************************************************************
1063 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1064 ****************************************************************************/
1066 BOOL cli_session_request(struct cli_state *cli,
1067 struct nmb_name *calling, struct nmb_name *called)
1071 extern pstring user_socket_options;
1073 memcpy(&(cli->calling), calling, sizeof(*calling));
1074 memcpy(&(cli->called ), called , sizeof(*called ));
1076 /* put in the destination name */
1077 p = cli->outbuf+len;
1078 name_mangle(cli->called .name, p, cli->called .name_type);
1082 p = cli->outbuf+len;
1083 name_mangle(cli->calling.name, p, cli->calling.name_type);
1086 /* 445 doesn't have session request */
1087 if (cli->port == 445)
1090 /* send a session request (RFC 1002) */
1091 /* setup the packet length
1092 * Remove four bytes from the length count, since the length
1093 * field in the NBT Session Service header counts the number
1094 * of bytes which follow. The cli_send_smb() function knows
1095 * about this and accounts for those four bytes.
1099 _smb_setlen(cli->outbuf,len);
1100 SCVAL(cli->outbuf,0,0x81);
1103 DEBUG(5,("Sent session request\n"));
1105 if (!cli_receive_smb(cli))
1108 if (CVAL(cli->inbuf,0) == 0x84) {
1109 /* C. Hoch 9/14/95 Start */
1110 /* For information, here is the response structure.
1111 * We do the byte-twiddling to for portability.
1112 struct RetargetResponse{
1114 unsigned char flags;
1120 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1121 /* SESSION RETARGET */
1122 putip((char *)&cli->dest_ip,cli->inbuf+4);
1124 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
1128 DEBUG(3,("Retargeted\n"));
1130 set_socket_options(cli->fd,user_socket_options);
1137 DEBUG(0,("Retarget recursion - failing\n"));
1141 ret = cli_session_request(cli, calling, called);
1145 } /* C. Hoch 9/14/95 End */
1147 if (CVAL(cli->inbuf,0) != 0x82) {
1148 /* This is the wrong place to put the error... JRA. */
1149 cli->rap_error = CVAL(cli->inbuf,4);
1155 /****************************************************************************
1156 Open the client sockets.
1157 ****************************************************************************/
1159 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
1161 extern pstring user_socket_options;
1162 int name_type = 0x20;
1165 /* reasonable default hostname */
1166 if (!host) host = "*SMBSERVER";
1168 fstrcpy(cli->desthost, host);
1170 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1171 if ((p = strchr(cli->desthost, '#'))) {
1172 name_type = strtol(p+1, NULL, 16);
1176 if (!ip || is_zero_ip(*ip)) {
1177 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
1180 if (ip) *ip = cli->dest_ip;
1185 if (getenv("LIBSMB_PROG")) {
1186 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1188 /* try 445 first, then 139 */
1189 int port = cli->port?cli->port:445;
1190 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1191 port, cli->timeout);
1192 if (cli->fd == -1 && cli->port == 0) {
1194 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1195 port, cli->timeout);
1200 if (cli->fd == -1) {
1201 DEBUG(1,("Error connecting to %s (%s)\n",
1202 ip?inet_ntoa(*ip):host,strerror(errno)));
1206 set_socket_options(cli->fd,user_socket_options);
1211 /****************************************************************************
1212 Initialise client credentials for authenticated pipe access.
1213 ****************************************************************************/
1215 static void init_creds(struct ntuser_creds *creds, const char* username,
1216 const char* domain, const char* password)
1218 ZERO_STRUCTP(creds);
1220 pwd_set_cleartext(&creds->pwd, password);
1222 fstrcpy(creds->user_name, username);
1223 fstrcpy(creds->domain, domain);
1226 creds->pwd.null_pwd = True;
1231 establishes a connection right up to doing tconX, password specified.
1232 @param output_cli A fully initialised cli structure, non-null only on success
1233 @param dest_host The netbios name of the remote host
1234 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1235 @param port (optional) The destination port (0 for default)
1236 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
1237 @param service_type The 'type' of serivice.
1238 @param user Username, unix string
1239 @param domain User's domain
1240 @param password User's password, unencrypted unix string.
1241 @param retry BOOL. Did this connection fail with a retryable error ?
1244 NTSTATUS cli_full_connection(struct cli_state **output_cli,
1245 const char *my_name,
1246 const char *dest_host,
1247 struct in_addr *dest_ip, int port,
1248 const char *service, const char *service_type,
1249 const char *user, const char *domain,
1250 const char *password, int flags,
1253 struct ntuser_creds creds;
1255 struct nmb_name calling;
1256 struct nmb_name called;
1257 struct cli_state *cli;
1264 my_name = global_myname();
1266 if (!(cli = cli_initialise(NULL)))
1267 return NT_STATUS_NO_MEMORY;
1269 make_nmb_name(&calling, my_name, 0x0);
1270 make_nmb_name(&called , dest_host, 0x20);
1272 if (cli_set_port(cli, port) != port) {
1274 return NT_STATUS_UNSUCCESSFUL;
1277 cli_set_timeout(cli, 10000); /* 10 seconds. */
1286 DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service));
1288 if (!cli_connect(cli, dest_host, &ip)) {
1289 DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
1290 nmb_namestr(&called), inet_ntoa(ip)));
1292 return NT_STATUS_UNSUCCESSFUL;
1298 if (!cli_session_request(cli, &calling, &called)) {
1300 DEBUG(1,("session request to %s failed (%s)\n",
1301 called.name, cli_errstr(cli)));
1302 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1306 if (strcmp(called.name, "*SMBSERVER")) {
1307 make_nmb_name(&called , "*SMBSERVER", 0x20);
1310 return NT_STATUS_UNSUCCESSFUL;
1313 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1314 cli->use_spnego = False;
1315 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1316 cli->use_kerberos = True;
1318 if (!cli_negprot(cli)) {
1319 DEBUG(1,("failed negprot\n"));
1320 nt_status = NT_STATUS_UNSUCCESSFUL;
1325 if (!cli_session_setup(cli, user, password, strlen(password)+1,
1326 password, strlen(password)+1,
1328 if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
1329 && cli_session_setup(cli, "", "", 0, "", 0, domain)) {
1331 nt_status = cli_nt_error(cli);
1332 DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
1334 if (NT_STATUS_IS_OK(nt_status))
1335 nt_status = NT_STATUS_UNSUCCESSFUL;
1341 if (!cli_send_tconX(cli, service, service_type,
1342 password, strlen(password)+1)) {
1343 nt_status = cli_nt_error(cli);
1344 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1346 if (NT_STATUS_IS_OK(nt_status)) {
1347 nt_status = NT_STATUS_UNSUCCESSFUL;
1353 init_creds(&creds, user, domain, password);
1354 cli_init_creds(cli, &creds);
1357 return NT_STATUS_OK;
1360 /****************************************************************************
1361 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1362 ****************************************************************************/
1364 BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
1365 struct in_addr *pdest_ip)
1367 struct nmb_name calling, called;
1369 make_nmb_name(&calling, srchost, 0x0);
1372 * If the called name is an IP address
1373 * then use *SMBSERVER immediately.
1376 if(is_ipaddress(desthost))
1377 make_nmb_name(&called, "*SMBSERVER", 0x20);
1379 make_nmb_name(&called, desthost, 0x20);
1381 if (!cli_session_request(cli, &calling, &called)) {
1382 struct nmb_name smbservername;
1384 make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
1387 * If the name wasn't *SMBSERVER then
1388 * try with *SMBSERVER if the first name fails.
1391 if (nmb_name_equal(&called, &smbservername)) {
1394 * The name used was *SMBSERVER, don't bother with another name.
1397 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1398 with error %s.\n", desthost, cli_errstr(cli) ));
1403 * We need to close the connection here but can't call cli_shutdown as
1404 * will free an allocated cli struct. cli_close_connection was invented
1405 * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
1408 cli_close_connection(cli);
1410 if (!cli_initialise(cli) ||
1411 !cli_connect(cli, desthost, pdest_ip) ||
1412 !cli_session_request(cli, &calling, &smbservername)) {
1413 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1414 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
1426 /****************************************************************************
1427 Send an old style tcon.
1428 ****************************************************************************/
1429 NTSTATUS cli_raw_tcon(struct cli_state *cli,
1430 const char *service, const char *pass, const char *dev,
1431 uint16 *max_xmit, uint16 *tid)
1435 if (!lp_client_plaintext_auth() && (*pass)) {
1436 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1438 return NT_STATUS_ACCESS_DENIED;
1441 memset(cli->outbuf,'\0',smb_size);
1442 memset(cli->inbuf,'\0',smb_size);
1444 set_message(cli->outbuf, 0, 0, True);
1445 SCVAL(cli->outbuf,smb_com,SMBtcon);
1446 cli_setup_packet(cli);
1448 p = smb_buf(cli->outbuf);
1449 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1450 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1451 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1453 cli_setup_bcc(cli, p);
1456 if (!cli_receive_smb(cli)) {
1457 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1460 if (cli_is_error(cli)) {
1461 return cli_nt_error(cli);
1464 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
1465 *tid = SVAL(cli->inbuf, smb_vwv1);
1467 return NT_STATUS_OK;
1470 /* Return a cli_state pointing at the IPC$ share for the given server */
1472 struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
1473 struct user_auth_info *user_info)
1475 struct cli_state *cli;
1481 nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC",
1482 user_info->username, lp_workgroup(), user_info->password,
1483 CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, NULL);
1485 if (NT_STATUS_IS_OK(nt_status)) {
1487 } else if (is_ipaddress(server)) {
1488 /* windows 9* needs a correct NMB name for connections */
1489 fstring remote_name;
1491 if (name_status_find("*", 0, 0, *server_ip, remote_name)) {
1492 cli = get_ipc_connect(remote_name, server_ip, user_info);
1500 /* Return the IP address and workgroup of a master browser on the
1503 struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
1505 struct ip_service *ip_list;
1506 struct cli_state *cli;
1508 struct in_addr server_ip;
1510 /* Go looking for workgroups by broadcasting on the local network */
1512 if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
1516 for (i = 0; i < count; i++) {
1517 static fstring name;
1519 if (!name_status_find("*", 0, 0x1d, ip_list[i].ip, name))
1522 if (!find_master_ip(name, &server_ip))
1525 pstrcpy(workgroup, name);
1527 DEBUG(4, ("found master browser %s, %s\n",
1528 name, inet_ntoa(ip_list[i].ip)));
1530 cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);