root/source3/libsmb/cliconnect.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cli_set_session_key
  2. cli_session_setup_lanman2
  3. cli_session_setup_capabilities
  4. cli_session_setup_guest_send
  5. cli_session_setup_guest_recv
  6. cli_session_setup_guest
  7. cli_session_setup_plaintext
  8. cli_session_setup_nt1
  9. cli_session_setup_blob_send
  10. cli_session_setup_blob_receive
  11. cli_session_setup_blob
  12. use_in_memory_ccache
  13. cli_session_setup_kerberos
  14. cli_session_setup_ntlmssp
  15. cli_session_setup_spnego
  16. cli_session_setup
  17. cli_ulogoff
  18. cli_tcon_andx_send
  19. cli_tcon_andx_recv
  20. cli_tcon_andx
  21. cli_tdis
  22. cli_negprot_sendsync
  23. cli_negprot_send
  24. cli_negprot_recv
  25. cli_negprot
  26. cli_session_request
  27. smb_sock_connected
  28. open_smb_socket
  29. cli_connect
  30. cli_start_connection
  31. cli_full_connection
  32. attempt_netbios_session_request
  33. cli_raw_tcon
  34. get_ipc_connect
  35. get_ipc_connect_master_ip
  36. get_ipc_connect_master_ip_bcast

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    client connect/disconnect routines
   4    Copyright (C) Andrew Tridgell 1994-1998
   5    Copyright (C) Andrew Bartlett 2001-2003
   6    
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11    
  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.
  16    
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 #include "includes.h"
  22 
  23 static const struct {
  24         int prot;
  25         const char name[24];
  26 } prots[10] = {
  27         {PROTOCOL_CORE,         "PC NETWORK PROGRAM 1.0"},
  28         {PROTOCOL_COREPLUS,     "MICROSOFT NETWORKS 1.03"},
  29         {PROTOCOL_LANMAN1,      "MICROSOFT NETWORKS 3.0"},
  30         {PROTOCOL_LANMAN1,      "LANMAN1.0"},
  31         {PROTOCOL_LANMAN2,      "LM1.2X002"},
  32         {PROTOCOL_LANMAN2,      "DOS LANMAN2.1"},
  33         {PROTOCOL_LANMAN2,      "LANMAN2.1"},
  34         {PROTOCOL_LANMAN2,      "Samba"},
  35         {PROTOCOL_NT1,          "NT LANMAN 1.0"},
  36         {PROTOCOL_NT1,          "NT LM 0.12"},
  37 };
  38 
  39 #define STAR_SMBSERVER "*SMBSERVER"
  40 
  41 /**
  42  * Set the user session key for a connection
  43  * @param cli The cli structure to add it too
  44  * @param session_key The session key used.  (A copy of this is taken for the cli struct)
  45  *
  46  */
  47 
  48 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key) 
     /* [<][>][^][v][top][bottom][index][help] */
  49 {
  50         cli->user_session_key = data_blob(session_key.data, session_key.length);
  51 }
  52 
  53 /****************************************************************************
  54  Do an old lanman2 style session setup.
  55 ****************************************************************************/
  56 
  57 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
  58                                           const char *user, 
  59                                           const char *pass, size_t passlen,
  60                                           const char *workgroup)
  61 {
  62         DATA_BLOB session_key = data_blob_null;
  63         DATA_BLOB lm_response = data_blob_null;
  64         NTSTATUS status;
  65         fstring pword;
  66         char *p;
  67 
  68         if (passlen > sizeof(pword)-1) {
  69                 return NT_STATUS_INVALID_PARAMETER;
  70         }
  71 
  72         /* LANMAN servers predate NT status codes and Unicode and ignore those 
  73            smb flags so we must disable the corresponding default capabilities  
  74            that would otherwise cause the Unicode and NT Status flags to be
  75            set (and even returned by the server) */
  76 
  77         cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
  78 
  79         /* if in share level security then don't send a password now */
  80         if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
  81                 passlen = 0;
  82 
  83         if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
  84                 /* Encrypted mode needed, and non encrypted password supplied. */
  85                 lm_response = data_blob(NULL, 24);
  86                 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
  87                         DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
  88                         return NT_STATUS_ACCESS_DENIED;
  89                 }
  90         } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
  91                 /* Encrypted mode needed, and encrypted password supplied. */
  92                 lm_response = data_blob(pass, passlen);
  93         } else if (passlen > 0) {
  94                 /* Plaintext mode needed, assume plaintext supplied. */
  95                 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
  96                 lm_response = data_blob(pass, passlen);
  97         }
  98 
  99         /* send a session setup command */
 100         memset(cli->outbuf,'\0',smb_size);
 101         cli_set_message(cli->outbuf,10, 0, True);
 102         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
 103         cli_setup_packet(cli);
 104         
 105         SCVAL(cli->outbuf,smb_vwv0,0xFF);
 106         SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
 107         SSVAL(cli->outbuf,smb_vwv3,2);
 108         SSVAL(cli->outbuf,smb_vwv4,1);
 109         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
 110         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
 111 
 112         p = smb_buf(cli->outbuf);
 113         memcpy(p,lm_response.data,lm_response.length);
 114         p += lm_response.length;
 115         p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
 116         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
 117         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
 118         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
 119         cli_setup_bcc(cli, p);
 120 
 121         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
 122                 return cli_nt_error(cli);
 123         }
 124 
 125         show_msg(cli->inbuf);
 126 
 127         if (cli_is_error(cli)) {
 128                 return cli_nt_error(cli);
 129         }
 130         
 131         /* use the returned vuid from now on */
 132         cli->vuid = SVAL(cli->inbuf,smb_uid);   
 133         status = cli_set_username(cli, user);
 134         if (!NT_STATUS_IS_OK(status)) {
 135                 return status;
 136         }
 137 
 138         if (session_key.data) {
 139                 /* Have plaintext orginal */
 140                 cli_set_session_key(cli, session_key);
 141         }
 142 
 143         return NT_STATUS_OK;
 144 }
 145 
 146 /****************************************************************************
 147  Work out suitable capabilities to offer the server.
 148 ****************************************************************************/
 149 
 150 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
 151 {
 152         uint32 capabilities = CAP_NT_SMBS;
 153 
 154         if (!cli->force_dos_errors)
 155                 capabilities |= CAP_STATUS32;
 156 
 157         if (cli->use_level_II_oplocks)
 158                 capabilities |= CAP_LEVEL_II_OPLOCKS;
 159 
 160         capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
 161         return capabilities;
 162 }
 163 
 164 /****************************************************************************
 165  Do a NT1 guest session setup.
 166 ****************************************************************************/
 167 
 168 struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 169                                                struct event_context *ev,
 170                                                struct cli_state *cli)
 171 {
 172         struct async_req *result;
 173         uint16_t vwv[13];
 174         uint8_t *bytes;
 175 
 176         SCVAL(vwv+0, 0, 0xFF);
 177         SCVAL(vwv+0, 1, 0);
 178         SSVAL(vwv+1, 0, 0);
 179         SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
 180         SSVAL(vwv+3, 0, 2);
 181         SSVAL(vwv+4, 0, cli->pid);
 182         SIVAL(vwv+5, 0, cli->sesskey);
 183         SSVAL(vwv+7, 0, 0);
 184         SSVAL(vwv+8, 0, 0);
 185         SSVAL(vwv+9, 0, 0);
 186         SSVAL(vwv+10, 0, 0);
 187         SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
 188 
 189         bytes = talloc_array(talloc_tos(), uint8_t, 0);
 190 
 191         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "",  1, /* username */
 192                                    NULL);
 193         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
 194                                    NULL);
 195         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
 196         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
 197 
 198         if (bytes == NULL) {
 199                 return NULL;
 200         }
 201 
 202         result = cli_request_send(mem_ctx, ev, cli, SMBsesssetupX, 0,
 203                                   13, vwv, 0, talloc_get_size(bytes), bytes);
 204         TALLOC_FREE(bytes);
 205         return result;
 206 }
 207 
 208 NTSTATUS cli_session_setup_guest_recv(struct async_req *req)
     /* [<][>][^][v][top][bottom][index][help] */
 209 {
 210         struct cli_request *cli_req = talloc_get_type_abort(
 211                 req->private_data, struct cli_request);
 212         struct cli_state *cli = cli_req->cli;
 213         uint8_t wct;
 214         uint16_t *vwv;
 215         uint16_t num_bytes;
 216         uint8_t *bytes;
 217         uint8_t *p;
 218         NTSTATUS status;
 219 
 220         if (async_req_is_nterror(req, &status)) {
 221                 return status;
 222         }
 223 
 224         status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
 225         if (!NT_STATUS_IS_OK(status)) {
 226                 return status;
 227         }
 228 
 229         p = bytes;
 230 
 231         cli->vuid = SVAL(cli_req->inbuf, smb_uid);
 232 
 233         p += clistr_pull(cli_req->inbuf, cli->server_os, (char *)p,
 234                          sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
 235         p += clistr_pull(cli_req->inbuf, cli->server_type, (char *)p,
 236                          sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
 237         p += clistr_pull(cli_req->inbuf, cli->server_domain, (char *)p,
 238                          sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
 239 
 240         if (strstr(cli->server_type, "Samba")) {
 241                 cli->is_samba = True;
 242         }
 243 
 244         status = cli_set_username(cli, "");
 245         if (!NT_STATUS_IS_OK(status)) {
 246                 return status;
 247         }
 248 
 249         return NT_STATUS_OK;
 250 }
 251 
 252 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
 253 {
 254         TALLOC_CTX *frame = talloc_stackframe();
 255         struct event_context *ev;
 256         struct async_req *req;
 257         NTSTATUS status;
 258 
 259         if (cli->fd_event != NULL) {
 260                 /*
 261                  * Can't use sync call while an async call is in flight
 262                  */
 263                 status = NT_STATUS_INVALID_PARAMETER;
 264                 goto fail;
 265         }
 266 
 267         ev = event_context_init(frame);
 268         if (ev == NULL) {
 269                 status = NT_STATUS_NO_MEMORY;
 270                 goto fail;
 271         }
 272 
 273         req = cli_session_setup_guest_send(frame, ev, cli);
 274         if (req == NULL) {
 275                 status = NT_STATUS_NO_MEMORY;
 276                 goto fail;
 277         }
 278 
 279         while (req->state < ASYNC_REQ_DONE) {
 280                 event_loop_once(ev);
 281         }
 282 
 283         status = cli_session_setup_guest_recv(req);
 284  fail:
 285         TALLOC_FREE(frame);
 286         return status;
 287 }
 288 
 289 /****************************************************************************
 290  Do a NT1 plaintext session setup.
 291 ****************************************************************************/
 292 
 293 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
 294                                             const char *user, const char *pass,
 295                                             const char *workgroup)
 296 {
 297         uint32 capabilities = cli_session_setup_capabilities(cli);
 298         char *p;
 299         NTSTATUS status;
 300         fstring lanman;
 301         
 302         fstr_sprintf( lanman, "Samba %s", samba_version_string());
 303 
 304         memset(cli->outbuf, '\0', smb_size);
 305         cli_set_message(cli->outbuf,13,0,True);
 306         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
 307         cli_setup_packet(cli);
 308                         
 309         SCVAL(cli->outbuf,smb_vwv0,0xFF);
 310         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
 311         SSVAL(cli->outbuf,smb_vwv3,2);
 312         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
 313         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
 314         SSVAL(cli->outbuf,smb_vwv8,0);
 315         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
 316         p = smb_buf(cli->outbuf);
 317         
 318         /* check wether to send the ASCII or UNICODE version of the password */
 319         
 320         if ( (capabilities & CAP_UNICODE) == 0 ) {
 321                 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
 322                 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
 323         }
 324         else {
 325                 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
 326                  * the space taken by the unicode password to be one byte too
 327                  * long (as we're on an odd byte boundary here). Reduce the
 328                  * count by 1 to cope with this. Fixes smbclient against NetApp
 329                  * servers which can't cope. Fix from
 330                  * bryan.kolodziej@allenlund.com in bug #3840.
 331                  */
 332                 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
 333                 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);        
 334         }
 335         
 336         p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
 337         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
 338         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
 339         p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
 340         cli_setup_bcc(cli, p);
 341 
 342         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
 343                 return cli_nt_error(cli);
 344         }
 345         
 346         show_msg(cli->inbuf);
 347         
 348         if (cli_is_error(cli)) {
 349                 return cli_nt_error(cli);
 350         }
 351 
 352         cli->vuid = SVAL(cli->inbuf,smb_uid);
 353         p = smb_buf(cli->inbuf);
 354         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
 355                          -1, STR_TERMINATE);
 356         p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
 357                          -1, STR_TERMINATE);
 358         p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
 359                          -1, STR_TERMINATE);
 360         status = cli_set_username(cli, user);
 361         if (!NT_STATUS_IS_OK(status)) {
 362                 return status;
 363         }
 364         if (strstr(cli->server_type, "Samba")) {
 365                 cli->is_samba = True;
 366         }
 367 
 368         return NT_STATUS_OK;
 369 }
 370 
 371 /****************************************************************************
 372    do a NT1 NTLM/LM encrypted session setup - for when extended security
 373    is not negotiated.
 374    @param cli client state to create do session setup on
 375    @param user username
 376    @param pass *either* cleartext password (passlen !=24) or LM response.
 377    @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
 378    @param workgroup The user's domain.
 379 ****************************************************************************/
 380 
 381 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user, 
     /* [<][>][^][v][top][bottom][index][help] */
 382                                       const char *pass, size_t passlen,
 383                                       const char *ntpass, size_t ntpasslen,
 384                                       const char *workgroup)
 385 {
 386         uint32 capabilities = cli_session_setup_capabilities(cli);
 387         DATA_BLOB lm_response = data_blob_null;
 388         DATA_BLOB nt_response = data_blob_null;
 389         DATA_BLOB session_key = data_blob_null;
 390         NTSTATUS result;
 391         char *p;
 392         bool ok;
 393 
 394         if (passlen == 0) {
 395                 /* do nothing - guest login */
 396         } else if (passlen != 24) {
 397                 if (lp_client_ntlmv2_auth()) {
 398                         DATA_BLOB server_chal;
 399                         DATA_BLOB names_blob;
 400                         server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); 
 401 
 402                         /* note that the 'workgroup' here is a best guess - we don't know
 403                            the server's domain at this point.  The 'server name' is also
 404                            dodgy... 
 405                         */
 406                         names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
 407 
 408                         if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal, 
 409                                               &names_blob,
 410                                               &lm_response, &nt_response, &session_key)) {
 411                                 data_blob_free(&names_blob);
 412                                 data_blob_free(&server_chal);
 413                                 return NT_STATUS_ACCESS_DENIED;
 414                         }
 415                         data_blob_free(&names_blob);
 416                         data_blob_free(&server_chal);
 417 
 418                 } else {
 419                         uchar nt_hash[16];
 420                         E_md4hash(pass, nt_hash);
 421 
 422 #ifdef LANMAN_ONLY
 423                         nt_response = data_blob_null;
 424 #else
 425                         nt_response = data_blob(NULL, 24);
 426                         SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
 427 #endif
 428                         /* non encrypted password supplied. Ignore ntpass. */
 429                         if (lp_client_lanman_auth()) {
 430                                 lm_response = data_blob(NULL, 24);
 431                                 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
 432                                         /* Oops, the LM response is invalid, just put 
 433                                            the NT response there instead */
 434                                         data_blob_free(&lm_response);
 435                                         lm_response = data_blob(nt_response.data, nt_response.length);
 436                                 }
 437                         } else {
 438                                 /* LM disabled, place NT# in LM field instead */
 439                                 lm_response = data_blob(nt_response.data, nt_response.length);
 440                         }
 441 
 442                         session_key = data_blob(NULL, 16);
 443 #ifdef LANMAN_ONLY
 444                         E_deshash(pass, session_key.data);
 445                         memset(&session_key.data[8], '\0', 8);
 446 #else
 447                         SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
 448 #endif
 449                 }
 450                 cli_temp_set_signing(cli);
 451         } else {
 452                 /* pre-encrypted password supplied.  Only used for 
 453                    security=server, can't do
 454                    signing because we don't have original key */
 455 
 456                 lm_response = data_blob(pass, passlen);
 457                 nt_response = data_blob(ntpass, ntpasslen);
 458         }
 459 
 460         /* send a session setup command */
 461         memset(cli->outbuf,'\0',smb_size);
 462 
 463         cli_set_message(cli->outbuf,13,0,True);
 464         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
 465         cli_setup_packet(cli);
 466                         
 467         SCVAL(cli->outbuf,smb_vwv0,0xFF);
 468         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
 469         SSVAL(cli->outbuf,smb_vwv3,2);
 470         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
 471         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
 472         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
 473         SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
 474         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
 475         p = smb_buf(cli->outbuf);
 476         if (lm_response.length) {
 477                 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
 478         }
 479         if (nt_response.length) {
 480                 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
 481         }
 482         p += clistr_push(cli, p, user, -1, STR_TERMINATE);
 483 
 484         /* Upper case here might help some NTLMv2 implementations */
 485         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
 486         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
 487         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
 488         cli_setup_bcc(cli, p);
 489 
 490         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
 491                 result = cli_nt_error(cli);
 492                 goto end;
 493         }
 494 
 495         /* show_msg(cli->inbuf); */
 496 
 497         if (cli_is_error(cli)) {
 498                 result = cli_nt_error(cli);
 499                 goto end;
 500         }
 501 
 502 #ifdef LANMAN_ONLY
 503         ok = cli_simple_set_signing(cli, session_key, lm_response);
 504 #else
 505         ok = cli_simple_set_signing(cli, session_key, nt_response);
 506 #endif
 507         if (ok) {
 508                 /* 'resign' the last message, so we get the right sequence numbers
 509                    for checking the first reply from the server */
 510                 cli_calculate_sign_mac(cli, cli->outbuf);
 511 
 512                 if (!cli_check_sign_mac(cli, cli->inbuf)) {
 513                         result = NT_STATUS_ACCESS_DENIED;
 514                         goto end;
 515                 }
 516         }
 517 
 518         /* use the returned vuid from now on */
 519         cli->vuid = SVAL(cli->inbuf,smb_uid);
 520         
 521         p = smb_buf(cli->inbuf);
 522         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
 523                          -1, STR_TERMINATE);
 524         p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
 525                          -1, STR_TERMINATE);
 526         p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
 527                          -1, STR_TERMINATE);
 528 
 529         if (strstr(cli->server_type, "Samba")) {
 530                 cli->is_samba = True;
 531         }
 532 
 533         result = cli_set_username(cli, user);
 534         if (!NT_STATUS_IS_OK(result)) {
 535                 goto end;
 536         }
 537 
 538         if (session_key.data) {
 539                 /* Have plaintext orginal */
 540                 cli_set_session_key(cli, session_key);
 541         }
 542 
 543         result = NT_STATUS_OK;
 544 end:    
 545         data_blob_free(&lm_response);
 546         data_blob_free(&nt_response);
 547         data_blob_free(&session_key);
 548         return result;
 549 }
 550 
 551 /****************************************************************************
 552  Send a extended security session setup blob
 553 ****************************************************************************/
 554 
 555 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
     /* [<][>][^][v][top][bottom][index][help] */
 556 {
 557         uint32 capabilities = cli_session_setup_capabilities(cli);
 558         char *p;
 559 
 560         capabilities |= CAP_EXTENDED_SECURITY;
 561 
 562         /* send a session setup command */
 563         memset(cli->outbuf,'\0',smb_size);
 564 
 565         cli_set_message(cli->outbuf,12,0,True);
 566         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
 567 
 568         cli_setup_packet(cli);
 569 
 570         SCVAL(cli->outbuf,smb_vwv0,0xFF);
 571         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
 572         SSVAL(cli->outbuf,smb_vwv3,2);
 573         SSVAL(cli->outbuf,smb_vwv4,1);
 574         SIVAL(cli->outbuf,smb_vwv5,0);
 575         SSVAL(cli->outbuf,smb_vwv7,blob.length);
 576         SIVAL(cli->outbuf,smb_vwv10,capabilities); 
 577         p = smb_buf(cli->outbuf);
 578         memcpy(p, blob.data, blob.length);
 579         p += blob.length;
 580         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
 581         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
 582         cli_setup_bcc(cli, p);
 583         return cli_send_smb(cli);
 584 }
 585 
 586 /****************************************************************************
 587  Send a extended security session setup blob, returning a reply blob.
 588 ****************************************************************************/
 589 
 590 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
 591 {
 592         DATA_BLOB blob2 = data_blob_null;
 593         char *p;
 594         size_t len;
 595 
 596         if (!cli_receive_smb(cli))
 597                 return blob2;
 598 
 599         show_msg(cli->inbuf);
 600 
 601         if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
 602                                                   NT_STATUS_MORE_PROCESSING_REQUIRED)) {
 603                 return blob2;
 604         }
 605 
 606         /* use the returned vuid from now on */
 607         cli->vuid = SVAL(cli->inbuf,smb_uid);
 608 
 609         p = smb_buf(cli->inbuf);
 610 
 611         blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
 612 
 613         p += blob2.length;
 614         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
 615                          -1, STR_TERMINATE);
 616 
 617         /* w2k with kerberos doesn't properly null terminate this field */
 618         len = smb_bufrem(cli->inbuf, p);
 619         if (p + len < cli->inbuf + cli->bufsize+SAFETY_MARGIN - 2) {
 620                 char *end_of_buf = p + len;
 621 
 622                 SSVAL(p, len, 0);
 623                 /* Now it's null terminated. */
 624                 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
 625                         -1, STR_TERMINATE);
 626                 /*
 627                  * See if there's another string. If so it's the
 628                  * server domain (part of the 'standard' Samba
 629                  * server signature).
 630                  */
 631                 if (p < end_of_buf) {
 632                         p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
 633                                 -1, STR_TERMINATE);
 634                 }
 635         } else {
 636                 /*
 637                  * No room to null terminate so we can't see if there
 638                  * is another string (server_domain) afterwards.
 639                  */
 640                 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
 641                                  len, 0);
 642         }
 643         return blob2;
 644 }
 645 
 646 #ifdef HAVE_KRB5
 647 /****************************************************************************
 648  Send a extended security session setup blob, returning a reply blob.
 649 ****************************************************************************/
 650 
 651 /* The following is calculated from :
 652  * (smb_size-4) = 35
 653  * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
 654  * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
 655  * end of packet.
 656  */
 657 
 658 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
 659 
 660 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
     /* [<][>][^][v][top][bottom][index][help] */
 661 {
 662         int32 remaining = blob.length;
 663         int32 cur = 0;
 664         DATA_BLOB send_blob = data_blob_null;
 665         int32 max_blob_size = 0;
 666         DATA_BLOB receive_blob = data_blob_null;
 667 
 668         if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
 669                 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
 670                         "(was %u, need minimum %u)\n",
 671                         (unsigned int)cli->max_xmit,
 672                         BASE_SESSSETUP_BLOB_PACKET_SIZE));
 673                 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
 674                 return False;
 675         }
 676 
 677         max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
 678 
 679         while ( remaining > 0) {
 680                 if (remaining >= max_blob_size) {
 681                         send_blob.length = max_blob_size;
 682                         remaining -= max_blob_size;
 683                 } else {
 684                         send_blob.length = remaining; 
 685                         remaining = 0;
 686                 }
 687 
 688                 send_blob.data =  &blob.data[cur];
 689                 cur += send_blob.length;
 690 
 691                 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n", 
 692                         (unsigned int)remaining,
 693                         (unsigned int)send_blob.length,
 694                         (unsigned int)cur ));
 695 
 696                 if (!cli_session_setup_blob_send(cli, send_blob)) {
 697                         DEBUG(0, ("cli_session_setup_blob: send failed\n"));
 698                         return False;
 699                 }
 700 
 701                 receive_blob = cli_session_setup_blob_receive(cli);
 702                 data_blob_free(&receive_blob);
 703 
 704                 if (cli_is_error(cli) &&
 705                                 !NT_STATUS_EQUAL( cli_get_nt_error(cli), 
 706                                         NT_STATUS_MORE_PROCESSING_REQUIRED)) {
 707                         DEBUG(0, ("cli_session_setup_blob: receive failed "
 708                                   "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
 709                         cli->vuid = 0;
 710                         return False;
 711                 }
 712         }
 713 
 714         return True;
 715 }
 716 
 717 /****************************************************************************
 718  Use in-memory credentials cache
 719 ****************************************************************************/
 720 
 721 static void use_in_memory_ccache(void) {
     /* [<][>][^][v][top][bottom][index][help] */
 722         setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
 723 }
 724 
 725 /****************************************************************************
 726  Do a spnego/kerberos encrypted session setup.
 727 ****************************************************************************/
 728 
 729 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
     /* [<][>][^][v][top][bottom][index][help] */
 730 {
 731         DATA_BLOB negTokenTarg;
 732         DATA_BLOB session_key_krb5;
 733         NTSTATUS nt_status;
 734         int rc;
 735 
 736         cli_temp_set_signing(cli);
 737 
 738         DEBUG(2,("Doing kerberos session setup\n"));
 739 
 740         /* generate the encapsulated kerberos5 ticket */
 741         rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
 742 
 743         if (rc) {
 744                 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
 745                         error_message(rc)));
 746                 return ADS_ERROR_KRB5(rc);
 747         }
 748 
 749 #if 0
 750         file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
 751 #endif
 752 
 753         if (!cli_session_setup_blob(cli, negTokenTarg)) {
 754                 nt_status = cli_nt_error(cli);
 755                 goto nt_error;
 756         }
 757 
 758         if (cli_is_error(cli)) {
 759                 nt_status = cli_nt_error(cli);
 760                 if (NT_STATUS_IS_OK(nt_status)) {
 761                         nt_status = NT_STATUS_UNSUCCESSFUL;
 762                 }
 763                 goto nt_error;
 764         }
 765 
 766         cli_set_session_key(cli, session_key_krb5);
 767 
 768         if (cli_simple_set_signing(
 769                     cli, session_key_krb5, data_blob_null)) {
 770 
 771                 /* 'resign' the last message, so we get the right sequence numbers
 772                    for checking the first reply from the server */
 773                 cli_calculate_sign_mac(cli, cli->outbuf);
 774 
 775                 if (!cli_check_sign_mac(cli, cli->inbuf)) {
 776                         nt_status = NT_STATUS_ACCESS_DENIED;
 777                         goto nt_error;
 778                 }
 779         }
 780 
 781         data_blob_free(&negTokenTarg);
 782         data_blob_free(&session_key_krb5);
 783 
 784         return ADS_ERROR_NT(NT_STATUS_OK);
 785 
 786 nt_error:
 787         data_blob_free(&negTokenTarg);
 788         data_blob_free(&session_key_krb5);
 789         cli->vuid = 0;
 790         return ADS_ERROR_NT(nt_status);
 791 }
 792 #endif  /* HAVE_KRB5 */
 793 
 794 
 795 /****************************************************************************
 796  Do a spnego/NTLMSSP encrypted session setup.
 797 ****************************************************************************/
 798 
 799 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, 
     /* [<][>][^][v][top][bottom][index][help] */
 800                                           const char *pass, const char *domain)
 801 {
 802         struct ntlmssp_state *ntlmssp_state;
 803         NTSTATUS nt_status;
 804         int turn = 1;
 805         DATA_BLOB msg1;
 806         DATA_BLOB blob = data_blob_null;
 807         DATA_BLOB blob_in = data_blob_null;
 808         DATA_BLOB blob_out = data_blob_null;
 809 
 810         cli_temp_set_signing(cli);
 811 
 812         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
 813                 return nt_status;
 814         }
 815         ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
 816 
 817         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
 818                 return nt_status;
 819         }
 820         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
 821                 return nt_status;
 822         }
 823         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
 824                 return nt_status;
 825         }
 826 
 827         do {
 828                 nt_status = ntlmssp_update(ntlmssp_state, 
 829                                                   blob_in, &blob_out);
 830                 data_blob_free(&blob_in);
 831                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
 832                         if (turn == 1) {
 833                                 /* and wrap it in a SPNEGO wrapper */
 834                                 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
 835                         } else {
 836                                 /* wrap it in SPNEGO */
 837                                 msg1 = spnego_gen_auth(blob_out);
 838                         }
 839 
 840                         /* now send that blob on its way */
 841                         if (!cli_session_setup_blob_send(cli, msg1)) {
 842                                 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
 843                                 nt_status = NT_STATUS_UNSUCCESSFUL;
 844                         } else {
 845                                 blob = cli_session_setup_blob_receive(cli);
 846 
 847                                 nt_status = cli_nt_error(cli);
 848                                 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
 849                                         if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
 850                                                 nt_status = NT_STATUS_ACCESS_DENIED;
 851                                         } else {
 852                                                 nt_status = NT_STATUS_UNSUCCESSFUL;
 853                                         }
 854                                 }
 855                         }
 856                         data_blob_free(&msg1);
 857                 }
 858 
 859                 if (!blob.length) {
 860                         if (NT_STATUS_IS_OK(nt_status)) {
 861                                 nt_status = NT_STATUS_UNSUCCESSFUL;
 862                         }
 863                 } else if ((turn == 1) && 
 864                            NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
 865                         DATA_BLOB tmp_blob = data_blob_null;
 866                         /* the server might give us back two challenges */
 867                         if (!spnego_parse_challenge(blob, &blob_in, 
 868                                                     &tmp_blob)) {
 869                                 DEBUG(3,("Failed to parse challenges\n"));
 870                                 nt_status = NT_STATUS_INVALID_PARAMETER;
 871                         }
 872                         data_blob_free(&tmp_blob);
 873                 } else {
 874                         if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP, 
 875                                                         &blob_in)) {
 876                                 DEBUG(3,("Failed to parse auth response\n"));
 877                                 if (NT_STATUS_IS_OK(nt_status) 
 878                                     || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) 
 879                                         nt_status = NT_STATUS_INVALID_PARAMETER;
 880                         }
 881                 }
 882                 data_blob_free(&blob);
 883                 data_blob_free(&blob_out);
 884                 turn++;
 885         } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
 886 
 887         data_blob_free(&blob_in);
 888 
 889         if (NT_STATUS_IS_OK(nt_status)) {
 890 
 891                 if (cli->server_domain[0] == '\0') {
 892                         fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
 893                 }
 894                 cli_set_session_key(cli, ntlmssp_state->session_key);
 895 
 896                 if (cli_simple_set_signing(
 897                             cli, ntlmssp_state->session_key, data_blob_null)) {
 898 
 899                         /* 'resign' the last message, so we get the right sequence numbers
 900                            for checking the first reply from the server */
 901                         cli_calculate_sign_mac(cli, cli->outbuf);
 902 
 903                         if (!cli_check_sign_mac(cli, cli->inbuf)) {
 904                                 nt_status = NT_STATUS_ACCESS_DENIED;
 905                         }
 906                 }
 907         }
 908 
 909         /* we have a reference conter on ntlmssp_state, if we are signing
 910            then the state will be kept by the signing engine */
 911 
 912         ntlmssp_end(&ntlmssp_state);
 913 
 914         if (!NT_STATUS_IS_OK(nt_status)) {
 915                 cli->vuid = 0;
 916         }
 917         return nt_status;
 918 }
 919 
 920 /****************************************************************************
 921  Do a spnego encrypted session setup.
 922 
 923  user_domain: The shortname of the domain the user/machine is a member of.
 924  dest_realm: The realm we're connecting to, if NULL we use our default realm.
 925 ****************************************************************************/
 926 
 927 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
     /* [<][>][^][v][top][bottom][index][help] */
 928                               const char *pass, const char *user_domain,
 929                               const char * dest_realm)
 930 {
 931         char *principal = NULL;
 932         char *OIDs[ASN1_MAX_OIDS];
 933         int i;
 934         DATA_BLOB blob;
 935         const char *p = NULL;
 936         char *account = NULL;
 937         NTSTATUS status;
 938 
 939         DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
 940 
 941         /* the server might not even do spnego */
 942         if (cli->secblob.length <= 16) {
 943                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
 944                 goto ntlmssp;
 945         }
 946 
 947 #if 0
 948         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
 949 #endif
 950 
 951         /* there is 16 bytes of GUID before the real spnego packet starts */
 952         blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
 953 
 954         /* The server sent us the first part of the SPNEGO exchange in the
 955          * negprot reply. It is WRONG to depend on the principal sent in the
 956          * negprot reply, but right now we do it. If we don't receive one,
 957          * we try to best guess, then fall back to NTLM.  */
 958         if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
 959                 data_blob_free(&blob);
 960                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
 961         }
 962         data_blob_free(&blob);
 963 
 964         /* make sure the server understands kerberos */
 965         for (i=0;OIDs[i];i++) {
 966                 DEBUG(3,("got OID=%s\n", OIDs[i]));
 967                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
 968                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
 969                         cli->got_kerberos_mechanism = True;
 970                 }
 971                 talloc_free(OIDs[i]);
 972         }
 973 
 974         DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
 975 
 976         status = cli_set_username(cli, user);
 977         if (!NT_STATUS_IS_OK(status)) {
 978                 return ADS_ERROR_NT(status);
 979         }
 980 
 981 #ifdef HAVE_KRB5
 982         /* If password is set we reauthenticate to kerberos server
 983          * and do not store results */
 984 
 985         if (cli->got_kerberos_mechanism && cli->use_kerberos) {
 986                 ADS_STATUS rc;
 987 
 988                 if (pass && *pass) {
 989                         int ret;
 990 
 991                         use_in_memory_ccache();
 992                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
 993 
 994                         if (ret){
 995                                 TALLOC_FREE(principal);
 996                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
 997                                 if (cli->fallback_after_kerberos)
 998                                         goto ntlmssp;
 999                                 return ADS_ERROR_KRB5(ret);
1000                         }
1001                 }
1002 
1003                 /* If we get a bad principal, try to guess it if
1004                    we have a valid host NetBIOS name.
1005                  */
1006                 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1007                         TALLOC_FREE(principal);
1008                 }
1009 
1010                 if (principal == NULL &&
1011                         !is_ipaddress(cli->desthost) &&
1012                         !strequal(STAR_SMBSERVER,
1013                                 cli->desthost)) {
1014                         char *realm = NULL;
1015                         char *machine = NULL;
1016                         char *host = NULL;
1017                         DEBUG(3,("cli_session_setup_spnego: got a "
1018                                 "bad server principal, trying to guess ...\n"));
1019 
1020                         host = strchr_m(cli->desthost, '.');
1021                         if (host) {
1022                                 machine = SMB_STRNDUP(cli->desthost,
1023                                         host - cli->desthost);
1024                         } else {
1025                                 machine = SMB_STRDUP(cli->desthost);
1026                         }
1027                         if (machine == NULL) {
1028                                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1029                         }
1030 
1031                         if (dest_realm) {
1032                                 realm = SMB_STRDUP(dest_realm);
1033                                 strupper_m(realm);
1034                         } else {
1035                                 realm = kerberos_get_default_realm_from_ccache();
1036                         }
1037                         if (realm && *realm) {
1038                                 principal = talloc_asprintf(NULL, "%s$@%s",
1039                                                         machine, realm);
1040                                 if (!principal) {
1041                                         SAFE_FREE(machine);
1042                                         SAFE_FREE(realm);
1043                                         return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1044                                 }
1045                                 DEBUG(3,("cli_session_setup_spnego: guessed "
1046                                         "server principal=%s\n",
1047                                         principal ? principal : "<null>"));
1048                         }
1049                         SAFE_FREE(machine);
1050                         SAFE_FREE(realm);
1051                 }
1052 
1053                 if (principal) {
1054                         rc = cli_session_setup_kerberos(cli, principal,
1055                                 dest_realm);
1056                         if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1057                                 TALLOC_FREE(principal);
1058                                 return rc;
1059                         }
1060                 }
1061         }
1062 #endif
1063 
1064         TALLOC_FREE(principal);
1065 
1066 ntlmssp:
1067 
1068         account = talloc_strdup(talloc_tos(), user);
1069         if (!account) {
1070                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1071         }
1072 
1073         /* when falling back to ntlmssp while authenticating with a machine
1074          * account strip off the realm - gd */
1075 
1076         if ((p = strchr_m(user, '@')) != NULL) {
1077                 account[PTR_DIFF(p,user)] = '\0';
1078         }
1079 
1080         return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1081 }
1082 
1083 /****************************************************************************
1084  Send a session setup. The username and workgroup is in UNIX character
1085  format and must be converted to DOS codepage format before sending. If the
1086  password is in plaintext, the same should be done.
1087 ****************************************************************************/
1088 
1089 NTSTATUS cli_session_setup(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
1090                            const char *user,
1091                            const char *pass, int passlen,
1092                            const char *ntpass, int ntpasslen,
1093                            const char *workgroup)
1094 {
1095         char *p;
1096         fstring user2;
1097 
1098         if (user) {
1099                 fstrcpy(user2, user);
1100         } else {
1101                 user2[0] ='\0';
1102         }
1103 
1104         if (!workgroup) {
1105                 workgroup = "";
1106         }
1107 
1108         /* allow for workgroups as part of the username */
1109         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1110             (p=strchr_m(user2,*lp_winbind_separator()))) {
1111                 *p = 0;
1112                 user = p+1;
1113                 workgroup = user2;
1114         }
1115 
1116         if (cli->protocol < PROTOCOL_LANMAN1) {
1117                 return NT_STATUS_OK;
1118         }
1119 
1120         /* now work out what sort of session setup we are going to
1121            do. I have split this into separate functions to make the
1122            flow a bit easier to understand (tridge) */
1123 
1124         /* if its an older server then we have to use the older request format */
1125 
1126         if (cli->protocol < PROTOCOL_NT1) {
1127                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1128                         DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1129                                   " is disabled\n"));
1130                         return NT_STATUS_ACCESS_DENIED;
1131                 }
1132 
1133                 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1134                     !lp_client_plaintext_auth() && (*pass)) {
1135                         DEBUG(1, ("Server requested plaintext password but "
1136                                   "'client plaintext auth' is disabled\n"));
1137                         return NT_STATUS_ACCESS_DENIED;
1138                 }
1139 
1140                 return cli_session_setup_lanman2(cli, user, pass, passlen,
1141                                                  workgroup);
1142         }
1143 
1144         /* if no user is supplied then we have to do an anonymous connection.
1145            passwords are ignored */
1146 
1147         if (!user || !*user)
1148                 return cli_session_setup_guest(cli);
1149 
1150         /* if the server is share level then send a plaintext null
1151            password at this point. The password is sent in the tree
1152            connect */
1153 
1154         if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
1155                 return cli_session_setup_plaintext(cli, user, "", workgroup);
1156 
1157         /* if the server doesn't support encryption then we have to use 
1158            plaintext. The second password is ignored */
1159 
1160         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1161                 if (!lp_client_plaintext_auth() && (*pass)) {
1162                         DEBUG(1, ("Server requested plaintext password but "
1163                                   "'client plaintext auth' is disabled\n"));
1164                         return NT_STATUS_ACCESS_DENIED;
1165                 }
1166                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1167         }
1168 
1169         /* if the server supports extended security then use SPNEGO */
1170 
1171         if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1172                 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1173                                                              workgroup, NULL);
1174                 if (!ADS_ERR_OK(status)) {
1175                         DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1176                         return ads_ntstatus(status);
1177                 }
1178         } else {
1179                 NTSTATUS status;
1180 
1181                 /* otherwise do a NT1 style session setup */
1182                 status = cli_session_setup_nt1(cli, user, pass, passlen,
1183                                                ntpass, ntpasslen, workgroup);
1184                 if (!NT_STATUS_IS_OK(status)) {
1185                         DEBUG(3,("cli_session_setup: NT1 session setup "
1186                                  "failed: %s\n", nt_errstr(status)));
1187                         return status;
1188                 }
1189         }
1190 
1191         if (strstr(cli->server_type, "Samba")) {
1192                 cli->is_samba = True;
1193         }
1194 
1195         return NT_STATUS_OK;
1196 }
1197 
1198 /****************************************************************************
1199  Send a uloggoff.
1200 *****************************************************************************/
1201 
1202 bool cli_ulogoff(struct cli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
1203 {
1204         memset(cli->outbuf,'\0',smb_size);
1205         cli_set_message(cli->outbuf,2,0,True);
1206         SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1207         cli_setup_packet(cli);
1208         SSVAL(cli->outbuf,smb_vwv0,0xFF);
1209         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
1210 
1211         cli_send_smb(cli);
1212         if (!cli_receive_smb(cli))
1213                 return False;
1214 
1215         if (cli_is_error(cli)) {
1216                 return False;
1217         }
1218 
1219         cli->vuid = -1;
1220         return True;
1221 }
1222 
1223 /****************************************************************************
1224  Send a tconX.
1225 ****************************************************************************/
1226 
1227 struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1228                                      struct event_context *ev,
1229                                      struct cli_state *cli,
1230                                      const char *share, const char *dev,
1231                                      const char *pass, int passlen)
1232 {
1233         fstring pword;
1234         char *tmp = NULL;
1235         struct async_req *result;
1236         uint16_t vwv[4];
1237         uint8_t *bytes;
1238 
1239         fstrcpy(cli->share, share);
1240 
1241         /* in user level security don't send a password now */
1242         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1243                 passlen = 1;
1244                 pass = "";
1245         } else if (pass == NULL) {
1246                 DEBUG(1, ("Server not using user level security and no "
1247                           "password supplied.\n"));
1248                 goto access_denied;
1249         }
1250 
1251         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1252             *pass && passlen != 24) {
1253                 if (!lp_client_lanman_auth()) {
1254                         DEBUG(1, ("Server requested LANMAN password "
1255                                   "(share-level security) but "
1256                                   "'client lanman auth' is disabled\n"));
1257                         goto access_denied;
1258                 }
1259 
1260                 /*
1261                  * Non-encrypted passwords - convert to DOS codepage before
1262                  * encryption.
1263                  */
1264                 passlen = 24;
1265                 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1266         } else {
1267                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1268                                      |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1269                    == 0) {
1270                         if (!lp_client_plaintext_auth() && (*pass)) {
1271                                 DEBUG(1, ("Server requested plaintext "
1272                                           "password but 'client plaintext "
1273                                           "auth' is disabled\n"));
1274                                 goto access_denied;
1275                         }
1276 
1277                         /*
1278                          * Non-encrypted passwords - convert to DOS codepage
1279                          * before using.
1280                          */
1281                         passlen = clistr_push(cli, pword, pass, sizeof(pword),
1282                                               STR_TERMINATE);
1283                         if (passlen == -1) {
1284                                 DEBUG(1, ("clistr_push(pword) failed\n"));
1285                                 goto access_denied;
1286                         }
1287                 } else {
1288                         if (passlen) {
1289                                 memcpy(pword, pass, passlen);
1290                         }
1291                 }
1292         }
1293 
1294         SCVAL(vwv+0, 0, 0xFF);
1295         SCVAL(vwv+0, 1, 0);
1296         SSVAL(vwv+1, 0, 0);
1297         SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1298         SSVAL(vwv+3, 0, passlen);
1299 
1300         if (passlen) {
1301                 bytes = (uint8_t *)talloc_memdup(talloc_tos(), pword, passlen);
1302         } else {
1303                 bytes = talloc_array(talloc_tos(), uint8_t, 0);
1304         }
1305 
1306         /*
1307          * Add the sharename
1308          */
1309         tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1310                                          cli->desthost, share);
1311         if (tmp == NULL) {
1312                 TALLOC_FREE(bytes);
1313                 return NULL;
1314         }
1315         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1316                                    NULL);
1317         TALLOC_FREE(tmp);
1318 
1319         /*
1320          * Add the devicetype
1321          */
1322         tmp = talloc_strdup_upper(talloc_tos(), dev);
1323         if (tmp == NULL) {
1324                 TALLOC_FREE(bytes);
1325                 return NULL;
1326         }
1327         bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1328         TALLOC_FREE(tmp);
1329 
1330         if (bytes == NULL) {
1331                 return NULL;
1332         }
1333 
1334         result = cli_request_send(mem_ctx, ev, cli, SMBtconX, 0,
1335                                   4, vwv, 0, talloc_get_size(bytes), bytes);
1336         TALLOC_FREE(bytes);
1337         return result;
1338 
1339  access_denied:
1340         {
1341                 struct cli_request *state;
1342                 if (!async_req_setup(mem_ctx, &result, &state,
1343                                      struct cli_request)) {
1344                         goto fail;
1345                 }
1346                 if (async_post_ntstatus(result, ev, NT_STATUS_ACCESS_DENIED)) {
1347                         return result;
1348                 }
1349         }
1350  fail:
1351         TALLOC_FREE(result);
1352         return NULL;
1353 }
1354 
1355 NTSTATUS cli_tcon_andx_recv(struct async_req *req)
     /* [<][>][^][v][top][bottom][index][help] */
1356 {
1357         struct cli_request *cli_req = talloc_get_type_abort(
1358                 req->private_data, struct cli_request);
1359         struct cli_state *cli = cli_req->cli;
1360         uint8_t wct;
1361         uint16_t *vwv;
1362         uint16_t num_bytes;
1363         uint8_t *bytes;
1364         NTSTATUS status;
1365 
1366         if (async_req_is_nterror(req, &status)) {
1367                 return status;
1368         }
1369 
1370         status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1371         if (!NT_STATUS_IS_OK(status)) {
1372                 return status;
1373         }
1374 
1375         clistr_pull(cli_req->inbuf, cli->dev, bytes, sizeof(fstring),
1376                     num_bytes, STR_TERMINATE|STR_ASCII);
1377 
1378         if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1379                 /* almost certainly win95 - enable bug fixes */
1380                 cli->win95 = True;
1381         }
1382 
1383         /*
1384          * Make sure that we have the optional support 16-bit field. WCT > 2.
1385          * Avoids issues when connecting to Win9x boxes sharing files
1386          */
1387 
1388         cli->dfsroot = false;
1389 
1390         if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1391                 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1392         }
1393 
1394         cli->cnum = SVAL(cli_req->inbuf,smb_tid);
1395         return NT_STATUS_OK;
1396 }
1397 
1398 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
     /* [<][>][^][v][top][bottom][index][help] */
1399                        const char *dev, const char *pass, int passlen)
1400 {
1401         TALLOC_CTX *frame = talloc_stackframe();
1402         struct event_context *ev;
1403         struct async_req *req;
1404         NTSTATUS status;
1405 
1406         if (cli->fd_event != NULL) {
1407                 /*
1408                  * Can't use sync call while an async call is in flight
1409                  */
1410                 status = NT_STATUS_INVALID_PARAMETER;
1411                 goto fail;
1412         }
1413 
1414         ev = event_context_init(frame);
1415         if (ev == NULL) {
1416                 status = NT_STATUS_NO_MEMORY;
1417                 goto fail;
1418         }
1419 
1420         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1421         if (req == NULL) {
1422                 status = NT_STATUS_NO_MEMORY;
1423                 goto fail;
1424         }
1425 
1426         while (req->state < ASYNC_REQ_DONE) {
1427                 event_loop_once(ev);
1428         }
1429 
1430         status = cli_tcon_andx_recv(req);
1431  fail:
1432         TALLOC_FREE(frame);
1433         return status;
1434 }
1435 
1436 /****************************************************************************
1437  Send a tree disconnect.
1438 ****************************************************************************/
1439 
1440 bool cli_tdis(struct cli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
1441 {
1442         memset(cli->outbuf,'\0',smb_size);
1443         cli_set_message(cli->outbuf,0,0,True);
1444         SCVAL(cli->outbuf,smb_com,SMBtdis);
1445         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1446         cli_setup_packet(cli);
1447 
1448         cli_send_smb(cli);
1449         if (!cli_receive_smb(cli))
1450                 return False;
1451 
1452         if (cli_is_error(cli)) {
1453                 return False;
1454         }
1455 
1456         cli->cnum = -1;
1457         return True;
1458 }
1459 
1460 /****************************************************************************
1461  Send a negprot command.
1462 ****************************************************************************/
1463 
1464 void cli_negprot_sendsync(struct cli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
1465 {
1466         char *p;
1467         int numprots;
1468 
1469         if (cli->protocol < PROTOCOL_NT1)
1470                 cli->use_spnego = False;
1471 
1472         memset(cli->outbuf,'\0',smb_size);
1473 
1474         /* setup the protocol strings */
1475         cli_set_message(cli->outbuf,0,0,True);
1476 
1477         p = smb_buf(cli->outbuf);
1478         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1479                 if (prots[numprots].prot > cli->protocol) {
1480                         break;
1481                 }
1482                 *p++ = 2;
1483                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1484         }
1485 
1486         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1487         cli_setup_bcc(cli, p);
1488         cli_setup_packet(cli);
1489 
1490         SCVAL(smb_buf(cli->outbuf),0,2);
1491 
1492         cli_send_smb(cli);
1493 }
1494 
1495 /****************************************************************************
1496  Send a negprot command.
1497 ****************************************************************************/
1498 
1499 struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1500                                    struct event_context *ev,
1501                                    struct cli_state *cli)
1502 {
1503         struct async_req *result;
1504         uint8_t *bytes = NULL;
1505         int numprots;
1506 
1507         if (cli->protocol < PROTOCOL_NT1)
1508                 cli->use_spnego = False;
1509 
1510         /* setup the protocol strings */
1511         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1512                 uint8_t c = 2;
1513                 if (prots[numprots].prot > cli->protocol) {
1514                         break;
1515                 }
1516                 bytes = (uint8_t *)talloc_append_blob(
1517                         talloc_tos(), bytes, data_blob_const(&c, sizeof(c)));
1518                 if (bytes == NULL) {
1519                         return NULL;
1520                 }
1521                 bytes = smb_bytes_push_str(bytes, false,
1522                                            prots[numprots].name,
1523                                            strlen(prots[numprots].name)+1,
1524                                            NULL);
1525                 if (bytes == NULL) {
1526                         return NULL;
1527                 }
1528         }
1529 
1530         result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, 0,
1531                                   talloc_get_size(bytes), bytes);
1532         TALLOC_FREE(bytes);
1533         return result;
1534 }
1535 
1536 NTSTATUS cli_negprot_recv(struct async_req *req)
     /* [<][>][^][v][top][bottom][index][help] */
1537 {
1538         struct cli_request *cli_req = talloc_get_type_abort(
1539                 req->private_data, struct cli_request);
1540         struct cli_state *cli = cli_req->cli;
1541         uint8_t wct;
1542         uint16_t *vwv;
1543         uint16_t num_bytes;
1544         uint8_t *bytes;
1545         NTSTATUS status;
1546         uint16_t protnum;
1547 
1548         if (async_req_is_nterror(req, &status)) {
1549                 return status;
1550         }
1551 
1552         status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1553         if (!NT_STATUS_IS_OK(status)) {
1554                 return status;
1555         }
1556 
1557         protnum = SVAL(vwv, 0);
1558 
1559         if ((protnum >= ARRAY_SIZE(prots))
1560             || (prots[protnum].prot > cli_req->cli->protocol)) {
1561                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1562         }
1563 
1564         cli->protocol = prots[protnum].prot;
1565 
1566         if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1567                 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1568                 return NT_STATUS_ACCESS_DENIED;
1569         }
1570 
1571         if (cli->protocol >= PROTOCOL_NT1) {    
1572                 struct timespec ts;
1573                 /* NT protocol */
1574                 cli->sec_mode = CVAL(vwv + 1, 0);
1575                 cli->max_mux = SVAL(vwv + 1, 1);
1576                 cli->max_xmit = IVAL(vwv + 3, 1);
1577                 cli->sesskey = IVAL(vwv + 7, 1);
1578                 cli->serverzone = SVALS(vwv + 15, 1);
1579                 cli->serverzone *= 60;
1580                 /* this time arrives in real GMT */
1581                 ts = interpret_long_date(((char *)(vwv+11))+1);
1582                 cli->servertime = ts.tv_sec;
1583                 cli->secblob = data_blob(bytes, num_bytes);
1584                 cli->capabilities = IVAL(vwv + 9, 1);
1585                 if (cli->capabilities & CAP_RAW_MODE) {
1586                         cli->readbraw_supported = True;
1587                         cli->writebraw_supported = True;      
1588                 }
1589                 /* work out if they sent us a workgroup */
1590                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1591                     smb_buflen(cli->inbuf) > 8) {
1592                         clistr_pull(cli->inbuf, cli->server_domain,
1593                                     bytes+8, sizeof(cli->server_domain),
1594                                     num_bytes-8,
1595                                     STR_UNICODE|STR_NOALIGN);
1596                 }
1597 
1598                 /*
1599                  * As signing is slow we only turn it on if either the client or
1600                  * the server require it. JRA.
1601                  */
1602 
1603                 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1604                         /* Fail if server says signing is mandatory and we don't want to support it. */
1605                         if (!cli->sign_info.allow_smb_signing) {
1606                                 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1607                                 return NT_STATUS_ACCESS_DENIED;
1608                         }
1609                         cli->sign_info.negotiated_smb_signing = True;
1610                         cli->sign_info.mandatory_signing = True;
1611                 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1612                         /* Fail if client says signing is mandatory and the server doesn't support it. */
1613                         if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1614                                 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1615                                 return NT_STATUS_ACCESS_DENIED;
1616                         }
1617                         cli->sign_info.negotiated_smb_signing = True;
1618                         cli->sign_info.mandatory_signing = True;
1619                 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1620                         cli->sign_info.negotiated_smb_signing = True;
1621                 }
1622 
1623                 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1624                         SAFE_FREE(cli->outbuf);
1625                         SAFE_FREE(cli->inbuf);
1626                         cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1627                         cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1628                         cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1629                 }
1630 
1631         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1632                 cli->use_spnego = False;
1633                 cli->sec_mode = SVAL(vwv + 1, 0);
1634                 cli->max_xmit = SVAL(vwv + 2, 0);
1635                 cli->max_mux = SVAL(vwv + 3, 0);
1636                 cli->sesskey = IVAL(vwv + 6, 0);
1637                 cli->serverzone = SVALS(vwv + 10, 0);
1638                 cli->serverzone *= 60;
1639                 /* this time is converted to GMT by make_unix_date */
1640                 cli->servertime = cli_make_unix_date(
1641                         cli, (char *)(vwv + 8));
1642                 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1643                 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1644                 cli->secblob = data_blob(bytes, num_bytes);
1645         } else {
1646                 /* the old core protocol */
1647                 cli->use_spnego = False;
1648                 cli->sec_mode = 0;
1649                 cli->serverzone = get_time_zone(time(NULL));
1650         }
1651 
1652         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1653 
1654         /* a way to force ascii SMB */
1655         if (getenv("CLI_FORCE_ASCII"))
1656                 cli->capabilities &= ~CAP_UNICODE;
1657 
1658         return NT_STATUS_OK;
1659 }
1660 
1661 NTSTATUS cli_negprot(struct cli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
1662 {
1663         TALLOC_CTX *frame = talloc_stackframe();
1664         struct event_context *ev;
1665         struct async_req *req;
1666         NTSTATUS status = NT_STATUS_NO_MEMORY;
1667 
1668         if (cli->fd_event != NULL) {
1669                 /*
1670                  * Can't use sync call while an async call is in flight
1671                  */
1672                 cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
1673                 goto fail;
1674         }
1675 
1676         ev = event_context_init(frame);
1677         if (ev == NULL) {
1678                 goto fail;
1679         }
1680 
1681         req = cli_negprot_send(frame, ev, cli);
1682         if (req == NULL) {
1683                 goto fail;
1684         }
1685 
1686         while (req->state < ASYNC_REQ_DONE) {
1687                 event_loop_once(ev);
1688         }
1689 
1690         status = cli_negprot_recv(req);
1691  fail:
1692         TALLOC_FREE(frame);
1693         return status;
1694 }
1695 
1696 /****************************************************************************
1697  Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1698 ****************************************************************************/
1699 
1700 bool cli_session_request(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
1701                          struct nmb_name *calling, struct nmb_name *called)
1702 {
1703         char *p;
1704         int len = 4;
1705         char *tmp;
1706 
1707         /* 445 doesn't have session request */
1708         if (cli->port == 445)
1709                 return True;
1710 
1711         memcpy(&(cli->calling), calling, sizeof(*calling));
1712         memcpy(&(cli->called ), called , sizeof(*called ));
1713 
1714         /* put in the destination name */
1715 
1716         tmp = name_mangle(talloc_tos(), cli->called.name,
1717                           cli->called.name_type);
1718         if (tmp == NULL) {
1719                 return false;
1720         }
1721 
1722         p = cli->outbuf+len;
1723         memcpy(p, tmp, name_len(tmp));
1724         len += name_len(tmp);
1725         TALLOC_FREE(tmp);
1726 
1727         /* and my name */
1728 
1729         tmp = name_mangle(talloc_tos(), cli->calling.name,
1730                           cli->calling.name_type);
1731         if (tmp == NULL) {
1732                 return false;
1733         }
1734 
1735         p = cli->outbuf+len;
1736         memcpy(p, tmp, name_len(tmp));
1737         len += name_len(tmp);
1738         TALLOC_FREE(tmp);
1739 
1740         /* send a session request (RFC 1002) */
1741         /* setup the packet length
1742          * Remove four bytes from the length count, since the length
1743          * field in the NBT Session Service header counts the number
1744          * of bytes which follow.  The cli_send_smb() function knows
1745          * about this and accounts for those four bytes.
1746          * CRH.
1747          */
1748         len -= 4;
1749         _smb_setlen(cli->outbuf,len);
1750         SCVAL(cli->outbuf,0,0x81);
1751 
1752         cli_send_smb(cli);
1753         DEBUG(5,("Sent session request\n"));
1754 
1755         if (!cli_receive_smb(cli))
1756                 return False;
1757 
1758         if (CVAL(cli->inbuf,0) == 0x84) {
1759                 /* C. Hoch  9/14/95 Start */
1760                 /* For information, here is the response structure.
1761                  * We do the byte-twiddling to for portability.
1762                 struct RetargetResponse{
1763                 unsigned char type;
1764                 unsigned char flags;
1765                 int16 length;
1766                 int32 ip_addr;
1767                 int16 port;
1768                 };
1769                 */
1770                 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1771                 struct in_addr dest_ip;
1772                 NTSTATUS status;
1773 
1774                 /* SESSION RETARGET */
1775                 putip((char *)&dest_ip,cli->inbuf+4);
1776                 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1777 
1778                 status = open_socket_out(&cli->dest_ss, port,
1779                                          LONG_CONNECT_TIMEOUT, &cli->fd);
1780                 if (!NT_STATUS_IS_OK(status)) {
1781                         return False;
1782                 }
1783 
1784                 DEBUG(3,("Retargeted\n"));
1785 
1786                 set_socket_options(cli->fd, lp_socket_options());
1787 
1788                 /* Try again */
1789                 {
1790                         static int depth;
1791                         bool ret;
1792                         if (depth > 4) {
1793                                 DEBUG(0,("Retarget recursion - failing\n"));
1794                                 return False;
1795                         }
1796                         depth++;
1797                         ret = cli_session_request(cli, calling, called);
1798                         depth--;
1799                         return ret;
1800                 }
1801         } /* C. Hoch 9/14/95 End */
1802 
1803         if (CVAL(cli->inbuf,0) != 0x82) {
1804                 /* This is the wrong place to put the error... JRA. */
1805                 cli->rap_error = CVAL(cli->inbuf,4);
1806                 return False;
1807         }
1808         return(True);
1809 }
1810 
1811 struct fd_struct {
1812         int fd;
1813 };
1814 
1815 static void smb_sock_connected(struct tevent_req *req)
     /* [<][>][^][v][top][bottom][index][help] */
1816 {
1817         struct fd_struct *pfd = tevent_req_callback_data(
1818                 req, struct fd_struct);
1819         int fd;
1820         NTSTATUS status;
1821 
1822         status = open_socket_out_defer_recv(req, &fd);
1823         if (NT_STATUS_IS_OK(status)) {
1824                 pfd->fd = fd;
1825         }
1826 }
1827 
1828 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
     /* [<][>][^][v][top][bottom][index][help] */
1829                                 uint16_t *port, int timeout, int *pfd)
1830 {
1831         struct event_context *ev;
1832         struct tevent_req *r139, *r445;
1833         struct fd_struct *fd139, *fd445;
1834         NTSTATUS status = NT_STATUS_NO_MEMORY;
1835 
1836         if (*port != 0) {
1837                 return open_socket_out(pss, *port, timeout, pfd);
1838         }
1839 
1840         ev = event_context_init(talloc_tos());
1841         if (ev == NULL) {
1842                 return NT_STATUS_NO_MEMORY;
1843         }
1844 
1845         fd139 = talloc(ev, struct fd_struct);
1846         if (fd139 == NULL) {
1847                 goto done;
1848         }
1849         fd139->fd = -1;
1850 
1851         fd445 = talloc(ev, struct fd_struct);
1852         if (fd445 == NULL) {
1853                 goto done;
1854         }
1855         fd445->fd = -1;
1856 
1857         r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1858                                           pss, 445, timeout);
1859         r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1860                                           pss, 139, timeout);
1861         if ((r445 == NULL) || (r139 == NULL)) {
1862                 goto done;
1863         }
1864         tevent_req_set_callback(r445, smb_sock_connected, fd445);
1865         tevent_req_set_callback(r139, smb_sock_connected, fd139);
1866 
1867         while ((fd445->fd == -1) && (fd139->fd == -1)
1868                && (tevent_req_is_in_progress(r139)
1869                    || tevent_req_is_in_progress(r445))) {
1870                 event_loop_once(ev);
1871         }
1872 
1873         if ((fd139->fd != -1) && (fd445->fd != -1)) {
1874                 close(fd139->fd);
1875                 fd139->fd = -1;
1876         }
1877 
1878         if (fd445->fd != -1) {
1879                 *port = 445;
1880                 *pfd = fd445->fd;
1881                 status = NT_STATUS_OK;
1882                 goto done;
1883         }
1884         if (fd139->fd != -1) {
1885                 *port = 139;
1886                 *pfd = fd139->fd;
1887                 status = NT_STATUS_OK;
1888                 goto done;
1889         }
1890 
1891         status = open_socket_out_defer_recv(r445, &fd445->fd);
1892  done:
1893         TALLOC_FREE(ev);
1894         return status;
1895 }
1896 
1897 /****************************************************************************
1898  Open the client sockets.
1899 ****************************************************************************/
1900 
1901 NTSTATUS cli_connect(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
1902                 const char *host,
1903                 struct sockaddr_storage *dest_ss)
1904 
1905 {
1906         int name_type = 0x20;
1907         TALLOC_CTX *frame = talloc_stackframe();
1908         unsigned int num_addrs = 0;
1909         unsigned int i = 0;
1910         struct sockaddr_storage *ss_arr = NULL;
1911         char *p = NULL;
1912 
1913         /* reasonable default hostname */
1914         if (!host) {
1915                 host = STAR_SMBSERVER;
1916         }
1917 
1918         fstrcpy(cli->desthost, host);
1919 
1920         /* allow hostnames of the form NAME#xx and do a netbios lookup */
1921         if ((p = strchr(cli->desthost, '#'))) {
1922                 name_type = strtol(p+1, NULL, 16);
1923                 *p = 0;
1924         }
1925 
1926         if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
1927                 NTSTATUS status =resolve_name_list(frame,
1928                                         cli->desthost,
1929                                         name_type,
1930                                         &ss_arr,
1931                                         &num_addrs);
1932                 if (!NT_STATUS_IS_OK(status)) {
1933                         TALLOC_FREE(frame);
1934                         return NT_STATUS_BAD_NETWORK_NAME;
1935                 }
1936         } else {
1937                 num_addrs = 1;
1938                 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
1939                 if (!ss_arr) {
1940                         TALLOC_FREE(frame);
1941                         return NT_STATUS_NO_MEMORY;
1942                 }
1943                 *ss_arr = *dest_ss;
1944         }
1945 
1946         for (i = 0; i < num_addrs; i++) {
1947                 cli->dest_ss = ss_arr[i];
1948                 if (getenv("LIBSMB_PROG")) {
1949                         cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1950                 } else {
1951                         uint16_t port = cli->port;
1952                         NTSTATUS status;
1953                         status = open_smb_socket(&cli->dest_ss, &port,
1954                                                  cli->timeout, &cli->fd);
1955                         if (NT_STATUS_IS_OK(status)) {
1956                                 cli->port = port;
1957                         }
1958                 }
1959                 if (cli->fd == -1) {
1960                         char addr[INET6_ADDRSTRLEN];
1961                         print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
1962                         DEBUG(2,("Error connecting to %s (%s)\n",
1963                                  dest_ss?addr:host,strerror(errno)));
1964                 } else {
1965                         /* Exit from loop on first connection. */
1966                         break;
1967                 }
1968         }
1969 
1970         if (cli->fd == -1) {
1971                 TALLOC_FREE(frame);
1972                 return map_nt_error_from_unix(errno);
1973         }
1974 
1975         if (dest_ss) {
1976                 *dest_ss = cli->dest_ss;
1977         }
1978 
1979         set_socket_options(cli->fd, lp_socket_options());
1980 
1981         TALLOC_FREE(frame);
1982         return NT_STATUS_OK;
1983 }
1984 
1985 /**
1986    establishes a connection to after the negprot. 
1987    @param output_cli A fully initialised cli structure, non-null only on success
1988    @param dest_host The netbios name of the remote host
1989    @param dest_ss (optional) The the destination IP, NULL for name based lookup
1990    @param port (optional) The destination port (0 for default)
1991    @param retry bool. Did this connection fail with a retryable error ?
1992 
1993 */
1994 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
     /* [<][>][^][v][top][bottom][index][help] */
1995                               const char *my_name, 
1996                               const char *dest_host, 
1997                               struct sockaddr_storage *dest_ss, int port,
1998                               int signing_state, int flags,
1999                               bool *retry) 
2000 {
2001         NTSTATUS nt_status;
2002         struct nmb_name calling;
2003         struct nmb_name called;
2004         struct cli_state *cli;
2005         struct sockaddr_storage ss;
2006 
2007         if (retry)
2008                 *retry = False;
2009 
2010         if (!my_name) 
2011                 my_name = global_myname();
2012 
2013         if (!(cli = cli_initialise_ex(signing_state))) {
2014                 return NT_STATUS_NO_MEMORY;
2015         }
2016 
2017         make_nmb_name(&calling, my_name, 0x0);
2018         make_nmb_name(&called , dest_host, 0x20);
2019 
2020         cli_set_port(cli, port);
2021         cli_set_timeout(cli, 10000); /* 10 seconds. */
2022 
2023         if (dest_ss) {
2024                 ss = *dest_ss;
2025         } else {
2026                 zero_sockaddr(&ss);
2027         }
2028 
2029 again:
2030 
2031         DEBUG(3,("Connecting to host=%s\n", dest_host));
2032 
2033         nt_status = cli_connect(cli, dest_host, &ss);
2034         if (!NT_STATUS_IS_OK(nt_status)) {
2035                 char addr[INET6_ADDRSTRLEN];
2036                 print_sockaddr(addr, sizeof(addr), &ss);
2037                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2038                          nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2039                 cli_shutdown(cli);
2040                 return nt_status;
2041         }
2042 
2043         if (retry)
2044                 *retry = True;
2045 
2046         if (!cli_session_request(cli, &calling, &called)) {
2047                 char *p;
2048                 DEBUG(1,("session request to %s failed (%s)\n",
2049                          called.name, cli_errstr(cli)));
2050                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2051                         *p = 0;
2052                         goto again;
2053                 }
2054                 if (strcmp(called.name, STAR_SMBSERVER)) {
2055                         make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2056                         goto again;
2057                 }
2058                 return NT_STATUS_BAD_NETWORK_NAME;
2059         }
2060 
2061         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2062                 cli->use_spnego = False;
2063         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2064                 cli->use_kerberos = True;
2065 
2066         if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2067              cli->use_kerberos) {
2068                 cli->fallback_after_kerberos = true;
2069         }
2070 
2071         nt_status = cli_negprot(cli);
2072         if (!NT_STATUS_IS_OK(nt_status)) {
2073                 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2074                 cli_shutdown(cli);
2075                 return nt_status;
2076         }
2077 
2078         *output_cli = cli;
2079         return NT_STATUS_OK;
2080 }
2081 
2082 
2083 /**
2084    establishes a connection right up to doing tconX, password specified.
2085    @param output_cli A fully initialised cli structure, non-null only on success
2086    @param dest_host The netbios name of the remote host
2087    @param dest_ip (optional) The the destination IP, NULL for name based lookup
2088    @param port (optional) The destination port (0 for default)
2089    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
2090    @param service_type The 'type' of serivice. 
2091    @param user Username, unix string
2092    @param domain User's domain
2093    @param password User's password, unencrypted unix string.
2094    @param retry bool. Did this connection fail with a retryable error ?
2095 */
2096 
2097 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
     /* [<][>][^][v][top][bottom][index][help] */
2098                              const char *my_name, 
2099                              const char *dest_host, 
2100                              struct sockaddr_storage *dest_ss, int port,
2101                              const char *service, const char *service_type,
2102                              const char *user, const char *domain, 
2103                              const char *password, int flags,
2104                              int signing_state,
2105                              bool *retry) 
2106 {
2107         NTSTATUS nt_status;
2108         struct cli_state *cli = NULL;
2109         int pw_len = password ? strlen(password)+1 : 0;
2110 
2111         *output_cli = NULL;
2112 
2113         if (password == NULL) {
2114                 password = "";
2115         }
2116 
2117         nt_status = cli_start_connection(&cli, my_name, dest_host,
2118                                          dest_ss, port, signing_state,
2119                                          flags, retry);
2120 
2121         if (!NT_STATUS_IS_OK(nt_status)) {
2122                 return nt_status;
2123         }
2124 
2125         nt_status = cli_session_setup(cli, user, password, pw_len, password,
2126                                       pw_len, domain);
2127         if (!NT_STATUS_IS_OK(nt_status)) {
2128 
2129                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2130                         DEBUG(1,("failed session setup with %s\n",
2131                                  nt_errstr(nt_status)));
2132                         cli_shutdown(cli);
2133                         return nt_status;
2134                 }
2135 
2136                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2137                 if (!NT_STATUS_IS_OK(nt_status)) {
2138                         DEBUG(1,("anonymous failed session setup with %s\n",
2139                                  nt_errstr(nt_status)));
2140                         cli_shutdown(cli);
2141                         return nt_status;
2142                 }
2143         }
2144 
2145         if (service) {
2146                 nt_status = cli_tcon_andx(cli, service, service_type, password,
2147                                           pw_len);
2148                 if (!NT_STATUS_IS_OK(nt_status)) {
2149                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2150                         cli_shutdown(cli);
2151                         if (NT_STATUS_IS_OK(nt_status)) {
2152                                 nt_status = NT_STATUS_UNSUCCESSFUL;
2153                         }
2154                         return nt_status;
2155                 }
2156         }
2157 
2158         nt_status = cli_init_creds(cli, user, domain, password);
2159         if (!NT_STATUS_IS_OK(nt_status)) {
2160                 cli_shutdown(cli);
2161                 return nt_status;
2162         }
2163 
2164         *output_cli = cli;
2165         return NT_STATUS_OK;
2166 }
2167 
2168 /****************************************************************************
2169  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2170 ****************************************************************************/
2171 
2172 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
     /* [<][>][^][v][top][bottom][index][help] */
2173                                      struct sockaddr_storage *pdest_ss)
2174 {
2175         struct nmb_name calling, called;
2176 
2177         make_nmb_name(&calling, srchost, 0x0);
2178 
2179         /*
2180          * If the called name is an IP address
2181          * then use *SMBSERVER immediately.
2182          */
2183 
2184         if(is_ipaddress(desthost)) {
2185                 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2186         } else {
2187                 make_nmb_name(&called, desthost, 0x20);
2188         }
2189 
2190         if (!cli_session_request(*ppcli, &calling, &called)) {
2191                 NTSTATUS status;
2192                 struct nmb_name smbservername;
2193 
2194                 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2195 
2196                 /*
2197                  * If the name wasn't *SMBSERVER then
2198                  * try with *SMBSERVER if the first name fails.
2199                  */
2200 
2201                 if (nmb_name_equal(&called, &smbservername)) {
2202 
2203                         /*
2204                          * The name used was *SMBSERVER, don't bother with another name.
2205                          */
2206 
2207                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2208 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2209                         return False;
2210                 }
2211 
2212                 /* Try again... */
2213                 cli_shutdown(*ppcli);
2214 
2215                 *ppcli = cli_initialise();
2216                 if (!*ppcli) {
2217                         /* Out of memory... */
2218                         return False;
2219                 }
2220 
2221                 status = cli_connect(*ppcli, desthost, pdest_ss);
2222                 if (!NT_STATUS_IS_OK(status) ||
2223                                 !cli_session_request(*ppcli, &calling, &smbservername)) {
2224                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2225 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2226                         return False;
2227                 }
2228         }
2229 
2230         return True;
2231 }
2232 
2233 /****************************************************************************
2234  Send an old style tcon.
2235 ****************************************************************************/
2236 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
     /* [<][>][^][v][top][bottom][index][help] */
2237                       const char *service, const char *pass, const char *dev,
2238                       uint16 *max_xmit, uint16 *tid)
2239 {
2240         char *p;
2241 
2242         if (!lp_client_plaintext_auth() && (*pass)) {
2243                 DEBUG(1, ("Server requested plaintext password but 'client "
2244                           "plaintext auth' is disabled\n"));
2245                 return NT_STATUS_ACCESS_DENIED;
2246         }
2247 
2248         memset(cli->outbuf,'\0',smb_size);
2249         memset(cli->inbuf,'\0',smb_size);
2250 
2251         cli_set_message(cli->outbuf, 0, 0, True);
2252         SCVAL(cli->outbuf,smb_com,SMBtcon);
2253         cli_setup_packet(cli);
2254 
2255         p = smb_buf(cli->outbuf);
2256         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2257         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2258         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2259 
2260         cli_setup_bcc(cli, p);
2261 
2262         cli_send_smb(cli);
2263         if (!cli_receive_smb(cli)) {
2264                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2265         }
2266 
2267         if (cli_is_error(cli)) {
2268                 return cli_nt_error(cli);
2269         }
2270 
2271         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2272         *tid = SVAL(cli->inbuf, smb_vwv1);
2273 
2274         return NT_STATUS_OK;
2275 }
2276 
2277 /* Return a cli_state pointing at the IPC$ share for the given server */
2278 
2279 struct cli_state *get_ipc_connect(char *server,
     /* [<][>][^][v][top][bottom][index][help] */
2280                                 struct sockaddr_storage *server_ss,
2281                                 const struct user_auth_info *user_info)
2282 {
2283         struct cli_state *cli;
2284         NTSTATUS nt_status;
2285         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2286 
2287         if (user_info->use_kerberos) {
2288                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2289         }
2290 
2291         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
2292                                         user_info->username ? user_info->username : "",
2293                                         lp_workgroup(),
2294                                         user_info->password ? user_info->password : "",
2295                                         flags,
2296                                         Undefined, NULL);
2297 
2298         if (NT_STATUS_IS_OK(nt_status)) {
2299                 return cli;
2300         } else if (is_ipaddress(server)) {
2301             /* windows 9* needs a correct NMB name for connections */
2302             fstring remote_name;
2303 
2304             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2305                 cli = get_ipc_connect(remote_name, server_ss, user_info);
2306                 if (cli)
2307                     return cli;
2308             }
2309         }
2310         return NULL;
2311 }
2312 
2313 /*
2314  * Given the IP address of a master browser on the network, return its
2315  * workgroup and connect to it.
2316  *
2317  * This function is provided to allow additional processing beyond what
2318  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2319  * browsers and obtain each master browsers' list of domains (in case the
2320  * first master browser is recently on the network and has not yet
2321  * synchronized with other master browsers and therefore does not yet have the
2322  * entire network browse list)
2323  */
2324 
2325 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
2326                                 struct ip_service *mb_ip,
2327                                 const struct user_auth_info *user_info,
2328                                 char **pp_workgroup_out)
2329 {
2330         char addr[INET6_ADDRSTRLEN];
2331         fstring name;
2332         struct cli_state *cli;
2333         struct sockaddr_storage server_ss;
2334 
2335         *pp_workgroup_out = NULL;
2336 
2337         print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2338         DEBUG(99, ("Looking up name of master browser %s\n",
2339                    addr));
2340 
2341         /*
2342          * Do a name status query to find out the name of the master browser.
2343          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2344          * master browser will not respond to a wildcard query (or, at least,
2345          * an NT4 server acting as the domain master browser will not).
2346          *
2347          * We might be able to use ONLY the query on MSBROWSE, but that's not
2348          * yet been tested with all Windows versions, so until it is, leave
2349          * the original wildcard query as the first choice and fall back to
2350          * MSBROWSE if the wildcard query fails.
2351          */
2352         if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2353             !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2354 
2355                 DEBUG(99, ("Could not retrieve name status for %s\n",
2356                            addr));
2357                 return NULL;
2358         }
2359 
2360         if (!find_master_ip(name, &server_ss)) {
2361                 DEBUG(99, ("Could not find master ip for %s\n", name));
2362                 return NULL;
2363         }
2364 
2365         *pp_workgroup_out = talloc_strdup(ctx, name);
2366 
2367         DEBUG(4, ("found master browser %s, %s\n", name, addr));
2368 
2369         print_sockaddr(addr, sizeof(addr), &server_ss);
2370         cli = get_ipc_connect(addr, &server_ss, user_info);
2371 
2372         return cli;
2373 }
2374 
2375 /*
2376  * Return the IP address and workgroup of a master browser on the network, and
2377  * connect to it.
2378  */
2379 
2380 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
2381                                         const struct user_auth_info *user_info,
2382                                         char **pp_workgroup_out)
2383 {
2384         struct ip_service *ip_list;
2385         struct cli_state *cli;
2386         int i, count;
2387 
2388         *pp_workgroup_out = NULL;
2389 
2390         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2391 
2392         /* Go looking for workgroups by broadcasting on the local network */
2393 
2394         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2395                                                 &count))) {
2396                 DEBUG(99, ("No master browsers responded\n"));
2397                 return False;
2398         }
2399 
2400         for (i = 0; i < count; i++) {
2401                 char addr[INET6_ADDRSTRLEN];
2402                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2403                 DEBUG(99, ("Found master browser %s\n", addr));
2404 
2405                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2406                                 user_info, pp_workgroup_out);
2407                 if (cli)
2408                         return(cli);
2409         }
2410 
2411         return NULL;
2412 }

/* [<][>][^][v][top][bottom][index][help] */