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) && (lp_client_signing() == Required)) {
993 DEBUG(1,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
997 if (cli->protocol >= PROTOCOL_NT1) {
999 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1000 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
1001 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1002 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1003 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
1004 cli->serverzone *= 60;
1005 /* this time arrives in real GMT */
1006 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
1007 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1008 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1009 if (cli->capabilities & CAP_RAW_MODE) {
1010 cli->readbraw_supported = True;
1011 cli->writebraw_supported = True;
1013 /* work out if they sent us a workgroup */
1014 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1015 smb_buflen(cli->inbuf) > 8) {
1016 clistr_pull(cli, cli->server_domain,
1017 smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1018 smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1021 if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)) {
1022 /* Fail if signing is mandatory and we don't want to support it. */
1023 if (!lp_client_signing()) {
1024 DEBUG(1,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1027 cli->sign_info.negotiated_smb_signing = True;
1030 if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && cli->sign_info.allow_smb_signing)
1031 cli->sign_info.negotiated_smb_signing = True;
1033 /* Fail if signing is mandatory and the server doesn't support it. */
1034 if (cli->sign_info.mandatory_signing && !(cli->sign_info.negotiated_smb_signing)) {
1035 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1039 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1040 cli->use_spnego = False;
1041 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1042 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1043 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1044 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1045 cli->serverzone *= 60;
1046 /* this time is converted to GMT by make_unix_date */
1047 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
1048 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1049 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1050 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1052 /* the old core protocol */
1053 cli->use_spnego = False;
1055 cli->serverzone = TimeDiff(time(NULL));
1058 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1060 /* a way to force ascii SMB */
1061 if (getenv("CLI_FORCE_ASCII"))
1062 cli->capabilities &= ~CAP_UNICODE;
1067 /****************************************************************************
1068 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1069 ****************************************************************************/
1071 BOOL cli_session_request(struct cli_state *cli,
1072 struct nmb_name *calling, struct nmb_name *called)
1076 extern pstring user_socket_options;
1078 memcpy(&(cli->calling), calling, sizeof(*calling));
1079 memcpy(&(cli->called ), called , sizeof(*called ));
1081 /* put in the destination name */
1082 p = cli->outbuf+len;
1083 name_mangle(cli->called .name, p, cli->called .name_type);
1087 p = cli->outbuf+len;
1088 name_mangle(cli->calling.name, p, cli->calling.name_type);
1091 /* 445 doesn't have session request */
1092 if (cli->port == 445)
1095 /* send a session request (RFC 1002) */
1096 /* setup the packet length
1097 * Remove four bytes from the length count, since the length
1098 * field in the NBT Session Service header counts the number
1099 * of bytes which follow. The cli_send_smb() function knows
1100 * about this and accounts for those four bytes.
1104 _smb_setlen(cli->outbuf,len);
1105 SCVAL(cli->outbuf,0,0x81);
1108 DEBUG(5,("Sent session request\n"));
1110 if (!cli_receive_smb(cli))
1113 if (CVAL(cli->inbuf,0) == 0x84) {
1114 /* C. Hoch 9/14/95 Start */
1115 /* For information, here is the response structure.
1116 * We do the byte-twiddling to for portability.
1117 struct RetargetResponse{
1119 unsigned char flags;
1125 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1126 /* SESSION RETARGET */
1127 putip((char *)&cli->dest_ip,cli->inbuf+4);
1129 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
1133 DEBUG(3,("Retargeted\n"));
1135 set_socket_options(cli->fd,user_socket_options);
1142 DEBUG(0,("Retarget recursion - failing\n"));
1146 ret = cli_session_request(cli, calling, called);
1150 } /* C. Hoch 9/14/95 End */
1152 if (CVAL(cli->inbuf,0) != 0x82) {
1153 /* This is the wrong place to put the error... JRA. */
1154 cli->rap_error = CVAL(cli->inbuf,4);
1160 /****************************************************************************
1161 Open the client sockets.
1162 ****************************************************************************/
1164 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
1166 extern pstring user_socket_options;
1167 int name_type = 0x20;
1170 /* reasonable default hostname */
1171 if (!host) host = "*SMBSERVER";
1173 fstrcpy(cli->desthost, host);
1175 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1176 if ((p = strchr(cli->desthost, '#'))) {
1177 name_type = strtol(p+1, NULL, 16);
1181 if (!ip || is_zero_ip(*ip)) {
1182 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
1185 if (ip) *ip = cli->dest_ip;
1190 if (getenv("LIBSMB_PROG")) {
1191 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1193 /* try 445 first, then 139 */
1194 int port = cli->port?cli->port:445;
1195 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1196 port, cli->timeout);
1197 if (cli->fd == -1 && cli->port == 0) {
1199 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1200 port, cli->timeout);
1205 if (cli->fd == -1) {
1206 DEBUG(1,("Error connecting to %s (%s)\n",
1207 ip?inet_ntoa(*ip):host,strerror(errno)));
1211 set_socket_options(cli->fd,user_socket_options);
1216 /****************************************************************************
1217 Initialise client credentials for authenticated pipe access.
1218 ****************************************************************************/
1220 static void init_creds(struct ntuser_creds *creds, const char* username,
1221 const char* domain, const char* password)
1223 ZERO_STRUCTP(creds);
1225 pwd_set_cleartext(&creds->pwd, password);
1227 fstrcpy(creds->user_name, username);
1228 fstrcpy(creds->domain, domain);
1231 creds->pwd.null_pwd = True;
1236 establishes a connection right up to doing tconX, password specified.
1237 @param output_cli A fully initialised cli structure, non-null only on success
1238 @param dest_host The netbios name of the remote host
1239 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1240 @param port (optional) The destination port (0 for default)
1241 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
1242 @param service_type The 'type' of serivice.
1243 @param user Username, unix string
1244 @param domain User's domain
1245 @param password User's password, unencrypted unix string.
1246 @param retry BOOL. Did this connection fail with a retryable error ?
1249 NTSTATUS cli_full_connection(struct cli_state **output_cli,
1250 const char *my_name,
1251 const char *dest_host,
1252 struct in_addr *dest_ip, int port,
1253 const char *service, const char *service_type,
1254 const char *user, const char *domain,
1255 const char *password, int flags,
1258 struct ntuser_creds creds;
1260 struct nmb_name calling;
1261 struct nmb_name called;
1262 struct cli_state *cli;
1269 my_name = global_myname();
1271 if (!(cli = cli_initialise(NULL)))
1272 return NT_STATUS_NO_MEMORY;
1274 make_nmb_name(&calling, my_name, 0x0);
1275 make_nmb_name(&called , dest_host, 0x20);
1277 if (cli_set_port(cli, port) != port) {
1279 return NT_STATUS_UNSUCCESSFUL;
1282 cli_set_timeout(cli, 10000); /* 10 seconds. */
1291 DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service));
1293 if (!cli_connect(cli, dest_host, &ip)) {
1294 DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
1295 nmb_namestr(&called), inet_ntoa(ip)));
1297 return NT_STATUS_UNSUCCESSFUL;
1303 if (!cli_session_request(cli, &calling, &called)) {
1305 DEBUG(1,("session request to %s failed (%s)\n",
1306 called.name, cli_errstr(cli)));
1307 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1311 if (strcmp(called.name, "*SMBSERVER")) {
1312 make_nmb_name(&called , "*SMBSERVER", 0x20);
1315 return NT_STATUS_UNSUCCESSFUL;
1318 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1319 cli->use_spnego = False;
1320 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1321 cli->use_kerberos = True;
1323 if (!cli_negprot(cli)) {
1324 DEBUG(1,("failed negprot\n"));
1325 nt_status = NT_STATUS_UNSUCCESSFUL;
1330 if (!cli_session_setup(cli, user, password, strlen(password)+1,
1331 password, strlen(password)+1,
1333 if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
1334 && cli_session_setup(cli, "", "", 0, "", 0, domain)) {
1336 nt_status = cli_nt_error(cli);
1337 DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
1339 if (NT_STATUS_IS_OK(nt_status))
1340 nt_status = NT_STATUS_UNSUCCESSFUL;
1346 if (!cli_send_tconX(cli, service, service_type,
1347 password, strlen(password)+1)) {
1348 nt_status = cli_nt_error(cli);
1349 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1351 if (NT_STATUS_IS_OK(nt_status)) {
1352 nt_status = NT_STATUS_UNSUCCESSFUL;
1358 init_creds(&creds, user, domain, password);
1359 cli_init_creds(cli, &creds);
1362 return NT_STATUS_OK;
1365 /****************************************************************************
1366 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1367 ****************************************************************************/
1369 BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
1370 struct in_addr *pdest_ip)
1372 struct nmb_name calling, called;
1374 make_nmb_name(&calling, srchost, 0x0);
1377 * If the called name is an IP address
1378 * then use *SMBSERVER immediately.
1381 if(is_ipaddress(desthost))
1382 make_nmb_name(&called, "*SMBSERVER", 0x20);
1384 make_nmb_name(&called, desthost, 0x20);
1386 if (!cli_session_request(cli, &calling, &called)) {
1387 struct nmb_name smbservername;
1389 make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
1392 * If the name wasn't *SMBSERVER then
1393 * try with *SMBSERVER if the first name fails.
1396 if (nmb_name_equal(&called, &smbservername)) {
1399 * The name used was *SMBSERVER, don't bother with another name.
1402 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1403 with error %s.\n", desthost, cli_errstr(cli) ));
1408 * We need to close the connection here but can't call cli_shutdown as
1409 * will free an allocated cli struct. cli_close_connection was invented
1410 * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
1413 cli_close_connection(cli);
1415 if (!cli_initialise(cli) ||
1416 !cli_connect(cli, desthost, pdest_ip) ||
1417 !cli_session_request(cli, &calling, &smbservername)) {
1418 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1419 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
1431 /****************************************************************************
1432 Send an old style tcon.
1433 ****************************************************************************/
1434 NTSTATUS cli_raw_tcon(struct cli_state *cli,
1435 const char *service, const char *pass, const char *dev,
1436 uint16 *max_xmit, uint16 *tid)
1440 if (!lp_client_plaintext_auth() && (*pass)) {
1441 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
1443 return NT_STATUS_ACCESS_DENIED;
1446 memset(cli->outbuf,'\0',smb_size);
1447 memset(cli->inbuf,'\0',smb_size);
1449 set_message(cli->outbuf, 0, 0, True);
1450 SCVAL(cli->outbuf,smb_com,SMBtcon);
1451 cli_setup_packet(cli);
1453 p = smb_buf(cli->outbuf);
1454 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
1455 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
1456 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
1458 cli_setup_bcc(cli, p);
1461 if (!cli_receive_smb(cli)) {
1462 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1465 if (cli_is_error(cli)) {
1466 return cli_nt_error(cli);
1469 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
1470 *tid = SVAL(cli->inbuf, smb_vwv1);
1472 return NT_STATUS_OK;
1475 /* Return a cli_state pointing at the IPC$ share for the given server */
1477 struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
1478 struct user_auth_info *user_info)
1480 struct cli_state *cli;
1486 nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC",
1487 user_info->username, lp_workgroup(), user_info->password,
1488 CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, NULL);
1490 if (NT_STATUS_IS_OK(nt_status)) {
1492 } else if (is_ipaddress(server)) {
1493 /* windows 9* needs a correct NMB name for connections */
1494 fstring remote_name;
1496 if (name_status_find("*", 0, 0, *server_ip, remote_name)) {
1497 cli = get_ipc_connect(remote_name, server_ip, user_info);
1505 /* Return the IP address and workgroup of a master browser on the
1508 struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
1510 struct ip_service *ip_list;
1511 struct cli_state *cli;
1513 struct in_addr server_ip;
1515 /* Go looking for workgroups by broadcasting on the local network */
1517 if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
1521 for (i = 0; i < count; i++) {
1522 static fstring name;
1524 if (!name_status_find("*", 0, 0x1d, ip_list[i].ip, name))
1527 if (!find_master_ip(name, &server_ip))
1530 pstrcpy(workgroup, name);
1532 DEBUG(4, ("found master browser %s, %s\n",
1533 name, inet_ntoa(ip_list[i].ip)));
1535 cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);