Changeset 988 for vendor/current/source3/libsmb/clientgen.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/libsmb/clientgen.c
r740 r988 22 22 #include "libsmb/libsmb.h" 23 23 #include "../lib/util/tevent_ntstatus.h" 24 #include "smb_signing.h" 24 #include "../libcli/smb/smb_signing.h" 25 #include "../libcli/smb/smb_seal.h" 25 26 #include "async_smb.h" 27 #include "../libcli/smb/smbXcli_base.h" 28 #include "../librpc/ndr/libndr.h" 29 #include "../include/client.h" 26 30 27 31 /******************************************************************* … … 52 56 53 57 /**************************************************************************** 54 Change the port number used to call on.58 Set the 'backup_intent' flag. 55 59 ****************************************************************************/ 56 60 57 void cli_set_port(struct cli_state *cli, int port) 58 { 59 cli->port = port; 60 } 61 62 /**************************************************************************** 63 convenience routine to find if we negotiated ucs2 64 ****************************************************************************/ 65 66 bool cli_ucs2(struct cli_state *cli) 67 { 68 return ((cli->capabilities & CAP_UNICODE) != 0); 69 } 70 71 72 /**************************************************************************** 73 Read an smb from a fd ignoring all keepalive packets. 74 The timeout is in milliseconds 75 76 This is exactly the same as receive_smb except that it never returns 77 a session keepalive packet (just as receive_smb used to do). 78 receive_smb was changed to return keepalives as the oplock processing means this call 79 should never go into a blocking read. 80 ****************************************************************************/ 81 82 static ssize_t client_receive_smb(struct cli_state *cli, size_t maxlen) 83 { 84 size_t len; 85 86 for(;;) { 87 NTSTATUS status; 88 89 set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK); 90 91 status = receive_smb_raw(cli->fd, cli->inbuf, cli->bufsize, 92 cli->timeout, maxlen, &len); 93 if (!NT_STATUS_IS_OK(status)) { 94 DEBUG(10,("client_receive_smb failed\n")); 95 show_msg(cli->inbuf); 96 97 if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { 98 set_smb_read_error(&cli->smb_rw_error, 99 SMB_READ_EOF); 100 return -1; 101 } 102 103 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { 104 set_smb_read_error(&cli->smb_rw_error, 105 SMB_READ_TIMEOUT); 106 return -1; 107 } 108 109 set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR); 110 return -1; 111 } 112 113 /* 114 * I don't believe len can be < 0 with NT_STATUS_OK 115 * returned above, but this check doesn't hurt. JRA. 116 */ 117 118 if ((ssize_t)len < 0) { 119 return len; 120 } 121 122 /* Ignore session keepalive packets. */ 123 if(CVAL(cli->inbuf,0) != SMBkeepalive) { 124 break; 125 } 126 } 127 128 if (cli_encryption_on(cli)) { 129 NTSTATUS status = cli_decrypt_message(cli); 130 if (!NT_STATUS_IS_OK(status)) { 131 DEBUG(0, ("SMB decryption failed on incoming packet! Error %s\n", 132 nt_errstr(status))); 133 cli->smb_rw_error = SMB_READ_BAD_DECRYPT; 134 return -1; 135 } 136 } 137 138 show_msg(cli->inbuf); 139 return len; 140 } 141 142 static bool cli_state_set_seqnum(struct cli_state *cli, uint16_t mid, uint32_t seqnum) 143 { 144 struct cli_state_seqnum *c; 145 146 for (c = cli->seqnum; c; c = c->next) { 147 if (c->mid == mid) { 148 c->seqnum = seqnum; 149 return true; 150 } 151 } 152 153 c = talloc_zero(cli, struct cli_state_seqnum); 154 if (!c) { 155 return false; 156 } 157 158 c->mid = mid; 159 c->seqnum = seqnum; 160 c->persistent = false; 161 DLIST_ADD_END(cli->seqnum, c, struct cli_state_seqnum *); 162 163 return true; 164 } 165 166 bool cli_state_seqnum_persistent(struct cli_state *cli, 167 uint16_t mid) 168 { 169 struct cli_state_seqnum *c; 170 171 for (c = cli->seqnum; c; c = c->next) { 172 if (c->mid == mid) { 173 c->persistent = true; 174 return true; 175 } 176 } 177 178 return false; 179 } 180 181 bool cli_state_seqnum_remove(struct cli_state *cli, 182 uint16_t mid) 183 { 184 struct cli_state_seqnum *c; 185 186 for (c = cli->seqnum; c; c = c->next) { 187 if (c->mid == mid) { 188 DLIST_REMOVE(cli->seqnum, c); 189 TALLOC_FREE(c); 190 return true; 191 } 192 } 193 194 return false; 195 } 196 197 static uint32_t cli_state_get_seqnum(struct cli_state *cli, uint16_t mid) 198 { 199 struct cli_state_seqnum *c; 200 201 for (c = cli->seqnum; c; c = c->next) { 202 if (c->mid == mid) { 203 uint32_t seqnum = c->seqnum; 204 if (!c->persistent) { 205 DLIST_REMOVE(cli->seqnum, c); 206 TALLOC_FREE(c); 207 } 208 return seqnum; 209 } 210 } 211 212 return 0; 213 } 214 215 /**************************************************************************** 216 Recv an smb. 217 ****************************************************************************/ 218 219 bool cli_receive_smb(struct cli_state *cli) 220 { 221 ssize_t len; 222 uint16_t mid; 223 uint32_t seqnum; 224 225 /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */ 226 if (cli->fd == -1) 227 return false; 228 229 again: 230 len = client_receive_smb(cli, 0); 231 232 if (len > 0) { 233 /* it might be an oplock break request */ 234 if (!(CVAL(cli->inbuf, smb_flg) & FLAG_REPLY) && 235 CVAL(cli->inbuf,smb_com) == SMBlockingX && 236 SVAL(cli->inbuf,smb_vwv6) == 0 && 237 SVAL(cli->inbuf,smb_vwv7) == 0) { 238 if (cli->oplock_handler) { 239 int fnum = SVAL(cli->inbuf,smb_vwv2); 240 unsigned char level = CVAL(cli->inbuf,smb_vwv3+1); 241 if (!NT_STATUS_IS_OK(cli->oplock_handler(cli, fnum, level))) { 242 return false; 243 } 244 } 245 /* try to prevent loops */ 246 SCVAL(cli->inbuf,smb_com,0xFF); 247 goto again; 248 } 249 } 250 251 /* If the server is not responding, note that now */ 252 if (len < 0) { 253 /* 254 * only log if the connection should still be open and not when 255 * the connection was closed due to a dropped ip message 256 */ 257 if (cli->fd != -1) { 258 char addr[INET6_ADDRSTRLEN]; 259 print_sockaddr(addr, sizeof(addr), &cli->dest_ss); 260 DEBUG(0, ("Receiving SMB: Server %s stopped responding\n", 261 addr)); 262 close(cli->fd); 263 cli->fd = -1; 264 } 265 return false; 266 } 267 268 mid = SVAL(cli->inbuf,smb_mid); 269 seqnum = cli_state_get_seqnum(cli, mid); 270 271 if (!cli_check_sign_mac(cli, cli->inbuf, seqnum+1)) { 272 /* 273 * If we get a signature failure in sessionsetup, then 274 * the server sometimes just reflects the sent signature 275 * back to us. Detect this and allow the upper layer to 276 * retrieve the correct Windows error message. 277 */ 278 if (CVAL(cli->outbuf,smb_com) == SMBsesssetupX && 279 (smb_len(cli->inbuf) > (smb_ss_field + 8 - 4)) && 280 (SVAL(cli->inbuf,smb_flg2) & FLAGS2_SMB_SECURITY_SIGNATURES) && 281 memcmp(&cli->outbuf[smb_ss_field],&cli->inbuf[smb_ss_field],8) == 0 && 282 cli_is_error(cli)) { 283 284 /* 285 * Reflected signature on login error. 286 * Set bad sig but don't close fd. 287 */ 288 cli->smb_rw_error = SMB_READ_BAD_SIG; 289 return true; 290 } 291 292 DEBUG(0, ("SMB Signature verification failed on incoming packet!\n")); 293 cli->smb_rw_error = SMB_READ_BAD_SIG; 294 close(cli->fd); 295 cli->fd = -1; 296 return false; 297 }; 298 return true; 299 } 300 301 static ssize_t write_socket(int fd, const char *buf, size_t len) 302 { 303 ssize_t ret=0; 304 305 DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len)); 306 ret = write_data(fd,buf,len); 307 308 DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret)); 309 if(ret <= 0) 310 DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n", 311 (int)len, fd, strerror(errno) )); 312 313 return(ret); 314 } 315 316 /**************************************************************************** 317 Send an smb to a fd. 318 ****************************************************************************/ 319 320 bool cli_send_smb(struct cli_state *cli) 321 { 322 size_t len; 323 size_t nwritten=0; 324 ssize_t ret; 325 char *buf_out = cli->outbuf; 326 bool enc_on = cli_encryption_on(cli); 327 uint32_t seqnum; 328 329 /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */ 330 if (cli->fd == -1) 331 return false; 332 333 cli_calculate_sign_mac(cli, cli->outbuf, &seqnum); 334 335 if (!cli_state_set_seqnum(cli, cli->mid, seqnum)) { 336 DEBUG(0,("Failed to store mid[%u]/seqnum[%u]\n", 337 (unsigned int)cli->mid, 338 (unsigned int)seqnum)); 339 return false; 340 } 341 342 if (enc_on) { 343 NTSTATUS status = cli_encrypt_message(cli, cli->outbuf, 344 &buf_out); 345 if (!NT_STATUS_IS_OK(status)) { 346 close(cli->fd); 347 cli->fd = -1; 348 cli->smb_rw_error = SMB_WRITE_ERROR; 349 DEBUG(0,("Error in encrypting client message. Error %s\n", 350 nt_errstr(status) )); 351 return false; 352 } 353 } 354 355 len = smb_len(buf_out) + 4; 356 357 while (nwritten < len) { 358 ret = write_socket(cli->fd,buf_out+nwritten,len - nwritten); 359 if (ret <= 0) { 360 if (enc_on) { 361 cli_free_enc_buffer(cli, buf_out); 362 } 363 close(cli->fd); 364 cli->fd = -1; 365 cli->smb_rw_error = SMB_WRITE_ERROR; 366 DEBUG(0,("Error writing %d bytes to client. %d (%s)\n", 367 (int)len,(int)ret, strerror(errno) )); 368 return false; 369 } 370 nwritten += ret; 371 } 372 373 if (enc_on) { 374 cli_free_enc_buffer(cli, buf_out); 375 } 376 377 /* Increment the mid so we can tell between responses. */ 378 cli->mid++; 379 if (!cli->mid) 380 cli->mid++; 381 return true; 382 } 383 384 /**************************************************************************** 385 Setup basics in a outgoing packet. 386 ****************************************************************************/ 387 388 void cli_setup_packet_buf(struct cli_state *cli, char *buf) 389 { 390 uint16 flags2; 391 cli->rap_error = 0; 392 SIVAL(buf,smb_rcls,0); 393 SSVAL(buf,smb_pid,cli->pid); 394 memset(buf+smb_pidhigh, 0, 12); 395 SSVAL(buf,smb_uid,cli->vuid); 396 SSVAL(buf,smb_mid,cli->mid); 397 398 if (cli->protocol <= PROTOCOL_CORE) { 399 return; 400 } 401 402 if (cli->case_sensitive) { 403 SCVAL(buf,smb_flg,0x0); 404 } else { 405 /* Default setting, case insensitive. */ 406 SCVAL(buf,smb_flg,0x8); 407 } 408 flags2 = FLAGS2_LONG_PATH_COMPONENTS; 409 if (cli->capabilities & CAP_UNICODE) 410 flags2 |= FLAGS2_UNICODE_STRINGS; 411 if ((cli->capabilities & CAP_DFS) && cli->dfsroot) 412 flags2 |= FLAGS2_DFS_PATHNAMES; 413 if (cli->capabilities & CAP_STATUS32) 414 flags2 |= FLAGS2_32_BIT_ERROR_CODES; 415 if (cli->use_spnego) 416 flags2 |= FLAGS2_EXTENDED_SECURITY; 417 SSVAL(buf,smb_flg2, flags2); 418 } 419 420 void cli_setup_packet(struct cli_state *cli) 421 { 422 cli_setup_packet_buf(cli, cli->outbuf); 423 } 424 425 /**************************************************************************** 426 Setup the bcc length of the packet from a pointer to the end of the data. 427 ****************************************************************************/ 428 429 void cli_setup_bcc(struct cli_state *cli, void *p) 430 { 431 set_message_bcc(cli->outbuf, PTR_DIFF(p, smb_buf(cli->outbuf))); 432 } 433 434 /**************************************************************************** 435 Initialize Domain, user or password. 436 ****************************************************************************/ 437 438 NTSTATUS cli_set_domain(struct cli_state *cli, const char *domain) 439 { 440 TALLOC_FREE(cli->domain); 441 cli->domain = talloc_strdup(cli, domain ? domain : ""); 442 if (cli->domain == NULL) { 443 return NT_STATUS_NO_MEMORY; 444 } 445 return NT_STATUS_OK; 446 } 447 448 NTSTATUS cli_set_username(struct cli_state *cli, const char *username) 449 { 450 TALLOC_FREE(cli->user_name); 451 cli->user_name = talloc_strdup(cli, username ? username : ""); 452 if (cli->user_name == NULL) { 453 return NT_STATUS_NO_MEMORY; 454 } 455 return NT_STATUS_OK; 456 } 457 458 NTSTATUS cli_set_password(struct cli_state *cli, const char *password) 459 { 460 TALLOC_FREE(cli->password); 461 462 /* Password can be NULL. */ 463 if (password) { 464 cli->password = talloc_strdup(cli, password); 465 if (cli->password == NULL) { 466 return NT_STATUS_NO_MEMORY; 467 } 468 } else { 469 /* Use zero NTLMSSP hashes and session key. */ 470 cli->password = NULL; 471 } 472 473 return NT_STATUS_OK; 474 } 475 476 /**************************************************************************** 477 Initialise credentials of a client structure. 478 ****************************************************************************/ 479 480 NTSTATUS cli_init_creds(struct cli_state *cli, const char *username, const char *domain, const char *password) 481 { 482 NTSTATUS status = cli_set_username(cli, username); 483 if (!NT_STATUS_IS_OK(status)) { 484 return status; 485 } 486 status = cli_set_domain(cli, domain); 487 if (!NT_STATUS_IS_OK(status)) { 488 return status; 489 } 490 DEBUG(10,("cli_init_creds: user %s domain %s\n", cli->user_name, cli->domain)); 491 492 return cli_set_password(cli, password); 61 bool cli_set_backup_intent(struct cli_state *cli, bool flag) 62 { 63 bool old_state = cli->backup_intent; 64 cli->backup_intent = flag; 65 return old_state; 493 66 } 494 67 … … 498 71 ****************************************************************************/ 499 72 500 struct cli_state *cli_initialise_ex(int signing_state) 73 struct GUID cli_state_client_guid; 74 75 struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx, 76 int fd, 77 const char *remote_name, 78 const char *remote_realm, 79 int signing_state, int flags) 501 80 { 502 81 struct cli_state *cli = NULL; 503 bool allow_smb_signing = false; 504 bool mandatory_signing = false; 82 bool use_spnego = lp_client_use_spnego(); 83 bool force_dos_errors = false; 84 bool force_ascii = false; 85 bool use_level_II_oplocks = false; 86 uint32_t smb1_capabilities = 0; 87 uint32_t smb2_capabilities = 0; 88 struct GUID client_guid; 89 90 if (!GUID_all_zero(&cli_state_client_guid)) { 91 client_guid = cli_state_client_guid; 92 } else { 93 client_guid = GUID_random(); 94 } 505 95 506 96 /* Check the effective uid - make sure we are not setuid */ … … 510 100 } 511 101 512 cli = TALLOC_ZERO_P(NULL, struct cli_state);102 cli = talloc_zero(mem_ctx, struct cli_state); 513 103 if (!cli) { 514 104 return NULL; 105 } 106 107 cli->server_domain = talloc_strdup(cli, ""); 108 if (!cli->server_domain) { 109 goto error; 110 } 111 cli->server_os = talloc_strdup(cli, ""); 112 if (!cli->server_os) { 113 goto error; 114 } 115 cli->server_type = talloc_strdup(cli, ""); 116 if (!cli->server_type) { 117 goto error; 515 118 } 516 119 … … 519 122 goto error; 520 123 } 521 cli->port = 0; 522 cli->fd = -1; 523 cli->cnum = -1; 524 cli->pid = (uint16)sys_getpid(); 525 cli->mid = 1; 526 cli->vuid = UID_FIELD_INVALID; 527 cli->protocol = PROTOCOL_NT1; 528 cli->timeout = 20000; /* Timeout is in milliseconds. */ 529 cli->bufsize = CLI_BUFFER_SIZE+4; 530 cli->max_xmit = cli->bufsize; 531 cli->outbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN); 532 cli->seqnum = 0; 533 cli->inbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN); 534 cli->oplock_handler = cli_oplock_ack; 535 cli->case_sensitive = false; 536 cli->smb_rw_error = SMB_READ_OK; 537 538 cli->use_spnego = lp_client_use_spnego(); 539 540 cli->capabilities = CAP_UNICODE | CAP_STATUS32 | CAP_DFS; 124 cli->raw_status = NT_STATUS_INTERNAL_ERROR; 125 cli->map_dos_errors = true; /* remove this */ 126 cli->timeout = CLIENT_TIMEOUT; 541 127 542 128 /* Set the CLI_FORCE_DOSERR environment variable to test 543 129 client routines using DOS errors instead of STATUS32 544 130 ones. This intended only as a temporary hack. */ 545 if (getenv("CLI_FORCE_DOSERR")) 546 cli->force_dos_errors = true; 547 548 if (lp_client_signing()) { 549 allow_smb_signing = true; 550 } 551 552 if (lp_client_signing() == Required) { 553 mandatory_signing = true; 554 } 555 556 if (signing_state != Undefined) { 557 allow_smb_signing = true; 558 } 559 560 if (signing_state == false) { 561 allow_smb_signing = false; 562 mandatory_signing = false; 563 } 564 565 if (signing_state == Required) { 566 mandatory_signing = true; 567 } 568 569 if (!cli->outbuf || !cli->inbuf) 570 goto error; 571 572 memset(cli->outbuf, 0, cli->bufsize); 573 memset(cli->inbuf, 0, cli->bufsize); 574 575 576 #if defined(DEVELOPER) 577 /* just because we over-allocate, doesn't mean it's right to use it */ 578 clobber_region(__FUNCTION__, __LINE__, cli->outbuf+cli->bufsize, SAFETY_MARGIN); 579 clobber_region(__FUNCTION__, __LINE__, cli->inbuf+cli->bufsize, SAFETY_MARGIN); 580 #endif 581 582 /* initialise signing */ 583 cli->signing_state = smb_signing_init(cli, 584 allow_smb_signing, 585 mandatory_signing); 586 if (!cli->signing_state) { 131 if (getenv("CLI_FORCE_DOSERR")) { 132 force_dos_errors = true; 133 } 134 if (flags & CLI_FULL_CONNECTION_FORCE_DOS_ERRORS) { 135 force_dos_errors = true; 136 } 137 138 if (getenv("CLI_FORCE_ASCII")) { 139 force_ascii = true; 140 } 141 if (!lp_unicode()) { 142 force_ascii = true; 143 } 144 if (flags & CLI_FULL_CONNECTION_FORCE_ASCII) { 145 force_ascii = true; 146 } 147 148 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO) { 149 use_spnego = false; 150 } else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) { 151 cli->use_kerberos = true; 152 } 153 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) && 154 cli->use_kerberos) { 155 cli->fallback_after_kerberos = true; 156 } 157 158 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) { 159 cli->use_ccache = true; 160 } 161 162 if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) { 163 cli->pw_nt_hash = true; 164 } 165 166 if (flags & CLI_FULL_CONNECTION_OPLOCKS) { 167 cli->use_oplocks = true; 168 } 169 if (flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) { 170 use_level_II_oplocks = true; 171 } 172 173 if (signing_state == SMB_SIGNING_IPC_DEFAULT) { 174 /* 175 * Ensure for IPC/RPC the default is to require 176 * signing unless explicitly turned off by the 177 * administrator. 178 */ 179 signing_state = lp_client_ipc_signing(); 180 } 181 182 if (signing_state == SMB_SIGNING_DEFAULT) { 183 signing_state = lp_client_signing(); 184 } 185 186 smb1_capabilities = 0; 187 smb1_capabilities |= CAP_LARGE_FILES; 188 smb1_capabilities |= CAP_NT_SMBS | CAP_RPC_REMOTE_APIS; 189 smb1_capabilities |= CAP_LOCK_AND_READ | CAP_NT_FIND; 190 smb1_capabilities |= CAP_DFS | CAP_W2K_SMBS; 191 smb1_capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX; 192 smb1_capabilities |= CAP_LWIO; 193 194 if (!force_dos_errors) { 195 smb1_capabilities |= CAP_STATUS32; 196 } 197 198 if (!force_ascii) { 199 smb1_capabilities |= CAP_UNICODE; 200 } 201 202 if (use_spnego) { 203 smb1_capabilities |= CAP_EXTENDED_SECURITY; 204 } 205 206 if (use_level_II_oplocks) { 207 smb1_capabilities |= CAP_LEVEL_II_OPLOCKS; 208 } 209 210 smb2_capabilities = SMB2_CAP_ALL; 211 212 if (remote_realm) { 213 cli->remote_realm = talloc_strdup(cli, remote_realm); 214 if (cli->remote_realm == NULL) { 215 goto error; 216 } 217 } 218 219 cli->conn = smbXcli_conn_create(cli, fd, remote_name, 220 signing_state, 221 smb1_capabilities, 222 &client_guid, 223 smb2_capabilities); 224 if (cli->conn == NULL) { 587 225 goto error; 588 226 } 589 227 590 cli->outgoing = tevent_queue_create(cli, "cli_outgoing"); 591 if (cli->outgoing == NULL) { 228 cli->smb1.pid = (uint16_t)getpid(); 229 cli->smb1.vc_num = cli->smb1.pid; 230 cli->smb1.tcon = smbXcli_tcon_create(cli); 231 if (cli->smb1.tcon == NULL) { 592 232 goto error; 593 233 } 594 cli->pending = NULL; 234 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX); 235 cli->smb1.session = smbXcli_session_create(cli, cli->conn); 236 if (cli->smb1.session == NULL) { 237 goto error; 238 } 595 239 596 240 cli->initialised = 1; 597 598 241 return cli; 599 242 … … 602 245 error: 603 246 604 SAFE_FREE(cli->inbuf);605 SAFE_FREE(cli->outbuf);606 247 TALLOC_FREE(cli); 607 248 return NULL; 608 }609 610 struct cli_state *cli_initialise(void)611 {612 return cli_initialise_ex(Undefined);613 249 } 614 250 … … 642 278 * later. This tree disconnect forces the peer to clean up, since the 643 279 * connection will be going away. 644 *645 * Also, do not do tree disconnect when cli->smb_rw_error is SMB_DO_NOT_DO_TDIS646 * the only user for this so far is smbmount which passes opened connection647 * down to kernel's smbfs module.648 280 */ 649 if ( (cli->cnum != (uint16)-1) && (cli->smb_rw_error != SMB_DO_NOT_DO_TDIS )) {281 if (cli_state_has_tcon(cli)) { 650 282 cli_tdis(cli); 651 283 } 652 653 SAFE_FREE(cli->outbuf); 654 SAFE_FREE(cli->inbuf); 655 656 data_blob_free(&cli->secblob); 657 data_blob_free(&cli->user_session_key); 658 659 if (cli->fd != -1) { 660 close(cli->fd); 661 } 662 cli->fd = -1; 663 cli->smb_rw_error = SMB_READ_OK; 664 665 /* 666 * Need to free pending first, they remove themselves 667 */ 668 while (cli->pending) { 669 talloc_free(cli->pending[0]); 670 } 284 285 smbXcli_conn_disconnect(cli->conn, NT_STATUS_OK); 286 671 287 TALLOC_FREE(cli); 672 288 } … … 698 314 } 699 315 700 /**************************************************************************** 701 Set socket options on a open connection. 702 ****************************************************************************/ 703 704 void cli_sockopt(struct cli_state *cli, const char *options) 705 { 706 set_socket_options(cli->fd, options); 316 const char *cli_state_remote_realm(struct cli_state *cli) 317 { 318 return cli->remote_realm; 319 } 320 321 uint16_t cli_state_get_vc_num(struct cli_state *cli) 322 { 323 return cli->smb1.vc_num; 707 324 } 708 325 … … 711 328 ****************************************************************************/ 712 329 713 uint16 cli_setpid(struct cli_state *cli, uint16 pid) 714 { 715 uint16 ret = cli->pid; 716 cli->pid = pid; 330 uint16_t cli_setpid(struct cli_state *cli, uint16_t pid) 331 { 332 uint16_t ret = cli->smb1.pid; 333 cli->smb1.pid = pid; 334 return ret; 335 } 336 337 uint16_t cli_getpid(struct cli_state *cli) 338 { 339 return cli->smb1.pid; 340 } 341 342 bool cli_state_has_tcon(struct cli_state *cli) 343 { 344 uint16_t tid = cli_state_get_tid(cli); 345 346 if (tid == UINT16_MAX) { 347 return false; 348 } 349 350 return true; 351 } 352 353 uint16_t cli_state_get_tid(struct cli_state *cli) 354 { 355 return smb1cli_tcon_current_id(cli->smb1.tcon); 356 } 357 358 uint16_t cli_state_set_tid(struct cli_state *cli, uint16_t tid) 359 { 360 uint16_t ret = smb1cli_tcon_current_id(cli->smb1.tcon); 361 smb1cli_tcon_set_id(cli->smb1.tcon, tid); 362 return ret; 363 } 364 365 uint16_t cli_state_get_uid(struct cli_state *cli) 366 { 367 return smb1cli_session_current_id(cli->smb1.session); 368 } 369 370 uint16_t cli_state_set_uid(struct cli_state *cli, uint16_t uid) 371 { 372 uint16_t ret = smb1cli_session_current_id(cli->smb1.session); 373 smb1cli_session_set_id(cli->smb1.session, uid); 717 374 return ret; 718 375 } … … 724 381 bool cli_set_case_sensitive(struct cli_state *cli, bool case_sensitive) 725 382 { 726 bool ret = cli->case_sensitive; 727 cli->case_sensitive = case_sensitive; 383 bool ret; 384 uint32_t fs_attrs; 385 struct smbXcli_tcon *tcon; 386 387 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { 388 tcon = cli->smb2.tcon; 389 } else { 390 tcon = cli->smb1.tcon; 391 } 392 393 fs_attrs = smbXcli_tcon_get_fs_attributes(tcon); 394 if (fs_attrs & FILE_CASE_SENSITIVE_SEARCH) { 395 ret = true; 396 } else { 397 ret = false; 398 } 399 if (case_sensitive) { 400 fs_attrs |= FILE_CASE_SENSITIVE_SEARCH; 401 } else { 402 fs_attrs &= ~FILE_CASE_SENSITIVE_SEARCH; 403 } 404 smbXcli_tcon_set_fs_attributes(tcon, fs_attrs); 405 728 406 return ret; 729 407 } 730 408 409 uint32_t cli_state_available_size(struct cli_state *cli, uint32_t ofs) 410 { 411 uint32_t ret = smb1cli_conn_max_xmit(cli->conn); 412 413 if (ofs >= ret) { 414 return 0; 415 } 416 417 ret -= ofs; 418 419 return ret; 420 } 421 422 time_t cli_state_server_time(struct cli_state *cli) 423 { 424 NTTIME nt; 425 time_t t; 426 427 nt = smbXcli_conn_server_system_time(cli->conn); 428 t = nt_time_to_unix(nt); 429 430 return t; 431 } 432 731 433 struct cli_echo_state { 732 uint16_t vwv[1]; 733 DATA_BLOB data; 734 int num_echos; 434 bool is_smb2; 735 435 }; 736 436 737 437 static void cli_echo_done(struct tevent_req *subreq); 738 438 739 struct tevent_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,439 struct tevent_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, 740 440 struct cli_state *cli, uint16_t num_echos, 741 441 DATA_BLOB data) … … 748 448 return NULL; 749 449 } 750 SSVAL(state->vwv, 0, num_echos); 751 state->data = data; 752 state->num_echos = num_echos; 753 754 subreq = cli_smb_send(state, ev, cli, SMBecho, 0, 1, state->vwv, 755 data.length, data.data); 756 if (subreq == NULL) { 757 goto fail; 450 451 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { 452 state->is_smb2 = true; 453 subreq = smb2cli_echo_send(state, ev, 454 cli->conn, 455 cli->timeout); 456 } else { 457 subreq = smb1cli_echo_send(state, ev, 458 cli->conn, 459 cli->timeout, 460 num_echos, 461 data); 462 } 463 if (tevent_req_nomem(subreq, req)) { 464 return tevent_req_post(req, ev); 758 465 } 759 466 tevent_req_set_callback(subreq, cli_echo_done, req); 467 760 468 return req; 761 fail:762 TALLOC_FREE(req);763 return NULL;764 469 } 765 470 … … 771 476 req, struct cli_echo_state); 772 477 NTSTATUS status; 773 uint32_t num_bytes; 774 uint8_t *bytes; 775 uint8_t *inbuf; 776 777 status = cli_smb_recv(subreq, state, &inbuf, 0, NULL, NULL, 778 &num_bytes, &bytes); 478 479 if (state->is_smb2) { 480 status = smb2cli_echo_recv(subreq); 481 } else { 482 status = smb1cli_echo_recv(subreq); 483 } 484 TALLOC_FREE(subreq); 779 485 if (!NT_STATUS_IS_OK(status)) { 780 486 tevent_req_nterror(req, status); 781 487 return; 782 488 } 783 if ((num_bytes != state->data.length) 784 || (memcmp(bytes, state->data.data, num_bytes) != 0)) { 785 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); 786 return; 787 } 788 789 state->num_echos -=1; 790 if (state->num_echos == 0) { 791 tevent_req_done(req); 792 return; 793 } 794 795 if (!cli_smb_req_set_pending(subreq)) { 796 tevent_req_nterror(req, NT_STATUS_NO_MEMORY); 797 return; 798 } 489 490 tevent_req_done(req); 799 491 } 800 492 … … 823 515 { 824 516 TALLOC_CTX *frame = talloc_stackframe(); 825 struct event_context *ev;517 struct tevent_context *ev; 826 518 struct tevent_req *req; 827 519 NTSTATUS status = NT_STATUS_OK; 828 520 829 if ( cli_has_async_calls(cli)) {521 if (smbXcli_conn_has_async_calls(cli->conn)) { 830 522 /* 831 523 * Can't use sync call while an async call is in flight … … 835 527 } 836 528 837 ev = event_context_init(frame);529 ev = samba_tevent_context_init(frame); 838 530 if (ev == NULL) { 839 531 status = NT_STATUS_NO_MEMORY; … … 847 539 } 848 540 849 if (!tevent_req_poll(req, ev)) { 850 status = map_nt_error_from_unix(errno); 541 if (!tevent_req_poll_ntstatus(req, ev, &status)) { 851 542 goto fail; 852 543 } … … 855 546 fail: 856 547 TALLOC_FREE(frame); 857 if (!NT_STATUS_IS_OK(status)) {858 cli_set_error(cli, status);859 }860 548 return status; 861 549 } … … 898 586 NTSTATUS status = NT_STATUS_NO_MEMORY; 899 587 900 if ( cli_has_async_calls(cli)) {588 if (smbXcli_conn_has_async_calls(cli->conn)) { 901 589 return NT_STATUS_INVALID_PARAMETER; 902 590 } 903 ev = tevent_context_init(mem_ctx);591 ev = samba_tevent_context_init(mem_ctx); 904 592 if (ev == NULL) { 905 593 goto fail;
Note:
See TracChangeset
for help on using the changeset viewer.