s3-talloc Change TALLOC_ZERO_P() to talloc_zero()
[nivanova/samba-autobuild/.git] / source3 / libsmb / clientgen.c
index 92b898146e528d921547b9c39bd415d12fa23015..1122bbbaa507373960c6de2797a78b542b85c128 100644 (file)
 */
 
 #include "includes.h"
+#include "libsmb/libsmb.h"
+#include "../lib/util/tevent_ntstatus.h"
+#include "smb_signing.h"
+#include "async_smb.h"
 
 /*******************************************************************
  Setup the word count and byte count for a client smb message.
@@ -64,101 +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)
 {
@@ -190,260 +99,6 @@ bool cli_state_seqnum_remove(struct cli_state *cli,
        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) {
-                DEBUG(0, ("Receiving SMB: Server stopped responding\n"));
-               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;
-}
-
-/****************************************************************************
- Read the data portion of a readX smb.
- The timeout is in milliseconds
-****************************************************************************/
-
-ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len)
-{
-       NTSTATUS status;
-
-       set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK);
-
-       status = read_fd_with_timeout(
-               cli->fd, buffer, len, len, cli->timeout, NULL);
-       if (NT_STATUS_IS_OK(status)) {
-               return len;
-       }
-
-       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;
-}
-
-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.
 ****************************************************************************/
@@ -480,20 +135,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.
 ****************************************************************************/
@@ -572,7 +213,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;
        }
@@ -635,13 +276,6 @@ struct cli_state *cli_initialise_ex(int signing_state)
        memset(cli->outbuf, 0, cli->bufsize);
        memset(cli->inbuf, 0, cli->bufsize);
 
-
-#if defined(DEVELOPER)
-       /* just because we over-allocate, doesn't mean it's right to use it */
-       clobber_region(FUNCTION_MACRO, __LINE__, cli->outbuf+cli->bufsize, SAFETY_MARGIN);
-       clobber_region(FUNCTION_MACRO, __LINE__, cli->inbuf+cli->bufsize, SAFETY_MARGIN);
-#endif
-
        /* initialise signing */
        cli->signing_state = smb_signing_init(cli,
                                              allow_smb_signing,
@@ -737,6 +371,9 @@ static void _cli_shutdown(struct cli_state *cli)
 void cli_shutdown(struct cli_state *cli)
 {
        struct cli_state *cli_head;
+       if (cli == NULL) {
+               return;
+       }
        DLIST_HEAD(cli, cli_head);
        if (cli_head == cli) {
                /*
@@ -788,25 +425,6 @@ bool cli_set_case_sensitive(struct cli_state *cli, bool case_sensitive)
        return ret;
 }
 
-/****************************************************************************
-Send a keepalive packet to the server
-****************************************************************************/
-
-bool cli_send_keepalive(struct cli_state *cli)
-{
-        if (cli->fd == -1) {
-                DEBUG(3, ("cli_send_keepalive: fd == -1\n"));
-                return false;
-        }
-        if (!send_keepalive(cli->fd)) {
-                close(cli->fd);
-                cli->fd = -1;
-                DEBUG(0,("Error sending keepalive packet to client.\n"));
-                return false;
-        }
-        return true;
-}
-
 struct cli_echo_state {
        uint16_t vwv[1];
        DATA_BLOB data;
@@ -851,8 +469,9 @@ static void cli_echo_done(struct tevent_req *subreq)
        NTSTATUS status;
        uint32_t num_bytes;
        uint8_t *bytes;
+       uint8_t *inbuf;
 
-       status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL,
+       status = cli_smb_recv(subreq, state, &inbuf, 0, NULL, NULL,
                              &num_bytes, &bytes);
        if (!NT_STATUS_IS_OK(status)) {
                tevent_req_nterror(req, status);
@@ -994,7 +613,7 @@ NTSTATUS cli_smb(TALLOC_CTX *mem_ctx, struct cli_state *cli,
                              pnum_bytes, pbytes);
 fail:
         TALLOC_FREE(ev);
-       if (NT_STATUS_IS_OK(status)) {
+       if (NT_STATUS_IS_OK(status) && (result_parent != NULL)) {
                *result_parent = req;
        }
         return status;