summaryrefslogtreecommitdiff
path: root/source3/libsmb/clientgen.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2011-06-24 16:26:23 +1000
committerAndrew Bartlett <abartlet@samba.org>2011-06-24 16:26:23 +1000
commit6da26870e0ae5acd6ff49a30ec2f6886b44d095e (patch)
tree850c71039563c16a5d563c47e7ba2ab645baf198 /source3/libsmb/clientgen.c
parent6925a799d04c6fa59dd2ddef1f5510f9bb7d17d1 (diff)
parent2610c05b5b95cc7036b3d6dfb894c6cfbdb68483 (diff)
downloadsamba-6da26870e0ae5acd6ff49a30ec2f6886b44d095e.tar.gz
samba-6da26870e0ae5acd6ff49a30ec2f6886b44d095e.tar.bz2
samba-6da26870e0ae5acd6ff49a30ec2f6886b44d095e.zip
Merge 2610c05b5b95cc7036b3d6dfb894c6cfbdb68483 as Samba-4.0alpha16
Diffstat (limited to 'source3/libsmb/clientgen.c')
-rw-r--r--source3/libsmb/clientgen.c377
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;