diff options
Diffstat (limited to 'source3/libsmb/clientgen.c')
-rw-r--r-- | source3/libsmb/clientgen.c | 377 |
1 files changed, 3 insertions, 374 deletions
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 7eb10c4f1d..d3b66b67e1 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -19,6 +19,8 @@ */ #include "includes.h" +#include "libsmb/libsmb.h" +#include "../lib/util/tevent_ntstatus.h" #include "smb_signing.h" #include "async_smb.h" @@ -66,364 +68,6 @@ bool cli_ucs2(struct cli_state *cli) return ((cli->capabilities & CAP_UNICODE) != 0); } - -/**************************************************************************** - Read an smb from a fd ignoring all keepalive packets. - The timeout is in milliseconds - - This is exactly the same as receive_smb except that it never returns - a session keepalive packet (just as receive_smb used to do). - receive_smb was changed to return keepalives as the oplock processing means this call - should never go into a blocking read. -****************************************************************************/ - -static ssize_t client_receive_smb(struct cli_state *cli, size_t maxlen) -{ - size_t len; - - for(;;) { - NTSTATUS status; - - set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK); - - status = receive_smb_raw(cli->fd, cli->inbuf, cli->bufsize, - cli->timeout, maxlen, &len); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10,("client_receive_smb failed\n")); - show_msg(cli->inbuf); - - if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { - set_smb_read_error(&cli->smb_rw_error, - SMB_READ_EOF); - return -1; - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - set_smb_read_error(&cli->smb_rw_error, - SMB_READ_TIMEOUT); - return -1; - } - - set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR); - return -1; - } - - /* - * I don't believe len can be < 0 with NT_STATUS_OK - * returned above, but this check doesn't hurt. JRA. - */ - - if ((ssize_t)len < 0) { - return len; - } - - /* Ignore session keepalive packets. */ - if(CVAL(cli->inbuf,0) != SMBkeepalive) { - break; - } - } - - if (cli_encryption_on(cli)) { - NTSTATUS status = cli_decrypt_message(cli); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("SMB decryption failed on incoming packet! Error %s\n", - nt_errstr(status))); - cli->smb_rw_error = SMB_READ_BAD_DECRYPT; - return -1; - } - } - - show_msg(cli->inbuf); - return len; -} - -static bool cli_state_set_seqnum(struct cli_state *cli, uint16_t mid, uint32_t seqnum) -{ - struct cli_state_seqnum *c; - - for (c = cli->seqnum; c; c = c->next) { - if (c->mid == mid) { - c->seqnum = seqnum; - return true; - } - } - - c = talloc_zero(cli, struct cli_state_seqnum); - if (!c) { - return false; - } - - c->mid = mid; - c->seqnum = seqnum; - c->persistent = false; - DLIST_ADD_END(cli->seqnum, c, struct cli_state_seqnum *); - - return true; -} - -bool cli_state_seqnum_persistent(struct cli_state *cli, - uint16_t mid) -{ - struct cli_state_seqnum *c; - - for (c = cli->seqnum; c; c = c->next) { - if (c->mid == mid) { - c->persistent = true; - return true; - } - } - - return false; -} - -bool cli_state_seqnum_remove(struct cli_state *cli, - uint16_t mid) -{ - struct cli_state_seqnum *c; - - for (c = cli->seqnum; c; c = c->next) { - if (c->mid == mid) { - DLIST_REMOVE(cli->seqnum, c); - TALLOC_FREE(c); - return true; - } - } - - return false; -} - -static uint32_t cli_state_get_seqnum(struct cli_state *cli, uint16_t mid) -{ - struct cli_state_seqnum *c; - - for (c = cli->seqnum; c; c = c->next) { - if (c->mid == mid) { - uint32_t seqnum = c->seqnum; - if (!c->persistent) { - DLIST_REMOVE(cli->seqnum, c); - TALLOC_FREE(c); - } - return seqnum; - } - } - - return 0; -} - -/**************************************************************************** - Recv an smb. -****************************************************************************/ - -bool cli_receive_smb(struct cli_state *cli) -{ - ssize_t len; - uint16_t mid; - uint32_t seqnum; - - /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */ - if (cli->fd == -1) - return false; - - again: - len = client_receive_smb(cli, 0); - - if (len > 0) { - /* it might be an oplock break request */ - if (!(CVAL(cli->inbuf, smb_flg) & FLAG_REPLY) && - CVAL(cli->inbuf,smb_com) == SMBlockingX && - SVAL(cli->inbuf,smb_vwv6) == 0 && - SVAL(cli->inbuf,smb_vwv7) == 0) { - if (cli->oplock_handler) { - int fnum = SVAL(cli->inbuf,smb_vwv2); - unsigned char level = CVAL(cli->inbuf,smb_vwv3+1); - if (!NT_STATUS_IS_OK(cli->oplock_handler(cli, fnum, level))) { - return false; - } - } - /* try to prevent loops */ - SCVAL(cli->inbuf,smb_com,0xFF); - goto again; - } - } - - /* If the server is not responding, note that now */ - if (len < 0) { - /* - * only log if the connection should still be open and not when - * the connection was closed due to a dropped ip message - */ - if (cli->fd != -1) { - char addr[INET6_ADDRSTRLEN]; - print_sockaddr(addr, sizeof(addr), &cli->dest_ss); - DEBUG(0, ("Receiving SMB: Server %s stopped responding\n", - addr)); - close(cli->fd); - cli->fd = -1; - } - return false; - } - - mid = SVAL(cli->inbuf,smb_mid); - seqnum = cli_state_get_seqnum(cli, mid); - - if (!cli_check_sign_mac(cli, cli->inbuf, seqnum+1)) { - /* - * If we get a signature failure in sessionsetup, then - * the server sometimes just reflects the sent signature - * back to us. Detect this and allow the upper layer to - * retrieve the correct Windows error message. - */ - if (CVAL(cli->outbuf,smb_com) == SMBsesssetupX && - (smb_len(cli->inbuf) > (smb_ss_field + 8 - 4)) && - (SVAL(cli->inbuf,smb_flg2) & FLAGS2_SMB_SECURITY_SIGNATURES) && - memcmp(&cli->outbuf[smb_ss_field],&cli->inbuf[smb_ss_field],8) == 0 && - cli_is_error(cli)) { - - /* - * Reflected signature on login error. - * Set bad sig but don't close fd. - */ - cli->smb_rw_error = SMB_READ_BAD_SIG; - return true; - } - - DEBUG(0, ("SMB Signature verification failed on incoming packet!\n")); - cli->smb_rw_error = SMB_READ_BAD_SIG; - close(cli->fd); - cli->fd = -1; - return false; - }; - return true; -} - -static ssize_t write_socket(int fd, const char *buf, size_t len) -{ - ssize_t ret=0; - - DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len)); - ret = write_data(fd,buf,len); - - DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret)); - if(ret <= 0) - DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n", - (int)len, fd, strerror(errno) )); - - return(ret); -} - -/**************************************************************************** - Send an smb to a fd. -****************************************************************************/ - -bool cli_send_smb(struct cli_state *cli) -{ - size_t len; - size_t nwritten=0; - ssize_t ret; - char *buf_out = cli->outbuf; - bool enc_on = cli_encryption_on(cli); - uint32_t seqnum; - - /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */ - if (cli->fd == -1) - return false; - - cli_calculate_sign_mac(cli, cli->outbuf, &seqnum); - - if (!cli_state_set_seqnum(cli, cli->mid, seqnum)) { - DEBUG(0,("Failed to store mid[%u]/seqnum[%u]\n", - (unsigned int)cli->mid, - (unsigned int)seqnum)); - return false; - } - - if (enc_on) { - NTSTATUS status = cli_encrypt_message(cli, cli->outbuf, - &buf_out); - if (!NT_STATUS_IS_OK(status)) { - close(cli->fd); - cli->fd = -1; - cli->smb_rw_error = SMB_WRITE_ERROR; - DEBUG(0,("Error in encrypting client message. Error %s\n", - nt_errstr(status) )); - return false; - } - } - - len = smb_len(buf_out) + 4; - - while (nwritten < len) { - ret = write_socket(cli->fd,buf_out+nwritten,len - nwritten); - if (ret <= 0) { - if (enc_on) { - cli_free_enc_buffer(cli, buf_out); - } - close(cli->fd); - cli->fd = -1; - cli->smb_rw_error = SMB_WRITE_ERROR; - DEBUG(0,("Error writing %d bytes to client. %d (%s)\n", - (int)len,(int)ret, strerror(errno) )); - return false; - } - nwritten += ret; - } - - if (enc_on) { - cli_free_enc_buffer(cli, buf_out); - } - - /* Increment the mid so we can tell between responses. */ - cli->mid++; - if (!cli->mid) - cli->mid++; - return true; -} - -/**************************************************************************** - Send a "direct" writeX smb to a fd. -****************************************************************************/ - -bool cli_send_smb_direct_writeX(struct cli_state *cli, - const char *p, - size_t extradata) -{ - /* First length to send is the offset to the data. */ - size_t len = SVAL(cli->outbuf,smb_vwv11) + 4; - size_t nwritten=0; - struct iovec iov[2]; - - /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */ - if (cli->fd == -1) { - return false; - } - - if (client_is_signing_on(cli)) { - DEBUG(0,("cli_send_smb_large: cannot send signed packet.\n")); - return false; - } - - iov[0].iov_base = (void *)cli->outbuf; - iov[0].iov_len = len; - iov[1].iov_base = CONST_DISCARD(void *, p); - iov[1].iov_len = extradata; - - nwritten = write_data_iov(cli->fd, iov, 2); - if (nwritten < (len + extradata)) { - close(cli->fd); - cli->fd = -1; - cli->smb_rw_error = SMB_WRITE_ERROR; - DEBUG(0,("Error writing %d bytes to client. (%s)\n", - (int)(len+extradata), strerror(errno))); - return false; - } - - /* Increment the mid so we can tell between responses. */ - cli->mid++; - if (!cli->mid) - cli->mid++; - return true; -} - /**************************************************************************** Setup basics in a outgoing packet. ****************************************************************************/ @@ -460,20 +104,6 @@ void cli_setup_packet_buf(struct cli_state *cli, char *buf) SSVAL(buf,smb_flg2, flags2); } -void cli_setup_packet(struct cli_state *cli) -{ - cli_setup_packet_buf(cli, cli->outbuf); -} - -/**************************************************************************** - Setup the bcc length of the packet from a pointer to the end of the data. -****************************************************************************/ - -void cli_setup_bcc(struct cli_state *cli, void *p) -{ - set_message_bcc(cli->outbuf, PTR_DIFF(p, smb_buf(cli->outbuf))); -} - /**************************************************************************** Initialize Domain, user or password. ****************************************************************************/ @@ -552,7 +182,7 @@ struct cli_state *cli_initialise_ex(int signing_state) return NULL; } - cli = TALLOC_ZERO_P(NULL, struct cli_state); + cli = talloc_zero(NULL, struct cli_state); if (!cli) { return NULL; } @@ -572,7 +202,6 @@ struct cli_state *cli_initialise_ex(int signing_state) cli->bufsize = CLI_BUFFER_SIZE+4; cli->max_xmit = cli->bufsize; cli->outbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN); - cli->seqnum = 0; cli->inbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN); cli->oplock_handler = cli_oplock_ack; cli->case_sensitive = false; |