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 2 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, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20*/ 21 22#define NO_SYSLOG 23 24#include "includes.h" 25 26 27static const struct { 28 int prot; 29 const char *name; 30} prots[] = { 31 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"}, 32 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"}, 33 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"}, 34 {PROTOCOL_LANMAN1,"LANMAN1.0"}, 35 {PROTOCOL_LANMAN2,"LM1.2X002"}, 36 {PROTOCOL_LANMAN2,"DOS LANMAN2.1"}, 37 {PROTOCOL_LANMAN2,"Samba"}, 38 {PROTOCOL_NT1,"NT LANMAN 1.0"}, 39 {PROTOCOL_NT1,"NT LM 0.12"}, 40 {-1,NULL} 41}; 42 43/** 44 * Set the user session key for a connection 45 * @param cli The cli structure to add it too 46 * @param session_key The session key used. (A copy of this is taken for the cli struct) 47 * 48 */ 49 50static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key) 51{ 52 cli->user_session_key = data_blob(session_key.data, session_key.length); 53} 54 55/**************************************************************************** 56 Do an old lanman2 style session setup. 57****************************************************************************/ 58 59static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user, 60 const char *pass, size_t passlen, const char *workgroup) 61{ 62 DATA_BLOB session_key = data_blob(NULL, 0); 63 DATA_BLOB lm_response = data_blob(NULL, 0); 64 fstring pword; 65 char *p; 66 67 if (passlen > sizeof(pword)-1) 68 return False; 69 70 /* LANMAN servers predate NT status codes and Unicode and ignore those 71 smb flags so we must disable the corresponding default capabilities 72 that would otherwise cause the Unicode and NT Status flags to be 73 set (and even returned by the server) */ 74 75 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32); 76 77 /* if in share level security then don't send a password now */ 78 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) 79 passlen = 0; 80 81 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) { 82 /* Encrypted mode needed, and non encrypted password supplied. */ 83 lm_response = data_blob(NULL, 24); 84 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) { 85 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n")); 86 return False; 87 } 88 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) { 89 /* Encrypted mode needed, and encrypted password supplied. */ 90 lm_response = data_blob(pass, passlen); 91 } else if (passlen > 0) { 92 /* Plaintext mode needed, assume plaintext supplied. */ 93 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE); 94 lm_response = data_blob(pass, passlen); 95 } 96 97 /* send a session setup command */ 98 memset(cli->outbuf,'\0',smb_size); 99 set_message(cli->outbuf,10, 0, True); 100 SCVAL(cli->outbuf,smb_com,SMBsesssetupX); 101 cli_setup_packet(cli); 102 103 SCVAL(cli->outbuf,smb_vwv0,0xFF); 104 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit); 105 SSVAL(cli->outbuf,smb_vwv3,2); 106 SSVAL(cli->outbuf,smb_vwv4,1); 107 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); 108 SSVAL(cli->outbuf,smb_vwv7,lm_response.length); 109 110 p = smb_buf(cli->outbuf); 111 memcpy(p,lm_response.data,lm_response.length); 112 p += lm_response.length; 113 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER); 114 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER); 115 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); 116 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE); 117 cli_setup_bcc(cli, p); 118 119 cli_send_smb(cli); 120 if (!cli_receive_smb(cli)) 121 return False; 122 123 show_msg(cli->inbuf); 124 125 if (cli_is_error(cli)) 126 return False; 127 128 /* use the returned vuid from now on */ 129 cli->vuid = SVAL(cli->inbuf,smb_uid); 130 fstrcpy(cli->user_name, user); 131 132 if (session_key.data) { 133 /* Have plaintext orginal */ 134 cli_set_session_key(cli, session_key); 135 } 136 137 return True; 138} 139 140/**************************************************************************** 141 Work out suitable capabilities to offer the server. 142****************************************************************************/ 143 144static uint32 cli_session_setup_capabilities(struct cli_state *cli) 145{ 146 uint32 capabilities = CAP_NT_SMBS; 147 148 if (!cli->force_dos_errors) 149 capabilities |= CAP_STATUS32; 150 151 if (cli->use_level_II_oplocks) 152 capabilities |= CAP_LEVEL_II_OPLOCKS; 153 154 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS)); 155 return capabilities; 156} 157 158/**************************************************************************** 159 Do a NT1 guest session setup. 160****************************************************************************/ 161 162static BOOL cli_session_setup_guest(struct cli_state *cli) 163{ 164 char *p; 165 uint32 capabilities = cli_session_setup_capabilities(cli); 166 167 set_message(cli->outbuf,13,0,True); 168 SCVAL(cli->outbuf,smb_com,SMBsesssetupX); 169 cli_setup_packet(cli); 170 171 SCVAL(cli->outbuf,smb_vwv0,0xFF); 172 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE); 173 SSVAL(cli->outbuf,smb_vwv3,2); 174 SSVAL(cli->outbuf,smb_vwv4,cli->pid); 175 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); 176 SSVAL(cli->outbuf,smb_vwv7,0); 177 SSVAL(cli->outbuf,smb_vwv8,0); 178 SIVAL(cli->outbuf,smb_vwv11,capabilities); 179 p = smb_buf(cli->outbuf); 180 p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */ 181 p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */ 182 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); 183 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE); 184 cli_setup_bcc(cli, p); 185 186 cli_send_smb(cli); 187 if (!cli_receive_smb(cli)) 188 return False; 189 190 show_msg(cli->inbuf); 191 192 if (cli_is_error(cli)) 193 return False; 194 195 cli->vuid = SVAL(cli->inbuf,smb_uid); 196 197 p = smb_buf(cli->inbuf); 198 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE); 199 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE); 200 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE); 201 202 fstrcpy(cli->user_name, ""); 203 204 return True; 205} 206 207/**************************************************************************** 208 Do a NT1 plaintext session setup. 209****************************************************************************/ 210 211static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user, 212 const char *pass, const char *workgroup) 213{ 214 uint32 capabilities = cli_session_setup_capabilities(cli); 215 char *p; 216 fstring lanman; 217 218 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING); 219 220 set_message(cli->outbuf,13,0,True); 221 SCVAL(cli->outbuf,smb_com,SMBsesssetupX); 222 cli_setup_packet(cli); 223 224 SCVAL(cli->outbuf,smb_vwv0,0xFF); 225 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE); 226 SSVAL(cli->outbuf,smb_vwv3,2); 227 SSVAL(cli->outbuf,smb_vwv4,cli->pid); 228 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); 229 SSVAL(cli->outbuf,smb_vwv8,0); 230 SIVAL(cli->outbuf,smb_vwv11,capabilities); 231 p = smb_buf(cli->outbuf); 232 233 /* check wether to send the ASCII or UNICODE version of the password */ 234 235 if ( (capabilities & CAP_UNICODE) == 0 ) { 236 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */ 237 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf))); 238 } 239 else { 240 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */ 241 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))); 242 } 243 244 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */ 245 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */ 246 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); 247 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE); 248 cli_setup_bcc(cli, p); 249 250 cli_send_smb(cli); 251 if (!cli_receive_smb(cli)) 252 return False; 253 254 show_msg(cli->inbuf); 255 256 if (cli_is_error(cli)) 257 return False; 258 259 cli->vuid = SVAL(cli->inbuf,smb_uid); 260 p = smb_buf(cli->inbuf); 261 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE); 262 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE); 263 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE); 264 fstrcpy(cli->user_name, user); 265 266 return True; 267} 268 269/**************************************************************************** 270 do a NT1 NTLM/LM encrypted session setup - for when extended security 271 is not negotiated. 272 @param cli client state to create do session setup on 273 @param user username 274 @param pass *either* cleartext password (passlen !=24) or LM response. 275 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear 276 @param workgroup The user's domain. 277****************************************************************************/ 278 279static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, 280 const char *pass, size_t passlen, 281 const char *ntpass, size_t ntpasslen, 282 const char *workgroup) 283{ 284 uint32 capabilities = cli_session_setup_capabilities(cli); 285 DATA_BLOB lm_response = data_blob(NULL, 0); 286 DATA_BLOB nt_response = data_blob(NULL, 0); 287 DATA_BLOB session_key = data_blob(NULL, 0); 288 BOOL ret = False; 289 char *p; 290 291 if (passlen == 0) { 292 /* do nothing - guest login */ 293 } else if (passlen != 24) { 294 if (lp_client_ntlmv2_auth()) { 295 DATA_BLOB server_chal; 296 DATA_BLOB names_blob; 297 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); 298 299 /* note that the 'workgroup' here is a best guess - we don't know 300 the server's domain at this point. The 'server name' is also 301 dodgy... 302 */ 303 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup); 304 305 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal, 306 &names_blob, 307 &lm_response, &nt_response, &session_key)) { 308 data_blob_free(&names_blob); 309 data_blob_free(&server_chal); 310 return False; 311 } 312 data_blob_free(&names_blob); 313 data_blob_free(&server_chal); 314 315 } else { 316 uchar nt_hash[16]; 317 E_md4hash(pass, nt_hash); 318 319#ifdef LANMAN_ONLY 320 nt_response = data_blob(NULL, 0); 321#else 322 nt_response = data_blob(NULL, 24); 323 SMBNTencrypt(pass,cli->secblob.data,nt_response.data); 324#endif 325 /* non encrypted password supplied. Ignore ntpass. */ 326 if (lp_client_lanman_auth()) { 327 lm_response = data_blob(NULL, 24); 328 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) { 329 /* Oops, the LM response is invalid, just put 330 the NT response there instead */ 331 data_blob_free(&lm_response); 332 lm_response = data_blob(nt_response.data, nt_response.length); 333 } 334 } else { 335 /* LM disabled, place NT# in LM field instead */ 336 lm_response = data_blob(nt_response.data, nt_response.length); 337 } 338 339 session_key = data_blob(NULL, 16); 340#ifdef LANMAN_ONLY 341 E_deshash(pass, session_key.data); 342 memset(&session_key.data[8], '\0', 8); 343#else 344 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); 345#endif 346 } 347#ifdef LANMAN_ONLY 348 cli_simple_set_signing(cli, session_key, lm_response); 349#else 350 cli_simple_set_signing(cli, session_key, nt_response); 351#endif 352 } else { 353 /* pre-encrypted password supplied. Only used for 354 security=server, can't do 355 signing because we don't have original key */ 356 357 lm_response = data_blob(pass, passlen); 358 nt_response = data_blob(ntpass, ntpasslen); 359 } 360 361 /* send a session setup command */ 362 memset(cli->outbuf,'\0',smb_size); 363 364 set_message(cli->outbuf,13,0,True); 365 SCVAL(cli->outbuf,smb_com,SMBsesssetupX); 366 cli_setup_packet(cli); 367 368 SCVAL(cli->outbuf,smb_vwv0,0xFF); 369 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE); 370 SSVAL(cli->outbuf,smb_vwv3,2); 371 SSVAL(cli->outbuf,smb_vwv4,cli->pid); 372 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); 373 SSVAL(cli->outbuf,smb_vwv7,lm_response.length); 374 SSVAL(cli->outbuf,smb_vwv8,nt_response.length); 375 SIVAL(cli->outbuf,smb_vwv11,capabilities); 376 p = smb_buf(cli->outbuf); 377 if (lm_response.length) { 378 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length; 379 } 380 if (nt_response.length) { 381 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length; 382 } 383 p += clistr_push(cli, p, user, -1, STR_TERMINATE); 384 385 /* Upper case here might help some NTLMv2 implementations */ 386 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER); 387 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); 388 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE); 389 cli_setup_bcc(cli, p); 390 391 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) { 392 ret = False; 393 goto end; 394 } 395 396 /* show_msg(cli->inbuf); */ 397 398 if (cli_is_error(cli)) { 399 ret = False; 400 goto end; 401 } 402 403 /* use the returned vuid from now on */ 404 cli->vuid = SVAL(cli->inbuf,smb_uid); 405 406 p = smb_buf(cli->inbuf); 407 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE); 408 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE); 409 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE); 410 411 fstrcpy(cli->user_name, user); 412 413 if (session_key.data) { 414 /* Have plaintext orginal */ 415 cli_set_session_key(cli, session_key); 416 } 417 418 ret = True; 419end: 420 data_blob_free(&lm_response); 421 data_blob_free(&nt_response); 422 data_blob_free(&session_key); 423 return ret; 424} 425 426/**************************************************************************** 427 Send a extended security session setup blob 428****************************************************************************/ 429 430static BOOL cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob) 431{ 432 uint32 capabilities = cli_session_setup_capabilities(cli); 433 char *p; 434 435 capabilities |= CAP_EXTENDED_SECURITY; 436 437 /* send a session setup command */ 438 memset(cli->outbuf,'\0',smb_size); 439 440 set_message(cli->outbuf,12,0,True); 441 SCVAL(cli->outbuf,smb_com,SMBsesssetupX); 442 443 cli_setup_packet(cli); 444 445 SCVAL(cli->outbuf,smb_vwv0,0xFF); 446 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE); 447 SSVAL(cli->outbuf,smb_vwv3,2); 448 SSVAL(cli->outbuf,smb_vwv4,1); 449 SIVAL(cli->outbuf,smb_vwv5,0); 450 SSVAL(cli->outbuf,smb_vwv7,blob.length); 451 SIVAL(cli->outbuf,smb_vwv10,capabilities); 452 p = smb_buf(cli->outbuf); 453 memcpy(p, blob.data, blob.length); 454 p += blob.length; 455 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); 456 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE); 457 cli_setup_bcc(cli, p); 458 return cli_send_smb(cli); 459} 460 461/**************************************************************************** 462 Send a extended security session setup blob, returning a reply blob. 463****************************************************************************/ 464 465static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli) 466{ 467 DATA_BLOB blob2 = data_blob(NULL, 0); 468 char *p; 469 size_t len; 470 471 if (!cli_receive_smb(cli)) 472 return blob2; 473 474 show_msg(cli->inbuf); 475 476 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli), 477 NT_STATUS_MORE_PROCESSING_REQUIRED)) { 478 return blob2; 479 } 480 481 /* use the returned vuid from now on */ 482 cli->vuid = SVAL(cli->inbuf,smb_uid); 483 484 p = smb_buf(cli->inbuf); 485 486 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3)); 487 488 p += blob2.length; 489 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE); 490 491 /* w2k with kerberos doesn't properly null terminate this field */ 492 len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf)); 493 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0); 494 495 return blob2; 496} 497 498#ifdef HAVE_KRB5 499 500/**************************************************************************** 501 Send a extended security session setup blob, returning a reply blob. 502****************************************************************************/ 503 504static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob) 505{ 506 DATA_BLOB blob2 = data_blob(NULL, 0); 507 if (!cli_session_setup_blob_send(cli, blob)) { 508 return blob2; 509 } 510 511 return cli_session_setup_blob_receive(cli); 512} 513 514/**************************************************************************** 515 Use in-memory credentials cache 516****************************************************************************/ 517 518static void use_in_memory_ccache(void) { 519 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1); 520} 521 522/**************************************************************************** 523 Do a spnego/kerberos encrypted session setup. 524****************************************************************************/ 525 526static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup) 527{ 528 DATA_BLOB blob2, negTokenTarg; 529 DATA_BLOB session_key_krb5; 530 DATA_BLOB null_blob = data_blob(NULL, 0); 531 int rc; 532 533 DEBUG(2,("Doing kerberos session setup\n")); 534 535 /* generate the encapsulated kerberos5 ticket */ 536 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5); 537 538 if (rc) { 539 DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc))); 540 return ADS_ERROR_KRB5(rc); 541 } 542 543#if 0 544 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length); 545#endif 546 547 cli_simple_set_signing(cli, session_key_krb5, null_blob); 548 549 blob2 = cli_session_setup_blob(cli, negTokenTarg); 550 551 /* we don't need this blob for kerberos */ 552 data_blob_free(&blob2); 553 554 cli_set_session_key(cli, session_key_krb5); 555 556 data_blob_free(&negTokenTarg); 557 data_blob_free(&session_key_krb5); 558 559 if (cli_is_error(cli)) { 560 if (NT_STATUS_IS_OK(cli_nt_error(cli))) { 561 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); 562 } 563 } 564 return ADS_ERROR_NT(cli_nt_error(cli)); 565} 566#endif /* HAVE_KRB5 */ 567 568 569/**************************************************************************** 570 Do a spnego/NTLMSSP encrypted session setup. 571****************************************************************************/ 572 573static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, 574 const char *pass, const char *domain) 575{ 576 struct ntlmssp_state *ntlmssp_state; 577 NTSTATUS nt_status; 578 int turn = 1; 579 DATA_BLOB msg1; 580 DATA_BLOB blob = data_blob(NULL, 0); 581 DATA_BLOB blob_in = data_blob(NULL, 0); 582 DATA_BLOB blob_out = data_blob(NULL, 0); 583 584 cli_temp_set_signing(cli); 585 586 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) { 587 return nt_status; 588 } 589 590 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) { 591 return nt_status; 592 } 593 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) { 594 return nt_status; 595 } 596 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) { 597 return nt_status; 598 } 599 600 do { 601 nt_status = ntlmssp_update(ntlmssp_state, 602 blob_in, &blob_out); 603 data_blob_free(&blob_in); 604 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 605 if (turn == 1) { 606 /* and wrap it in a SPNEGO wrapper */ 607 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out); 608 } else { 609 /* wrap it in SPNEGO */ 610 msg1 = spnego_gen_auth(blob_out); 611 } 612 613 /* now send that blob on its way */ 614 if (!cli_session_setup_blob_send(cli, msg1)) { 615 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n")); 616 nt_status = NT_STATUS_UNSUCCESSFUL; 617 } else { 618 data_blob_free(&msg1); 619 620 blob = cli_session_setup_blob_receive(cli); 621 622 nt_status = cli_nt_error(cli); 623 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) { 624 if (cli->smb_rw_error == READ_BAD_SIG) { 625 nt_status = NT_STATUS_ACCESS_DENIED; 626 } else { 627 nt_status = NT_STATUS_UNSUCCESSFUL; 628 } 629 } 630 } 631 } 632 633 if (!blob.length) { 634 if (NT_STATUS_IS_OK(nt_status)) { 635 nt_status = NT_STATUS_UNSUCCESSFUL; 636 } 637 } else if ((turn == 1) && 638 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 639 DATA_BLOB tmp_blob = data_blob(NULL, 0); 640 /* the server might give us back two challenges */ 641 if (!spnego_parse_challenge(blob, &blob_in, 642 &tmp_blob)) { 643 DEBUG(3,("Failed to parse challenges\n")); 644 nt_status = NT_STATUS_INVALID_PARAMETER; 645 } 646 data_blob_free(&tmp_blob); 647 } else { 648 if (!spnego_parse_auth_response(blob, nt_status, 649 &blob_in)) { 650 DEBUG(3,("Failed to parse auth response\n")); 651 if (NT_STATUS_IS_OK(nt_status) 652 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) 653 nt_status = NT_STATUS_INVALID_PARAMETER; 654 } 655 } 656 data_blob_free(&blob); 657 data_blob_free(&blob_out); 658 turn++; 659 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)); 660 661 if (NT_STATUS_IS_OK(nt_status)) { 662 663 DATA_BLOB key = data_blob(ntlmssp_state->session_key.data, 664 ntlmssp_state->session_key.length); 665 DATA_BLOB null_blob = data_blob(NULL, 0); 666 BOOL res; 667 668 fstrcpy(cli->server_domain, ntlmssp_state->server_domain); 669 cli_set_session_key(cli, ntlmssp_state->session_key); 670 671 res = cli_simple_set_signing(cli, key, null_blob); 672 673 data_blob_free(&key); 674 675 if (res) { 676 677 /* 'resign' the last message, so we get the right sequence numbers 678 for checking the first reply from the server */ 679 cli_calculate_sign_mac(cli); 680 681 if (!cli_check_sign_mac(cli)) { 682 nt_status = NT_STATUS_ACCESS_DENIED; 683 } 684 } 685 } 686 687 /* we have a reference conter on ntlmssp_state, if we are signing 688 then the state will be kept by the signing engine */ 689 690 ntlmssp_end(&ntlmssp_state); 691 692 return nt_status; 693} 694 695/**************************************************************************** 696 Do a spnego encrypted session setup. 697****************************************************************************/ 698 699ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 700 const char *pass, const char *domain) 701{ 702 char *principal; 703 char *OIDs[ASN1_MAX_OIDS]; 704 int i; 705 BOOL got_kerberos_mechanism = False; 706 DATA_BLOB blob; 707 708 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length)); 709 710 /* the server might not even do spnego */ 711 if (cli->secblob.length <= 16) { 712 DEBUG(3,("server didn't supply a full spnego negprot\n")); 713 goto ntlmssp; 714 } 715 716#if 0 717 file_save("negprot.dat", cli->secblob.data, cli->secblob.length); 718#endif 719 720 /* there is 16 bytes of GUID before the real spnego packet starts */ 721 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16); 722 723 /* the server sent us the first part of the SPNEGO exchange in the negprot 724 reply */ 725 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) { 726 data_blob_free(&blob); 727 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); 728 } 729 data_blob_free(&blob); 730 731 /* make sure the server understands kerberos */ 732 for (i=0;OIDs[i];i++) { 733 DEBUG(3,("got OID=%s\n", OIDs[i])); 734 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 || 735 strcmp(OIDs[i], OID_KERBEROS5) == 0) { 736 got_kerberos_mechanism = True; 737 } 738 free(OIDs[i]); 739 } 740 DEBUG(3,("got principal=%s\n", principal)); 741 742 fstrcpy(cli->user_name, user); 743 744#ifdef HAVE_KRB5 745 /* If password is set we reauthenticate to kerberos server 746 * and do not store results */ 747 748 if (got_kerberos_mechanism && cli->use_kerberos) { 749 ADS_STATUS rc; 750 751 if (pass && *pass) { 752 int ret; 753 754 use_in_memory_ccache(); 755 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL, NULL); 756 757 if (ret){ 758 SAFE_FREE(principal); 759 DEBUG(0, ("Kinit failed: %s\n", error_message(ret))); 760 if (cli->fallback_after_kerberos) 761 goto ntlmssp; 762 return ADS_ERROR_KRB5(ret); 763 } 764 } 765 766 rc = cli_session_setup_kerberos(cli, principal, domain); 767 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) { 768 SAFE_FREE(principal); 769 return rc; 770 } 771 } 772#endif 773 774 SAFE_FREE(principal); 775 776ntlmssp: 777 778 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass, domain)); 779} 780 781/**************************************************************************** 782 Send a session setup. The username and workgroup is in UNIX character 783 format and must be converted to DOS codepage format before sending. If the 784 password is in plaintext, the same should be done. 785****************************************************************************/ 786 787BOOL cli_session_setup(struct cli_state *cli, 788 const char *user, 789 const char *pass, int passlen, 790 const char *ntpass, int ntpasslen, 791 const char *workgroup) 792{ 793 char *p; 794 fstring user2; 795 796 /* allow for workgroups as part of the username */ 797 fstrcpy(user2, user); 798 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) || 799 (p=strchr_m(user2,*lp_winbind_separator()))) { 800 *p = 0; 801 user = p+1; 802 workgroup = user2; 803 } 804 805 if (cli->protocol < PROTOCOL_LANMAN1) 806 return True; 807 808 /* now work out what sort of session setup we are going to 809 do. I have split this into separate functions to make the 810 flow a bit easier to understand (tridge) */ 811 812 /* if its an older server then we have to use the older request format */ 813 814 if (cli->protocol < PROTOCOL_NT1) { 815 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) { 816 DEBUG(1, ("Server requested LM password but 'client lanman auth'" 817 " is disabled\n")); 818 return False; 819 } 820 821 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 && 822 !lp_client_plaintext_auth() && (*pass)) { 823 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'" 824 " is disabled\n")); 825 return False; 826 } 827 828 return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup); 829 } 830 831 /* if no user is supplied then we have to do an anonymous connection. 832 passwords are ignored */ 833 834 if (!user || !*user) 835 return cli_session_setup_guest(cli); 836 837 /* if the server is share level then send a plaintext null 838 password at this point. The password is sent in the tree 839 connect */ 840 841 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 842 return cli_session_setup_plaintext(cli, user, "", workgroup); 843 844 /* if the server doesn't support encryption then we have to use 845 plaintext. The second password is ignored */ 846 847 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) { 848 if (!lp_client_plaintext_auth() && (*pass)) { 849 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'" 850 " is disabled\n")); 851 return False; 852 } 853 return cli_session_setup_plaintext(cli, user, pass, workgroup); 854 } 855 856 /* if the server supports extended security then use SPNEGO */ 857 858 if (cli->capabilities & CAP_EXTENDED_SECURITY) { 859 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup); 860 if (!ADS_ERR_OK(status)) { 861 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status))); 862 return False; 863 } 864 return True; 865 } 866 867 /* otherwise do a NT1 style session setup */ 868 869 return cli_session_setup_nt1(cli, user, 870 pass, passlen, ntpass, ntpasslen, 871 workgroup); 872} 873 874/**************************************************************************** 875 Send a uloggoff. 876*****************************************************************************/ 877 878BOOL cli_ulogoff(struct cli_state *cli) 879{ 880 memset(cli->outbuf,'\0',smb_size); 881 set_message(cli->outbuf,2,0,True); 882 SCVAL(cli->outbuf,smb_com,SMBulogoffX); 883 cli_setup_packet(cli); 884 SSVAL(cli->outbuf,smb_vwv0,0xFF); 885 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */ 886 887 cli_send_smb(cli); 888 if (!cli_receive_smb(cli)) 889 return False; 890 891 if (cli_is_error(cli)) { 892 return False; 893 } 894 895 cli->cnum = -1; 896 return True; 897} 898 899/**************************************************************************** 900 Send a tconX. 901****************************************************************************/ 902BOOL cli_send_tconX(struct cli_state *cli, 903 const char *share, const char *dev, const char *pass, int passlen) 904{ 905 fstring fullshare, pword; 906 char *p; 907 memset(cli->outbuf,'\0',smb_size); 908 memset(cli->inbuf,'\0',smb_size); 909 910 fstrcpy(cli->share, share); 911 912 /* in user level security don't send a password now */ 913 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) { 914 passlen = 1; 915 pass = ""; 916 } 917 918 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) { 919 if (!lp_client_lanman_auth()) { 920 DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'" 921 " is disabled\n")); 922 return False; 923 } 924 925 /* 926 * Non-encrypted passwords - convert to DOS codepage before encryption. 927 */ 928 passlen = 24; 929 SMBencrypt(pass,cli->secblob.data,(uchar *)pword); 930 } else { 931 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) { 932 if (!lp_client_plaintext_auth() && (*pass)) { 933 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'" 934 " is disabled\n")); 935 return False; 936 } 937 938 /* 939 * Non-encrypted passwords - convert to DOS codepage before using. 940 */ 941 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE); 942 943 } else { 944 memcpy(pword, pass, passlen); 945 } 946 } 947 948 slprintf(fullshare, sizeof(fullshare)-1, 949 "\\\\%s\\%s", cli->desthost, share); 950 951 set_message(cli->outbuf,4, 0, True); 952 SCVAL(cli->outbuf,smb_com,SMBtconX); 953 cli_setup_packet(cli); 954 955 SSVAL(cli->outbuf,smb_vwv0,0xFF); 956 SSVAL(cli->outbuf,smb_vwv3,passlen); 957 958 p = smb_buf(cli->outbuf); 959 memcpy(p,pword,passlen); 960 p += passlen; 961 p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER); 962 p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII); 963 964 cli_setup_bcc(cli, p); 965 966 cli_send_smb(cli); 967 if (!cli_receive_smb(cli)) 968 return False; 969 970 if (cli_is_error(cli)) 971 return False; 972 973 clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII); 974 975 if (cli->protocol >= PROTOCOL_NT1 && 976 smb_buflen(cli->inbuf) == 3) { 977 /* almost certainly win95 - enable bug fixes */ 978 cli->win95 = True; 979 } 980 981 /* Make sure that we have the optional support 16-bit field. WCT > 2 */ 982 /* Avoids issues when connecting to Win9x boxes sharing files */ 983 984 cli->dfsroot = False; 985 if ( (CVAL(cli->inbuf, smb_wct))>2 && cli->protocol >= PROTOCOL_LANMAN2 ) 986 cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS) ? True : False; 987 988 cli->cnum = SVAL(cli->inbuf,smb_tid); 989 return True; 990} 991 992/**************************************************************************** 993 Send a tree disconnect. 994****************************************************************************/ 995 996BOOL cli_tdis(struct cli_state *cli) 997{ 998 memset(cli->outbuf,'\0',smb_size); 999 set_message(cli->outbuf,0,0,True); 1000 SCVAL(cli->outbuf,smb_com,SMBtdis); 1001 SSVAL(cli->outbuf,smb_tid,cli->cnum); 1002 cli_setup_packet(cli); 1003 1004 cli_send_smb(cli); 1005 if (!cli_receive_smb(cli)) 1006 return False; 1007 1008 if (cli_is_error(cli)) { 1009 return False; 1010 } 1011 1012 cli->cnum = -1; 1013 return True; 1014} 1015 1016/**************************************************************************** 1017 Send a negprot command. 1018****************************************************************************/ 1019 1020void cli_negprot_send(struct cli_state *cli) 1021{ 1022 char *p; 1023 int numprots; 1024 1025 if (cli->protocol < PROTOCOL_NT1) 1026 cli->use_spnego = False; 1027 1028 memset(cli->outbuf,'\0',smb_size); 1029 1030 /* setup the protocol strings */ 1031 set_message(cli->outbuf,0,0,True); 1032 1033 p = smb_buf(cli->outbuf); 1034 for (numprots=0; 1035 prots[numprots].name && prots[numprots].prot<=cli->protocol; 1036 numprots++) { 1037 *p++ = 2; 1038 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE); 1039 } 1040 1041 SCVAL(cli->outbuf,smb_com,SMBnegprot); 1042 cli_setup_bcc(cli, p); 1043 cli_setup_packet(cli); 1044 1045 SCVAL(smb_buf(cli->outbuf),0,2); 1046 1047 cli_send_smb(cli); 1048} 1049 1050/**************************************************************************** 1051 Send a negprot command. 1052****************************************************************************/ 1053 1054BOOL cli_negprot(struct cli_state *cli) 1055{ 1056 char *p; 1057 int numprots; 1058 int plength; 1059 1060 if (cli->protocol < PROTOCOL_NT1) 1061 cli->use_spnego = False; 1062 1063 memset(cli->outbuf,'\0',smb_size); 1064 1065 /* setup the protocol strings */ 1066 for (plength=0,numprots=0; 1067 prots[numprots].name && prots[numprots].prot<=cli->protocol; 1068 numprots++) 1069 plength += strlen(prots[numprots].name)+2; 1070 1071 set_message(cli->outbuf,0,plength,True); 1072 1073 p = smb_buf(cli->outbuf); 1074 for (numprots=0; 1075 prots[numprots].name && prots[numprots].prot<=cli->protocol; 1076 numprots++) { 1077 *p++ = 2; 1078 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE); 1079 } 1080 1081 SCVAL(cli->outbuf,smb_com,SMBnegprot); 1082 cli_setup_packet(cli); 1083 1084 SCVAL(smb_buf(cli->outbuf),0,2); 1085 1086 cli_send_smb(cli); 1087 if (!cli_receive_smb(cli)) 1088 return False; 1089 1090 show_msg(cli->inbuf); 1091 1092 if (cli_is_error(cli) || 1093 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) { 1094 return(False); 1095 } 1096 1097 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot; 1098 1099 if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) { 1100 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n")); 1101 return False; 1102 } 1103 1104 if (cli->protocol >= PROTOCOL_NT1) { 1105 /* NT protocol */ 1106 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1); 1107 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1); 1108 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1); 1109 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1); 1110 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1); 1111 cli->serverzone *= 60; 1112 /* this time arrives in real GMT */ 1113 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1); 1114 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf)); 1115 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1); 1116 if (cli->capabilities & CAP_RAW_MODE) { 1117 cli->readbraw_supported = True; 1118 cli->writebraw_supported = True; 1119 } 1120 /* work out if they sent us a workgroup */ 1121 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) && 1122 smb_buflen(cli->inbuf) > 8) { 1123 clistr_pull(cli, cli->server_domain, 1124 smb_buf(cli->inbuf)+8, sizeof(cli->server_domain), 1125 smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN); 1126 } 1127 1128 /* 1129 * As signing is slow we only turn it on if either the client or 1130 * the server require it. JRA. 1131 */ 1132 1133 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) { 1134 /* Fail if server says signing is mandatory and we don't want to support it. */ 1135 if (!cli->sign_info.allow_smb_signing) { 1136 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n")); 1137 return False; 1138 } 1139 cli->sign_info.negotiated_smb_signing = True; 1140 cli->sign_info.mandatory_signing = True; 1141 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) { 1142 /* Fail if client says signing is mandatory and the server doesn't support it. */ 1143 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) { 1144 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n")); 1145 return False; 1146 } 1147 cli->sign_info.negotiated_smb_signing = True; 1148 cli->sign_info.mandatory_signing = True; 1149 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) { 1150 cli->sign_info.negotiated_smb_signing = True; 1151 } 1152 1153 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) { 1154 SAFE_FREE(cli->outbuf); 1155 SAFE_FREE(cli->inbuf); 1156 cli->outbuf = (char *)SMB_MALLOC(CLI_MAX_LARGE_READX_SIZE+SAFETY_MARGIN); 1157 cli->inbuf = (char *)SMB_MALLOC(CLI_MAX_LARGE_READX_SIZE+SAFETY_MARGIN); 1158 cli->bufsize = CLI_MAX_LARGE_READX_SIZE; 1159 } 1160 1161 } else if (cli->protocol >= PROTOCOL_LANMAN1) { 1162 cli->use_spnego = False; 1163 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1); 1164 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2); 1165 cli->max_mux = SVAL(cli->inbuf, smb_vwv3); 1166 cli->sesskey = IVAL(cli->inbuf,smb_vwv6); 1167 cli->serverzone = SVALS(cli->inbuf,smb_vwv10); 1168 cli->serverzone *= 60; 1169 /* this time is converted to GMT by make_unix_date */ 1170 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8); 1171 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0); 1172 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0); 1173 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf)); 1174 } else { 1175 /* the old core protocol */ 1176 cli->use_spnego = False; 1177 cli->sec_mode = 0; 1178 cli->serverzone = TimeDiff(time(NULL)); 1179 } 1180 1181 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE); 1182 1183 /* a way to force ascii SMB */ 1184 if (getenv("CLI_FORCE_ASCII")) 1185 cli->capabilities &= ~CAP_UNICODE; 1186 1187 return True; 1188} 1189 1190/**************************************************************************** 1191 Send a session request. See rfc1002.txt 4.3 and 4.3.2. 1192****************************************************************************/ 1193 1194BOOL cli_session_request(struct cli_state *cli, 1195 struct nmb_name *calling, struct nmb_name *called) 1196{ 1197 char *p; 1198 int len = 4; 1199 extern pstring user_socket_options; 1200 1201 memcpy(&(cli->calling), calling, sizeof(*calling)); 1202 memcpy(&(cli->called ), called , sizeof(*called )); 1203 1204 /* put in the destination name */ 1205 p = cli->outbuf+len; 1206 name_mangle(cli->called .name, p, cli->called .name_type); 1207 len += name_len(p); 1208 1209 /* and my name */ 1210 p = cli->outbuf+len; 1211 name_mangle(cli->calling.name, p, cli->calling.name_type); 1212 len += name_len(p); 1213 1214 /* 445 doesn't have session request */ 1215 if (cli->port == 445) 1216 return True; 1217 1218 /* send a session request (RFC 1002) */ 1219 /* setup the packet length 1220 * Remove four bytes from the length count, since the length 1221 * field in the NBT Session Service header counts the number 1222 * of bytes which follow. The cli_send_smb() function knows 1223 * about this and accounts for those four bytes. 1224 * CRH. 1225 */ 1226 len -= 4; 1227 _smb_setlen(cli->outbuf,len); 1228 SCVAL(cli->outbuf,0,0x81); 1229 1230 cli_send_smb(cli); 1231 DEBUG(5,("Sent session request\n")); 1232 1233 if (!cli_receive_smb(cli)) 1234 return False; 1235 1236 if (CVAL(cli->inbuf,0) == 0x84) { 1237 /* C. Hoch 9/14/95 Start */ 1238 /* For information, here is the response structure. 1239 * We do the byte-twiddling to for portability. 1240 struct RetargetResponse{ 1241 unsigned char type; 1242 unsigned char flags; 1243 int16 length; 1244 int32 ip_addr; 1245 int16 port; 1246 }; 1247 */ 1248 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9); 1249 /* SESSION RETARGET */ 1250 putip((char *)&cli->dest_ip,cli->inbuf+4); 1251 1252 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT); 1253 if (cli->fd == -1) 1254 return False; 1255 1256 DEBUG(3,("Retargeted\n")); 1257 1258 set_socket_options(cli->fd,user_socket_options); 1259 1260 /* Try again */ 1261 { 1262 static int depth; 1263 BOOL ret; 1264 if (depth > 4) { 1265 DEBUG(0,("Retarget recursion - failing\n")); 1266 return False; 1267 } 1268 depth++; 1269 ret = cli_session_request(cli, calling, called); 1270 depth--; 1271 return ret; 1272 } 1273 } /* C. Hoch 9/14/95 End */ 1274 1275 if (CVAL(cli->inbuf,0) != 0x82) { 1276 /* This is the wrong place to put the error... JRA. */ 1277 cli->rap_error = CVAL(cli->inbuf,4); 1278 return False; 1279 } 1280 return(True); 1281} 1282 1283/**************************************************************************** 1284 Open the client sockets. 1285****************************************************************************/ 1286 1287BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) 1288{ 1289 extern pstring user_socket_options; 1290 int name_type = 0x20; 1291 char *p; 1292 1293 /* reasonable default hostname */ 1294 if (!host) host = "*SMBSERVER"; 1295 1296 fstrcpy(cli->desthost, host); 1297 1298 /* allow hostnames of the form NAME#xx and do a netbios lookup */ 1299 if ((p = strchr(cli->desthost, '#'))) { 1300 name_type = strtol(p+1, NULL, 16); 1301 *p = 0; 1302 } 1303 1304 if (!ip || is_zero_ip(*ip)) { 1305 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) { 1306 return False; 1307 } 1308 if (ip) *ip = cli->dest_ip; 1309 } else { 1310 cli->dest_ip = *ip; 1311 } 1312 1313 if (getenv("LIBSMB_PROG")) { 1314 cli->fd = sock_exec(getenv("LIBSMB_PROG")); 1315 } else { 1316 /* try 445 first, then 139 */ 1317 int port = cli->port?cli->port:445; 1318 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 1319 port, cli->timeout); 1320 if (cli->fd == -1 && cli->port == 0) { 1321 port = 139; 1322 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 1323 port, cli->timeout); 1324 } 1325 if (cli->fd != -1) 1326 cli->port = port; 1327 } 1328 if (cli->fd == -1) { 1329 DEBUG(1,("Error connecting to %s (%s)\n", 1330 ip?inet_ntoa(*ip):host,strerror(errno))); 1331 return False; 1332 } 1333 1334 set_socket_options(cli->fd,user_socket_options); 1335 1336 return True; 1337} 1338 1339/**************************************************************************** 1340 Initialise client credentials for authenticated pipe access. 1341****************************************************************************/ 1342 1343void init_creds(struct ntuser_creds *creds, const char* username, 1344 const char* domain, const char* password) 1345{ 1346 ZERO_STRUCTP(creds); 1347 1348 pwd_set_cleartext(&creds->pwd, password); 1349 1350 fstrcpy(creds->user_name, username); 1351 fstrcpy(creds->domain, domain); 1352 1353 if (!*username) { 1354 creds->pwd.null_pwd = True; 1355 } 1356} 1357 1358/** 1359 establishes a connection to after the negprot. 1360 @param output_cli A fully initialised cli structure, non-null only on success 1361 @param dest_host The netbios name of the remote host 1362 @param dest_ip (optional) The the destination IP, NULL for name based lookup 1363 @param port (optional) The destination port (0 for default) 1364 @param retry BOOL. Did this connection fail with a retryable error ? 1365 1366*/ 1367NTSTATUS cli_start_connection(struct cli_state **output_cli, 1368 const char *my_name, 1369 const char *dest_host, 1370 struct in_addr *dest_ip, int port, 1371 int signing_state, int flags, 1372 BOOL *retry) 1373{ 1374 NTSTATUS nt_status; 1375 struct nmb_name calling; 1376 struct nmb_name called; 1377 struct cli_state *cli; 1378 struct in_addr ip; 1379 1380 if (retry) 1381 *retry = False; 1382 1383 if (!my_name) 1384 my_name = global_myname(); 1385 1386 if (!(cli = cli_initialise(NULL))) 1387 return NT_STATUS_NO_MEMORY; 1388 1389 make_nmb_name(&calling, my_name, 0x0); 1390 make_nmb_name(&called , dest_host, 0x20); 1391 1392 if (cli_set_port(cli, port) != port) { 1393 cli_shutdown(cli); 1394 return NT_STATUS_UNSUCCESSFUL; 1395 } 1396 1397 cli_set_timeout(cli, 10000); /* 10 seconds. */ 1398 1399 if (dest_ip) 1400 ip = *dest_ip; 1401 else 1402 ZERO_STRUCT(ip); 1403 1404again: 1405 1406 DEBUG(3,("Connecting to host=%s\n", dest_host)); 1407 1408 if (!cli_connect(cli, dest_host, &ip)) { 1409 DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n", 1410 nmb_namestr(&called), inet_ntoa(ip))); 1411 cli_shutdown(cli); 1412 return NT_STATUS_UNSUCCESSFUL; 1413 } 1414 1415 if (retry) 1416 *retry = True; 1417 1418 if (!cli_session_request(cli, &calling, &called)) { 1419 char *p; 1420 DEBUG(1,("session request to %s failed (%s)\n", 1421 called.name, cli_errstr(cli))); 1422 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) { 1423 *p = 0; 1424 goto again; 1425 } 1426 if (strcmp(called.name, "*SMBSERVER")) { 1427 make_nmb_name(&called , "*SMBSERVER", 0x20); 1428 goto again; 1429 } 1430 return NT_STATUS_UNSUCCESSFUL; 1431 } 1432 1433 cli_setup_signing_state(cli, signing_state); 1434 1435 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO) 1436 cli->use_spnego = False; 1437 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) 1438 cli->use_kerberos = True; 1439 1440 if (!cli_negprot(cli)) { 1441 DEBUG(1,("failed negprot\n")); 1442 nt_status = NT_STATUS_UNSUCCESSFUL; 1443 cli_shutdown(cli); 1444 return nt_status; 1445 } 1446 1447 *output_cli = cli; 1448 return NT_STATUS_OK; 1449} 1450 1451 1452/** 1453 establishes a connection right up to doing tconX, password specified. 1454 @param output_cli A fully initialised cli structure, non-null only on success 1455 @param dest_host The netbios name of the remote host 1456 @param dest_ip (optional) The the destination IP, NULL for name based lookup 1457 @param port (optional) The destination port (0 for default) 1458 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way. 1459 @param service_type The 'type' of serivice. 1460 @param user Username, unix string 1461 @param domain User's domain 1462 @param password User's password, unencrypted unix string. 1463 @param retry BOOL. Did this connection fail with a retryable error ? 1464*/ 1465 1466NTSTATUS cli_full_connection(struct cli_state **output_cli, 1467 const char *my_name, 1468 const char *dest_host, 1469 struct in_addr *dest_ip, int port, 1470 const char *service, const char *service_type, 1471 const char *user, const char *domain, 1472 const char *password, int flags, 1473 int signing_state, 1474 BOOL *retry) 1475{ 1476 struct ntuser_creds creds; 1477 NTSTATUS nt_status; 1478 struct cli_state *cli = NULL; 1479 1480 nt_status = cli_start_connection(&cli, my_name, dest_host, 1481 dest_ip, port, signing_state, flags, retry); 1482 1483 if (!NT_STATUS_IS_OK(nt_status)) { 1484 return nt_status; 1485 } 1486 1487 if (!cli_session_setup(cli, user, password, strlen(password)+1, 1488 password, strlen(password)+1, 1489 domain)) { 1490 if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK) 1491 && cli_session_setup(cli, "", "", 0, "", 0, domain)) { 1492 } else { 1493 nt_status = cli_nt_error(cli); 1494 DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status))); 1495 cli_shutdown(cli); 1496 if (NT_STATUS_IS_OK(nt_status)) 1497 nt_status = NT_STATUS_UNSUCCESSFUL; 1498 return nt_status; 1499 } 1500 } 1501 1502 if (service) { 1503 if (!cli_send_tconX(cli, service, service_type, 1504 password, strlen(password)+1)) { 1505 nt_status = cli_nt_error(cli); 1506 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status))); 1507 cli_shutdown(cli); 1508 if (NT_STATUS_IS_OK(nt_status)) { 1509 nt_status = NT_STATUS_UNSUCCESSFUL; 1510 } 1511 return nt_status; 1512 } 1513 } 1514 1515 init_creds(&creds, user, domain, password); 1516 cli_init_creds(cli, &creds); 1517 1518 *output_cli = cli; 1519 return NT_STATUS_OK; 1520} 1521 1522/**************************************************************************** 1523 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed. 1524****************************************************************************/ 1525 1526BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost, 1527 struct in_addr *pdest_ip) 1528{ 1529 struct nmb_name calling, called; 1530 1531 make_nmb_name(&calling, srchost, 0x0); 1532 1533 /* 1534 * If the called name is an IP address 1535 * then use *SMBSERVER immediately. 1536 */ 1537 1538 if(is_ipaddress(desthost)) 1539 make_nmb_name(&called, "*SMBSERVER", 0x20); 1540 else 1541 make_nmb_name(&called, desthost, 0x20); 1542 1543 if (!cli_session_request(cli, &calling, &called)) { 1544 struct nmb_name smbservername; 1545 1546 make_nmb_name(&smbservername , "*SMBSERVER", 0x20); 1547 1548 /* 1549 * If the name wasn't *SMBSERVER then 1550 * try with *SMBSERVER if the first name fails. 1551 */ 1552 1553 if (nmb_name_equal(&called, &smbservername)) { 1554 1555 /* 1556 * The name used was *SMBSERVER, don't bother with another name. 1557 */ 1558 1559 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \ 1560with error %s.\n", desthost, cli_errstr(cli) )); 1561 return False; 1562 } 1563 1564 /* 1565 * We need to close the connection here but can't call cli_shutdown as 1566 * will free an allocated cli struct. cli_close_connection was invented 1567 * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>. 1568 */ 1569 1570 cli_close_connection(cli); 1571 1572 if (!cli_initialise(cli) || 1573 !cli_connect(cli, desthost, pdest_ip) || 1574 !cli_session_request(cli, &calling, &smbservername)) { 1575 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \ 1576name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) )); 1577 return False; 1578 } 1579 } 1580 1581 return True; 1582} 1583 1584 1585 1586 1587 1588/**************************************************************************** 1589 Send an old style tcon. 1590****************************************************************************/ 1591NTSTATUS cli_raw_tcon(struct cli_state *cli, 1592 const char *service, const char *pass, const char *dev, 1593 uint16 *max_xmit, uint16 *tid) 1594{ 1595 char *p; 1596 1597 if (!lp_client_plaintext_auth() && (*pass)) { 1598 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'" 1599 " is disabled\n")); 1600 return NT_STATUS_ACCESS_DENIED; 1601 } 1602 1603 memset(cli->outbuf,'\0',smb_size); 1604 memset(cli->inbuf,'\0',smb_size); 1605 1606 set_message(cli->outbuf, 0, 0, True); 1607 SCVAL(cli->outbuf,smb_com,SMBtcon); 1608 cli_setup_packet(cli); 1609 1610 p = smb_buf(cli->outbuf); 1611 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN); 1612 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN); 1613 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN); 1614 1615 cli_setup_bcc(cli, p); 1616 1617 cli_send_smb(cli); 1618 if (!cli_receive_smb(cli)) { 1619 return NT_STATUS_UNEXPECTED_NETWORK_ERROR; 1620 } 1621 1622 if (cli_is_error(cli)) { 1623 return cli_nt_error(cli); 1624 } 1625 1626 *max_xmit = SVAL(cli->inbuf, smb_vwv0); 1627 *tid = SVAL(cli->inbuf, smb_vwv1); 1628 1629 return NT_STATUS_OK; 1630} 1631 1632/* Return a cli_state pointing at the IPC$ share for the given server */ 1633 1634struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip, 1635 struct user_auth_info *user_info) 1636{ 1637 struct cli_state *cli; 1638 pstring myname; 1639 NTSTATUS nt_status; 1640 1641 get_myname(myname); 1642 1643 nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC", 1644 user_info->username, lp_workgroup(), user_info->password, 1645 CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, NULL); 1646 1647 if (NT_STATUS_IS_OK(nt_status)) { 1648 return cli; 1649 } else if (is_ipaddress(server)) { 1650 /* windows 9* needs a correct NMB name for connections */ 1651 fstring remote_name; 1652 1653 if (name_status_find("*", 0, 0, *server_ip, remote_name)) { 1654 cli = get_ipc_connect(remote_name, server_ip, user_info); 1655 if (cli) 1656 return cli; 1657 } 1658 } 1659 return NULL; 1660} 1661 1662/* 1663 * Given the IP address of a master browser on the network, return its 1664 * workgroup and connect to it. 1665 * 1666 * This function is provided to allow additional processing beyond what 1667 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master 1668 * browsers and obtain each master browsers' list of domains (in case the 1669 * first master browser is recently on the network and has not yet 1670 * synchronized with other master browsers and therefore does not yet have the 1671 * entire network browse list) 1672 */ 1673 1674struct cli_state *get_ipc_connect_master_ip(struct ip_service * mb_ip, pstring workgroup, struct user_auth_info *user_info) 1675{ 1676 static fstring name; 1677 struct cli_state *cli; 1678 struct in_addr server_ip; 1679 1680 DEBUG(99, ("Looking up name of master browser %s\n", 1681 inet_ntoa(mb_ip->ip))); 1682 1683 /* 1684 * Do a name status query to find out the name of the master browser. 1685 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain 1686 * master browser will not respond to a wildcard query (or, at least, 1687 * an NT4 server acting as the domain master browser will not). 1688 * 1689 * We might be able to use ONLY the query on MSBROWSE, but that's not 1690 * yet been tested with all Windows versions, so until it is, leave 1691 * the original wildcard query as the first choice and fall back to 1692 * MSBROWSE if the wildcard query fails. 1693 */ 1694 if (!name_status_find("*", 0, 0x1d, mb_ip->ip, name) && 1695 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip->ip, name)) { 1696 1697 DEBUG(99, ("Could not retrieve name status for %s\n", 1698 inet_ntoa(mb_ip->ip))); 1699 return NULL; 1700 } 1701 1702 if (!find_master_ip(name, &server_ip)) { 1703 DEBUG(99, ("Could not find master ip for %s\n", name)); 1704 return NULL; 1705 } 1706 1707 pstrcpy(workgroup, name); 1708 1709 DEBUG(4, ("found master browser %s, %s\n", 1710 name, inet_ntoa(mb_ip->ip))); 1711 1712 cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info); 1713 1714 return cli; 1715 1716} 1717 1718/* 1719 * Return the IP address and workgroup of a master browser on the network, and 1720 * connect to it. 1721 */ 1722 1723struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info) 1724{ 1725 struct ip_service *ip_list; 1726 struct cli_state *cli; 1727 int i, count; 1728 1729 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n")); 1730 1731 /* Go looking for workgroups by broadcasting on the local network */ 1732 1733 if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) { 1734 DEBUG(99, ("No master browsers responded\n")); 1735 return False; 1736 } 1737 1738 for (i = 0; i < count; i++) { 1739 DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip))); 1740 1741 cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, user_info); 1742 if (cli) 1743 return(cli); 1744 } 1745 1746 return NULL; 1747} 1748