s4:libcli/raw: implement on top of smbXcli_conn/req
authorStefan Metzmacher <metze@samba.org>
Fri, 23 Sep 2011 06:35:17 +0000 (08:35 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 30 Nov 2011 14:13:36 +0000 (15:13 +0100)
metze

Autobuild-User: Stefan Metzmacher <metze@samba.org>
Autobuild-Date: Wed Nov 30 15:13:36 CET 2011 on sn-devel-104

20 files changed:
source4/libcli/cliconnect.c
source4/libcli/libcli.h
source4/libcli/raw/clioplock.c
source4/libcli/raw/clisession.c
source4/libcli/raw/clisocket.c
source4/libcli/raw/clitransport.c
source4/libcli/raw/libcliraw.h
source4/libcli/raw/rawnegotiate.c
source4/libcli/raw/rawnotify.c
source4/libcli/raw/rawreadwrite.c
source4/libcli/raw/rawrequest.c
source4/libcli/raw/rawtrans.c
source4/libcli/raw/smb_signing.c
source4/libcli/smb_composite/connect.c
source4/libcli/smb_composite/sesssetup.c
source4/librpc/rpc/dcerpc_smb.c
source4/ntvfs/cifs/vfs_cifs.c
source4/torture/basic/base.c
source4/torture/raw/lockbench.c
source4/torture/raw/openbench.c

index a8e86a04888e573e073580bde4db11c16aba3e98..45d8d2a77649fb01bd16664528a5c278866dd421 100644 (file)
@@ -39,9 +39,10 @@ bool smbcli_socket_connect(struct smbcli_state *cli, const char *server,
                           struct nbt_name *calling,
                           struct nbt_name *called)
 {
-       struct smbcli_socket *sock = NULL;
        NTSTATUS status;
 
+       cli->options = *options;
+
        status = smbcli_sock_connect(cli,
                                     NULL, /* host_addr */
                                     ports,
@@ -51,22 +52,30 @@ bool smbcli_socket_connect(struct smbcli_state *cli, const char *server,
                                     socket_options,
                                     calling,
                                     called,
-                                    &sock);
+                                    &cli->sock);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
 
-       cli->transport = smbcli_transport_init(sock, cli, true, options);
-       if (!cli->transport) {
-               return false;
-       }
-
        return true;
 }
 
 /* wrapper around smb_raw_negotiate() */
 NTSTATUS smbcli_negprot(struct smbcli_state *cli, bool unicode, int maxprotocol)
 {
+       if (unicode) {
+               cli->options.unicode = 1;
+       } else {
+               cli->options.unicode = 0;
+       }
+
+       cli->transport = smbcli_transport_init(cli->sock, cli,
+                                              true, &cli->options);
+       cli->sock = NULL;
+       if (!cli->transport) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
        return smb_raw_negotiate(cli->transport, unicode, maxprotocol);
 }
 
index 9f661e3f4ddfe06d63f6939bcc532deaa5ad47a6..9e817408deda743bf3d234ce8d2e96582e128bfb 100644 (file)
@@ -22,6 +22,7 @@
 #define __LIBCLI_H__
 
 #include "librpc/gen_ndr/nbt.h"
+#include "libcli/raw/libcliraw.h"
 
 struct substitute_context;
 
@@ -30,6 +31,8 @@ struct substitute_context;
    i.e. a single session on a single socket. 
  */
 struct smbcli_state {
+       struct smbcli_options options;
+       struct smbcli_socket *sock; /* NULL if connected */
        struct smbcli_transport *transport;
        struct smbcli_session *session;
        struct smbcli_tree *tree;
index 42ac6b517bab656e5d67d9d3b46391f60358a246..396ab96445028d607fabb45cd4bbb26cd9248995 100644 (file)
@@ -40,11 +40,12 @@ _PUBLIC_ bool smbcli_oplock_ack(struct smbcli_tree *tree, uint16_t fnum, uint16_
        SSVAL(req->out.vwv,VWV(6),0);
        SSVAL(req->out.vwv,VWV(7),0);
 
-       /* this request does not expect a reply, so tell the signing
-          subsystem not to allocate an id for a reply */
-       req->one_way_request = 1;
-
-       ret = smbcli_request_send(req); 
+       /*
+        * The low level code knows it is a
+        * one way request by looking at SMBlockingX,
+        * wct == 8 and LOCKING_ANDX_OPLOCK_RELEASE
+        */
+       ret = smbcli_request_send(req);
 
        return ret;
 }
index 41765bfb2b2fa036968d00fd3adb6642f46afc4c..d68f309519055cb98d54c1c8f520024e5575e1a2 100644 (file)
@@ -23,6 +23,7 @@
 #include "libcli/raw/libcliraw.h"
 #include "libcli/raw/raw_proto.h"
 #include "system/filesys.h"
+#include "../libcli/smb/smbXcli_base.h"
 
 #define SETUP_REQUEST_SESSION(cmd, wct, buflen) do { \
        req = smbcli_request_setup_session(session, cmd, wct, buflen); \
@@ -68,7 +69,7 @@ struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport,
        if (capabilities & CAP_EXTENDED_SECURITY) {
                flags2 |= FLAGS2_EXTENDED_SECURITY;
        }
-       if (session->transport->negotiate.sign_info.doing_signing) {
+       if (smb1cli_conn_signing_is_active(session->transport->conn)) {
                flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
        }
 
index 258fe8b09153ebf70192dc3b133f8598a10aa4cb..dd3ea3971c1510ea49a974c83cb00f36357843a1 100644 (file)
@@ -432,16 +432,3 @@ NTSTATUS smbcli_sock_connect(TALLOC_CTX *mem_ctx,
                                         calling, called);
        return smbcli_sock_connect_recv(c, mem_ctx, result);
 }
-
-
-/****************************************************************************
- mark the socket as dead
-****************************************************************************/
-_PUBLIC_ void smbcli_sock_dead(struct smbcli_socket *sock)
-{
-       talloc_free(sock->event.fde);
-       sock->event.fde = NULL;
-       talloc_free(sock->sock);
-       sock->sock = NULL;
-}
-
index b83a07063c022f5e3d44301934745963eb17d604..f1f41bcb7888ef7ee487ccd815dfed1299d76c71 100644 (file)
 */
 
 #include "includes.h"
+#include "system/network.h"
+#include "../lib/async_req/async_sock.h"
+#include "../lib/util/tevent_ntstatus.h"
 #include "libcli/raw/libcliraw.h"
 #include "libcli/raw/raw_proto.h"
 #include "lib/socket/socket.h"
-#include "../lib/util/dlinklist.h"
 #include "lib/events/events.h"
-#include "lib/stream/packet.h"
 #include "librpc/gen_ndr/ndr_nbt.h"
 #include "../libcli/nbt/libnbt.h"
-
-
-/*
-  an event has happened on the socket
-*/
-static void smbcli_transport_event_handler(struct tevent_context *ev, 
-                                          struct tevent_fd *fde, 
-                                          uint16_t flags, void *private_data)
-{
-       struct smbcli_transport *transport = talloc_get_type(private_data,
-                                                            struct smbcli_transport);
-       if (flags & TEVENT_FD_READ) {
-               packet_recv(transport->packet);
-               return;
-       }
-       if (flags & TEVENT_FD_WRITE) {
-               packet_queue_run(transport->packet);
-       }
-}
+#include "../libcli/smb/smbXcli_base.h"
+#include "../libcli/smb/read_smb.h"
 
 /*
   destroy a transport
@@ -57,18 +41,6 @@ static int transport_destructor(struct smbcli_transport *transport)
        return 0;
 }
 
-
-/*
-  handle receive errors
-*/
-static void smbcli_transport_error(void *private_data, NTSTATUS status)
-{
-       struct smbcli_transport *transport = talloc_get_type(private_data, struct smbcli_transport);
-       smbcli_transport_dead(transport, status);
-}
-
-static NTSTATUS smbcli_transport_finish_recv(void *private_data, DATA_BLOB blob);
-
 /*
   create a transport structure based on an established socket
 */
@@ -78,51 +50,55 @@ struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock,
                                               struct smbcli_options *options)
 {
        struct smbcli_transport *transport;
+       uint32_t smb1_capabilities;
 
        transport = talloc_zero(parent_ctx, struct smbcli_transport);
        if (!transport) return NULL;
 
-       if (primary) {
-               transport->socket = talloc_steal(transport, sock);
-       } else {
-               transport->socket = talloc_reference(transport, sock);
-       }
-       transport->negotiate.protocol = PROTOCOL_NT1;
        transport->ev = sock->event.ctx;
        transport->options = *options;
-       transport->negotiate.max_xmit = transport->options.max_xmit;
 
-       /* setup the stream -> packet parser */
-       transport->packet = packet_init(transport);
-       if (transport->packet == NULL) {
-               talloc_free(transport);
+       TALLOC_FREE(sock->event.fde);
+       TALLOC_FREE(sock->event.te);
+
+       smb1_capabilities = 0;
+       smb1_capabilities |= CAP_LARGE_FILES;
+       smb1_capabilities |= CAP_NT_SMBS | CAP_RPC_REMOTE_APIS;
+       smb1_capabilities |= CAP_LOCK_AND_READ | CAP_NT_FIND;
+       smb1_capabilities |= CAP_DFS | CAP_W2K_SMBS;
+       smb1_capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX;
+       smb1_capabilities |= CAP_LWIO;
+
+       if (options->ntstatus_support) {
+               smb1_capabilities |= CAP_STATUS32;
+       }
+
+       if (options->unicode) {
+               smb1_capabilities |= CAP_UNICODE;
+       }
+
+       if (options->use_spnego) {
+               smb1_capabilities |= CAP_EXTENDED_SECURITY;
+       }
+
+       if (options->use_level2_oplocks) {
+               smb1_capabilities |= CAP_LEVEL_II_OPLOCKS;
+       }
+
+       transport->conn = smbXcli_conn_create(transport,
+                                             sock->sock->fd,
+                                             sock->hostname,
+                                             options->signing,
+                                             smb1_capabilities,
+                                             NULL); /* client_guid */
+       if (transport->conn == NULL) {
+               TALLOC_FREE(sock);
+               TALLOC_FREE(transport);
                return NULL;
        }
-       packet_set_private(transport->packet, transport);
-       packet_set_socket(transport->packet, transport->socket->sock);
-       packet_set_callback(transport->packet, smbcli_transport_finish_recv);
-       packet_set_full_request(transport->packet, packet_full_request_nbt);
-       packet_set_error_handler(transport->packet, smbcli_transport_error);
-       packet_set_event_context(transport->packet, transport->socket->event.ctx);
-       packet_set_nofree(transport->packet);
-       packet_set_initial_read(transport->packet, 4);
-
-       smbcli_init_signing(transport);
-
-       ZERO_STRUCT(transport->called);
-
-       /* take over event handling from the socket layer - it only
-          handles events up until we are connected */
-       talloc_free(transport->socket->event.fde);
-       transport->socket->event.fde = tevent_add_fd(transport->socket->event.ctx,
-                                                   transport->socket->sock,
-                                                   socket_get_fd(transport->socket->sock),
-                                                   TEVENT_FD_READ,
-                                                   smbcli_transport_event_handler,
-                                                   transport);
-
-       packet_set_fde(transport->packet, transport->socket->event.fde);
-       packet_set_serialise(transport->packet);
+       sock->sock->fd = -1;
+       TALLOC_FREE(sock);
+
        talloc_set_destructor(transport, transport_destructor);
 
        return transport;
@@ -133,54 +109,14 @@ struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock,
 */
 void smbcli_transport_dead(struct smbcli_transport *transport, NTSTATUS status)
 {
-       smbcli_sock_dead(transport->socket);
-
        if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
                status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
        }
-
-       /* kill only the first pending receive - this is so that if
-        that async function frees the connection we don't die trying
-        to use old memory. The caller has to cope with only one
-        network error */
-       if (transport->pending_recv) {
-               struct smbcli_request *req = transport->pending_recv;
-               req->state = SMBCLI_REQUEST_ERROR;
-               req->status = status;
-               DLIST_REMOVE(transport->pending_recv, req);
-               if (req->async.fn) {
-                       req->async.fn(req);
-               }
-       }
-}
-
-/****************************************************************************
-get next mid in sequence
-****************************************************************************/
-uint16_t smbcli_transport_next_mid(struct smbcli_transport *transport)
-{
-       uint16_t mid;
-       struct smbcli_request *req;
-
-       mid = transport->next_mid;
-
-again:
-       /* now check to see if this mid is being used by one of the 
-          pending requests. This is quite efficient because the list is
-          usually very short */
-
-       /* the zero mid is reserved for requests that don't have a mid */
-       if (mid == 0) mid = 1;
-
-       for (req=transport->pending_recv; req; req=req->next) {
-               if (req->mid == mid) {
-                       mid++;
-                       goto again;
-               }
+       if (NT_STATUS_IS_OK(status)) {
+               status = NT_STATUS_LOCAL_DISCONNECT;
        }
 
-       transport->next_mid = mid+1;
-       return mid;
+       smbXcli_conn_disconnect(transport->conn, status);
 }
 
 static void idle_handler(struct tevent_context *ev, 
@@ -188,12 +124,17 @@ static void idle_handler(struct tevent_context *ev,
 {
        struct smbcli_transport *transport = talloc_get_type(private_data,
                                                             struct smbcli_transport);
-       struct timeval next = timeval_add(&t, 0, transport->idle.period);
-       transport->socket->event.te = tevent_add_timer(transport->socket->event.ctx, 
-                                                     transport,
-                                                     next,
-                                                     idle_handler, transport);
+       struct timeval next;
+
        transport->idle.func(transport, transport->idle.private_data);
+
+       next = timeval_current_ofs_usec(transport->idle.period);
+
+       transport->idle.te = tevent_add_timer(transport->ev,
+                                             transport,
+                                             next,
+                                             idle_handler,
+                                             transport);
 }
 
 /*
@@ -205,293 +146,383 @@ _PUBLIC_ void smbcli_transport_idle_handler(struct smbcli_transport *transport,
                                   uint64_t period,
                                   void *private_data)
 {
+       TALLOC_FREE(transport->idle.te);
+
        transport->idle.func = idle_func;
        transport->idle.private_data = private_data;
        transport->idle.period = period;
 
-       if (transport->socket->event.te != NULL) {
-               talloc_free(transport->socket->event.te);
-       }
-
-       transport->socket->event.te = tevent_add_timer(transport->socket->event.ctx, 
-                                                     transport,
-                                                     timeval_current_ofs_usec(period),
-                                                     idle_handler, transport);
+       transport->idle.te = tevent_add_timer(transport->ev,
+                                             transport,
+                                             timeval_current_ofs_usec(period),
+                                             idle_handler,
+                                             transport);
 }
 
 /*
-  we have a full request in our receive buffer - match it to a pending request
-  and process
- */
-static NTSTATUS smbcli_transport_finish_recv(void *private_data, DATA_BLOB blob)
+  process some read/write requests that are pending
+  return false if the socket is dead
+*/
+_PUBLIC_ bool smbcli_transport_process(struct smbcli_transport *transport)
 {
-       struct smbcli_transport *transport = talloc_get_type(private_data,
-                                                            struct smbcli_transport);
-       uint8_t *buffer, *hdr, *vwv;
-       int len;
-       uint16_t wct=0, mid = 0, op = 0;
-       struct smbcli_request *req = NULL;
+       struct tevent_req *subreq = NULL;
+       int ret;
 
-       buffer = blob.data;
-       len = blob.length;
-
-       hdr = buffer+NBT_HDR_SIZE;
-       vwv = hdr + HDR_VWV;
-
-       /* see if it could be an oplock break request */
-       if (smbcli_handle_oplock_break(transport, len, hdr, vwv)) {
-               talloc_free(buffer);
-               return NT_STATUS_OK;
+       if (!smbXcli_conn_is_connected(transport->conn)) {
+               return false;
        }
 
-       /* at this point we need to check for a readbraw reply, as
-          these can be any length */
-       if (transport->readbraw_pending) {
-               transport->readbraw_pending = 0;
-
-               /* it must match the first entry in the pending queue
-                  as the client is not allowed to have outstanding
-                  readbraw requests */
-               req = transport->pending_recv;
-               if (!req) goto error;
-
-               req->in.buffer = buffer;
-               talloc_steal(req, buffer);
-               req->in.size = len;
-               req->in.allocated = req->in.size;
-               goto async;
+       if (!smbXcli_conn_has_async_calls(transport->conn)) {
+               return true;
        }
 
-       if (len >= MIN_SMB_SIZE) {
-               /* extract the mid for matching to pending requests */
-               mid = SVAL(hdr, HDR_MID);
-               wct = CVAL(hdr, HDR_WCT);
-               op  = CVAL(hdr, HDR_COM);
+       /*
+        * do not block for more than 500 micro seconds
+        */
+       subreq = tevent_wakeup_send(transport,
+                                   transport->ev,
+                                   timeval_current_ofs_usec(500));
+       if (subreq == NULL) {
+               return false;
        }
 
-       /* match the incoming request against the list of pending requests */
-       for (req=transport->pending_recv; req; req=req->next) {
-               if (req->mid == mid) break;
+       ret = tevent_loop_once(transport->ev);
+       if (ret != 0) {
+               return false;
        }
 
-       /* see if it's a ntcancel reply for the current MID */
-       req = smbcli_handle_ntcancel_reply(req, len, hdr);
+       TALLOC_FREE(subreq);
 
-       if (!req) {
-               DEBUG(1,("Discarding unmatched reply with mid %d op %d\n", mid, op));
-               goto error;
+       if (!smbXcli_conn_is_connected(transport->conn)) {
+               return false;
        }
 
-       /* fill in the 'in' portion of the matching request */
-       req->in.buffer = buffer;
-       talloc_steal(req, buffer);
-       req->in.size = len;
-       req->in.allocated = req->in.size;
+       return true;
+}
+
+static void smbcli_transport_break_handler(struct tevent_req *subreq);
+static void smbcli_request_done(struct tevent_req *subreq);
 
-       /* handle NBT session replies */
-       if (req->in.size >= 4 && req->in.buffer[0] != 0) {
-               req->status = NT_STATUS_OK;
-               goto async;
+struct tevent_req *smbcli_transport_setup_subreq(struct smbcli_request *req)
+{
+       struct smbcli_transport *transport = req->transport;
+       uint8_t smb_command;
+       uint8_t additional_flags;
+       uint8_t clear_flags;
+       uint16_t additional_flags2;
+       uint16_t clear_flags2;
+       uint32_t pid;
+       uint16_t tid;
+       uint16_t uid;
+       uint32_t timeout_msec = transport->options.request_timeout * 1000;
+       struct iovec *bytes_iov = NULL;
+       struct tevent_req *subreq = NULL;
+
+       smb_command = SVAL(req->out.hdr, HDR_COM);
+       additional_flags = CVAL(req->out.hdr, HDR_FLG);
+       additional_flags2 = SVAL(req->out.hdr, HDR_FLG2);
+       pid  = SVAL(req->out.hdr, HDR_PID);
+       pid |= SVAL(req->out.hdr, HDR_PIDHIGH)<<16;
+       tid = SVAL(req->out.hdr, HDR_TID);
+       uid = SVAL(req->out.hdr, HDR_UID);
+
+       clear_flags = ~additional_flags;
+       clear_flags2 = ~additional_flags2;
+
+       bytes_iov = talloc(req, struct iovec);
+       if (bytes_iov == NULL) {
+               return NULL;
+       }
+       bytes_iov->iov_base = (void *)req->out.data;
+       bytes_iov->iov_len = req->out.data_size;
+
+       subreq = smb1cli_req_create(req,
+                                   transport->ev,
+                                   transport->conn,
+                                   smb_command,
+                                   additional_flags,
+                                   clear_flags,
+                                   additional_flags2,
+                                   clear_flags2,
+                                   timeout_msec,
+                                   pid,
+                                   tid,
+                                   uid,
+                                   req->out.wct,
+                                   (uint16_t *)req->out.vwv,
+                                   1, bytes_iov);
+       if (subreq == NULL) {
+               return NULL;
        }
 
-       /* handle non-SMB replies */
-       if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE) {
-               req->state = SMBCLI_REQUEST_ERROR;
-               goto error;
+       ZERO_STRUCT(req->out);
+
+       return subreq;
+}
+
+/*
+  put a request into the send queue
+*/
+void smbcli_transport_send(struct smbcli_request *req)
+{
+       struct smbcli_transport *transport = req->transport;
+       NTSTATUS status;
+       bool need_pending_break = false;
+       struct tevent_req *subreq = NULL;
+       size_t i;
+       size_t num_subreqs = 0;
+
+       if (transport->oplock.handler) {
+               need_pending_break = true;
+       }
+
+       if (transport->break_subreq) {
+               need_pending_break = false;
+       }
+
+       if (need_pending_break) {
+               subreq = smb1cli_req_create(transport,
+                                           transport->ev,
+                                           transport->conn,
+                                           0, /* smb_command */
+                                           0, /* additional_flags */
+                                           0, /* clear_flags */
+                                           0, /* additional_flags2 */
+                                           0, /* clear_flags2 */
+                                           0, /* timeout_msec */
+                                           0, /* pid */
+                                           0, /* tid */
+                                           0, /* uid */
+                                           0, /* wct */
+                                           NULL, /* vwv */
+                                           0, /* iov_count */
+                                           NULL); /* bytes_iov */
+               if (subreq != NULL) {
+                       smb1cli_req_set_mid(subreq, 0xFFFF);
+                       smbXcli_req_set_pending(subreq);
+                       tevent_req_set_callback(subreq,
+                                               smbcli_transport_break_handler,
+                                               transport);
+                       transport->break_subreq = subreq;
+                       subreq = NULL;
+               }
        }
 
-       if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)) {
-               DEBUG(2,("bad reply size for mid %d\n", mid));
-               req->status = NT_STATUS_UNSUCCESSFUL;
+       subreq = smbcli_transport_setup_subreq(req);
+       if (subreq == NULL) {
                req->state = SMBCLI_REQUEST_ERROR;
-               goto error;
+               req->status = NT_STATUS_NO_MEMORY;
+               return;
        }
 
-       req->in.hdr = hdr;
-       req->in.vwv = vwv;
-       req->in.wct = wct;
-       if (req->in.size >= NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)) {
-               req->in.data = req->in.vwv + VWV(wct) + 2;
-               req->in.data_size = SVAL(req->in.vwv, VWV(wct));
-               if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct) + req->in.data_size) {
-                       DEBUG(3,("bad data size for mid %d\n", mid));
-                       /* blergh - w2k3 gives a bogus data size values in some
-                          openX replies */
-                       req->in.data_size = req->in.size - (NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct));
+       for (i = 0; i < ARRAY_SIZE(req->subreqs); i++) {
+               if (req->subreqs[i] == NULL) {
+                       req->subreqs[i] = subreq;
+                       subreq = NULL;
+               }
+               if (req->subreqs[i] == NULL) {
+                       break;
                }
-       }
-       req->in.ptr = req->in.data;
-       req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
-
-       smb_setup_bufinfo(req);
 
-       if (!(req->flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
-               int eclass = CVAL(req->in.hdr,HDR_RCLS);
-               int code = SVAL(req->in.hdr,HDR_ERR);
-               if (eclass == 0 && code == 0) {
-                       transport->error.e.nt_status = NT_STATUS_OK;
-               } else {
-                       transport->error.e.nt_status = NT_STATUS_DOS(eclass, code);
+               if (!tevent_req_is_in_progress(req->subreqs[i])) {
+                       req->state = SMBCLI_REQUEST_ERROR;
+                       req->status = NT_STATUS_INTERNAL_ERROR;
+                       return;
                }
-       } else {
-               transport->error.e.nt_status = NT_STATUS(IVAL(req->in.hdr, HDR_RCLS));
        }
+       num_subreqs = i;
 
-       req->status = transport->error.e.nt_status;
-       if (NT_STATUS_IS_OK(req->status)) {
-               transport->error.etype = ETYPE_NONE;
-       } else {
-               transport->error.etype = ETYPE_SMB;
+       req->state = SMBCLI_REQUEST_RECV;
+       tevent_req_set_callback(req->subreqs[0], smbcli_request_done, req);
+
+       status = smb1cli_req_chain_submit(req->subreqs, num_subreqs);
+       if (!NT_STATUS_IS_OK(status)) {
+               smbXcli_conn_disconnect(transport->conn, status);
        }
+}
 
-       if (!smbcli_request_check_sign_mac(req)) {
-               transport->error.etype = ETYPE_SOCKET;
-               transport->error.e.socket_error = SOCKET_READ_BAD_SIG;
-               req->state = SMBCLI_REQUEST_ERROR;
-               req->status = NT_STATUS_ACCESS_DENIED;
-               goto error;
-       };
+static void smbcli_request_done(struct tevent_req *subreq)
+{
+       struct smbcli_request *req =
+               tevent_req_callback_data(subreq,
+               struct smbcli_request);
+       struct smbcli_transport *transport = req->transport;
+       ssize_t len;
+       size_t i;
+       uint8_t *hdr = NULL;
+       uint8_t wct = 0;
+       uint16_t *vwv = NULL;
+       uint32_t num_bytes = 0;
+       uint8_t *bytes = NULL;
+       struct iovec *recv_iov = NULL;
+       uint8_t *inbuf = NULL;
+
+       req->status = smb1cli_req_recv(req->subreqs[0], req,
+                                      &recv_iov,
+                                      &hdr,
+                                      &wct,
+                                      &vwv,
+                                      NULL, /* pvwv_offset */
+                                      &num_bytes,
+                                      &bytes,
+                                      NULL, /* pbytes_offset */
+                                      &inbuf,
+                                      NULL, 0); /* expected */
+       TALLOC_FREE(req->subreqs[0]);
+       if (!NT_STATUS_IS_OK(req->status)) {
+               if (recv_iov == NULL) {
+                       req->state = SMBCLI_REQUEST_ERROR;
+                       transport->error.e.nt_status = req->status;
+                       transport->error.etype = ETYPE_SOCKET;
+                       if (req->async.fn) {
+                               req->async.fn(req);
+                       }
+                       return;
+               }
+       }
 
-async:
-       /* if this request has an async handler then call that to
-          notify that the reply has been received. This might destroy
-          the request so it must happen last */
+       /*
+        * For SMBreadBraw hdr is NULL
+        */
+       len = recv_iov[0].iov_len;
+       for (i=1; hdr != NULL && i < 3; i++) {
+               uint8_t *p = recv_iov[i-1].iov_base;
+               uint8_t *c1 = recv_iov[i].iov_base;
+               uint8_t *c2 = p + recv_iov[i-1].iov_len;
 
-       req->state = SMBCLI_REQUEST_DONE;
+               len += recv_iov[i].iov_len;
 
-       if (req->recv_helper.fn) {
-               /*
-                * let the recv helper decide in
-                * what state the request really is
-                */
-               req->state = req->recv_helper.fn(req);
+               c2 += i;
+               len += i;
 
-               /* if more parts are needed, wait for them */
-               if (req->state <= SMBCLI_REQUEST_RECV) {
-                       return NT_STATUS_OK;
+               if (recv_iov[i].iov_len == 0) {
+                       continue;
                }
-       }
-       DLIST_REMOVE(transport->pending_recv, req);
-       if (req->async.fn) {
-               req->async.fn(req);
-       }
-       return NT_STATUS_OK;
 
-error:
-       if (req) {
-               DLIST_REMOVE(transport->pending_recv, req);
-               req->state = SMBCLI_REQUEST_ERROR;
-               if (req->async.fn) {
-                       req->async.fn(req);
+               if (c1 != c2) {
+                       req->state = SMBCLI_REQUEST_ERROR;
+                       req->status = NT_STATUS_INTERNAL_ERROR;
+                       transport->error.e.nt_status = req->status;
+                       transport->error.etype = ETYPE_SMB;
+                       if (req->async.fn) {
+                               req->async.fn(req);
+                       }
+                       return;
                }
-       } else {
-               talloc_free(buffer);
        }
-       return NT_STATUS_OK;
-}
-
-/*
-  process some read/write requests that are pending
-  return false if the socket is dead
-*/
-_PUBLIC_ bool smbcli_transport_process(struct smbcli_transport *transport)
-{
-       NTSTATUS status;
-       size_t npending;
 
-       packet_queue_run(transport->packet);
-       if (transport->socket->sock == NULL) {
-               return false;
-       }
+       /* fill in the 'in' portion of the matching request */
+       req->in.buffer = inbuf;
+       req->in.size = NBT_HDR_SIZE + len;
+       req->in.allocated = req->in.size;
 
-       status = socket_pending(transport->socket->sock, &npending);
-       if (NT_STATUS_IS_OK(status) && npending > 0) {
-               packet_recv(transport->packet);
-       }
-       if (transport->socket->sock == NULL) {
-               return false;
+       req->in.hdr = hdr;
+       req->in.vwv = (uint8_t *)vwv;
+       req->in.wct = wct;
+       req->in.data = bytes;
+       req->in.data_size = num_bytes;
+       req->in.ptr = req->in.data;
+       if (hdr != NULL) {
+               req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
        }
-       return true;
-}
 
-/*
-  handle timeouts of individual smb requests
-*/
-static void smbcli_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, 
-                                  struct timeval t, void *private_data)
-{
-       struct smbcli_request *req = talloc_get_type(private_data, struct smbcli_request);
+       smb_setup_bufinfo(req);
 
-       if (req->state == SMBCLI_REQUEST_RECV) {
-               DLIST_REMOVE(req->transport->pending_recv, req);
+       transport->error.e.nt_status = req->status;
+       if (NT_STATUS_IS_OK(req->status)) {
+               transport->error.etype = ETYPE_NONE;
+       } else {
+               transport->error.etype = ETYPE_SMB;
        }
-       req->status = NT_STATUS_IO_TIMEOUT;
-       req->state = SMBCLI_REQUEST_ERROR;
+
+       req->state = SMBCLI_REQUEST_DONE;
        if (req->async.fn) {
                req->async.fn(req);
        }
 }
 
-
-/*
-  destroy a request
-*/
-static int smbcli_request_destructor(struct smbcli_request *req)
-{
-       if (req->state == SMBCLI_REQUEST_RECV) {
-               DLIST_REMOVE(req->transport->pending_recv, req);
-       }
-       return 0;
-}
-
-
-/*
-  put a request into the send queue
-*/
-void smbcli_transport_send(struct smbcli_request *req)
+static void smbcli_transport_break_handler(struct tevent_req *subreq)
 {
-       DATA_BLOB blob;
+       struct smbcli_transport *transport =
+               tevent_req_callback_data(subreq,
+               struct smbcli_transport);
        NTSTATUS status;
-
-       /* check if the transport is dead */
-       if (req->transport->socket->sock == NULL) {
-               req->state = SMBCLI_REQUEST_ERROR;
-               req->status = NT_STATUS_NET_WRITE_FAULT;
-               return;
+       struct iovec *recv_iov = NULL;
+       uint8_t *hdr = NULL;
+       uint16_t *vwv = NULL;
+       const struct smb1cli_req_expected_response expected[] = {
+       {
+               .status = NT_STATUS_OK,
+               .wct = 8,
        }
-
-       blob = data_blob_const(req->out.buffer, req->out.size);
-       status = packet_send(req->transport->packet, blob);
+       };
+       uint16_t tid;
+       uint16_t fnum;
+       uint8_t level;
+
+       transport->break_subreq = NULL;
+
+       status = smb1cli_req_recv(subreq, transport,
+                                 &recv_iov,
+                                 &hdr,
+                                 NULL, /* pwct */
+                                 &vwv,
+                                 NULL, /* pvwv_offset */
+                                 NULL, /* pnum_bytes */
+                                 NULL, /* pbytes */
+                                 NULL, /* pbytes_offset */
+                                 NULL, /* pinbuf */
+                                 expected,
+                                 ARRAY_SIZE(expected));
+       TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
-               req->state = SMBCLI_REQUEST_ERROR;
-               req->status = status;
+               TALLOC_FREE(recv_iov);
+               smbcli_transport_dead(transport, status);
                return;
        }
 
-       packet_queue_run(req->transport->packet);
-       if (req->transport->socket->sock == NULL) {
-               req->state = SMBCLI_REQUEST_ERROR;
-               req->status = NT_STATUS_NET_WRITE_FAULT;
-               return;
-       }
-
-       if (req->one_way_request) {
-               req->state = SMBCLI_REQUEST_DONE;
-               smbcli_request_destroy(req);
-               return;
-       }
-
-       req->state = SMBCLI_REQUEST_RECV;
-       DLIST_ADD(req->transport->pending_recv, req);
-
-       /* add a timeout */
-       if (req->transport->options.request_timeout) {
-               tevent_add_timer(req->transport->socket->event.ctx, req,
-                               timeval_current_ofs(req->transport->options.request_timeout, 0), 
-                               smbcli_timeout_handler, req);
+       /*
+        * Setup the subreq to handle the
+        * next incoming SMB2 Break.
+        */
+       subreq = smb1cli_req_create(transport,
+                                   transport->ev,
+                                   transport->conn,
+                                   0, /* smb_command */
+                                   0, /* additional_flags */
+                                   0, /* clear_flags */
+                                   0, /* additional_flags2 */
+                                   0, /* clear_flags2 */
+                                   0, /* timeout_msec */
+                                   0, /* pid */
+                                   0, /* tid */
+                                   0, /* uid */
+                                   0, /* wct */
+                                   NULL, /* vwv */
+                                   0, /* iov_count */
+                                   NULL); /* bytes_iov */
+       if (subreq != NULL) {
+               smb1cli_req_set_mid(subreq, 0xFFFF);
+               smbXcli_req_set_pending(subreq);
+               tevent_req_set_callback(subreq,
+                                       smbcli_transport_break_handler,
+                                       transport);
+               transport->break_subreq = subreq;
+       }
+
+       tid = SVAL(hdr, HDR_TID);
+       fnum = SVAL(vwv+2, 0);
+       level = CVAL(vwv+3, 1);
+
+       TALLOC_FREE(recv_iov);
+
+       if (transport->oplock.handler) {
+               transport->oplock.handler(transport, tid, fnum, level,
+                                         transport->oplock.private_data);
+       } else {
+               DEBUG(5,("Got SMB oplock break with no handler\n"));
        }
 
-       talloc_set_destructor(req, smbcli_request_destructor);
 }
 
 
index b3d32273b2202d87637a6632d011ada97611a6f1..81bf715f0826aa98ce81ed0805b06a56d6535294 100644 (file)
@@ -25,6 +25,7 @@
 #include "../libcli/smb/smb_common.h"
 #include "libcli/raw/request.h"
 #include "librpc/gen_ndr/nbt.h"
+#include "libcli/raw/interfaces.h"
 
 struct smbcli_tree;  /* forward declare */
 struct smbcli_request;  /* forward declare */
@@ -52,23 +53,18 @@ struct smbcli_negotiate {
        enum protocol_types protocol;
 
        uint8_t sec_mode;               /* security mode returned by negprot */
-       uint8_t key_len;
-       DATA_BLOB server_guid;      /* server_guid */
        DATA_BLOB secblob;      /* cryptkey or negTokenInit blob */
        uint32_t sesskey;
-       
-       struct smb_signing_context sign_info;
 
        /* capabilities that the server reported */
        uint32_t capabilities;
        
        int server_zone;
        time_t server_time;
+
        unsigned int readbraw_supported:1;
        unsigned int writebraw_supported:1;
        unsigned int lockread_supported:1;
-
-       char *server_domain;
 };
        
 /* this is the context for a SMB socket associated with the socket itself */
@@ -109,24 +105,14 @@ struct smbcli_options {
 /* this is the context for the client transport layer */
 struct smbcli_transport {
        struct tevent_context *ev; /* TODO: remove this !!! */
+       struct smbXcli_conn *conn;
 
-       /* socket level info */
-       struct smbcli_socket *socket;
-
-       /* the next mid to be allocated - needed for signing and
-          request matching */
-       uint16_t next_mid;
-       
        /* negotiated protocol information */
        struct smbcli_negotiate negotiate;
 
        /* options to control the behaviour of the client code */
        struct smbcli_options options;
 
-       /* is a readbraw pending? we need to handle that case
-          specially on receiving packets */
-       unsigned int readbraw_pending:1;
-       
        /* an idle function - if this is defined then it will be
           called once every period microseconds while we are waiting
           for a packet */
@@ -134,6 +120,7 @@ struct smbcli_transport {
                void (*func)(struct smbcli_transport *, void *);
                void *private_data;
                unsigned int period;
+               struct tevent_timer *te;
        } idle;
 
        /* the error fields from the last message */
@@ -157,16 +144,7 @@ struct smbcli_transport {
                /* private data passed to the oplock handler */
                void *private_data;
        } oplock;
-
-       /* a list of async requests that are pending for receive on this connection */
-       struct smbcli_request *pending_recv;
-
-       /* remember the called name - some sub-protocols require us to
-          know the server name */
-       struct nbt_name called;
-
-       /* context of the stream -> packet parser */
-       struct packet_context *packet;
+       struct tevent_req *break_subreq;
 };
 
 /* this is the context for the user */
@@ -227,8 +205,8 @@ enum smbcli_request_state {SMBCLI_REQUEST_INIT, /* we are creating the request *
  * functions (similar to context.h, the server version).
  * This will allow requests to be multi-threaded. */
 struct smbcli_request {
-       /* allow a request to be part of a list of requests */
-       struct smbcli_request *next, *prev;
+       /* smbXcli_req */
+       struct tevent_req *subreqs[2];
 
        /* each request is in one of 4 possible states */
        enum smbcli_request_state state;
@@ -239,14 +217,6 @@ struct smbcli_request {
        struct smbcli_session *session;
        struct smbcli_tree *tree;
 
-       /* a receive helper, smbcli_transport_finish_recv will not call
-          req->async.fn callback handler unless the recv_helper returns
-          a value > SMBCLI_REQUEST_RECV. */
-       struct {
-               enum smbcli_request_state (*fn)(struct smbcli_request *);
-               void *private_data;
-       } recv_helper;
-
        /* the flags2 from the SMB request, in raw form (host byte
           order). Used to parse strings */
        uint16_t flags2;
@@ -254,20 +224,6 @@ struct smbcli_request {
        /* the NT status for this request. Set by packet receive code
           or code detecting error. */
        NTSTATUS status;
-       
-       /* the sequence number of this packet - used for signing */
-       unsigned int seq_num;
-
-       /* list of ntcancel request for this requests */
-       struct smbcli_request *ntcancel;
-
-       /* set if this is a one-way request, meaning we are not
-          expecting a reply from the server. */
-       unsigned int one_way_request:1;
-
-       /* set this when the request should only increment the signing
-          counter by one */
-       unsigned int sign_single_increment:1;
 
        /* the caller wants to do the signing check */
        bool sign_caller_checks;
@@ -275,12 +231,12 @@ struct smbcli_request {
        /* give the caller a chance to prevent the talloc_free() in the _recv() function */
        bool do_not_free;
 
-       /* the mid of this packet - used to match replies */
-       uint16_t mid;
-
        struct smb_request_buffer in;
        struct smb_request_buffer out;
 
+       struct smb_trans2 trans2;
+       struct smb_nttrans nttrans;
+
        /* information on what to do with a reply when it is received
           asyncronously. If this is not setup when a reply is received then
           the reply is discarded
@@ -307,8 +263,6 @@ struct smbcli_request {
       goto failed; \
 }
 
-#include "libcli/raw/interfaces.h"
-
 NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms);
 struct smbcli_request *smb_raw_read_send(struct smbcli_tree *tree, union smb_read *parms);
 NTSTATUS smb_raw_trans_recv(struct smbcli_request *req,
@@ -379,6 +333,4 @@ NTSTATUS smb_raw_trans(struct smbcli_tree *tree,
                       TALLOC_CTX *mem_ctx,
                       struct smb_trans2 *parms);
 
-void smbcli_sock_dead(struct smbcli_socket *sock);
-
 #endif /* __LIBCLI_RAW__H__ */
index 9d6c9ffaf27f36d7c4a5ce0a697d54bf2c35a3b9..9b0ed38cf0c1a55c000d23a671018b9de6048ede 100644 (file)
 */
 
 #include "includes.h"
+#include <tevent.h>
+#include "system/time.h"
 #include "libcli/raw/libcliraw.h"
 #include "libcli/raw/raw_proto.h"
-#include "system/time.h"
+#include "../libcli/smb/smbXcli_base.h"
+#include "../lib/util/tevent_ntstatus.h"
 
-static const struct {
-       enum protocol_types prot;
-       const char *name;
-} prots[] = {
-       {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
-       {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
-       {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
-       {PROTOCOL_LANMAN1,"LANMAN1.0"},
-       {PROTOCOL_LANMAN1,"Windows for Workgroups 3.1a"},
-       {PROTOCOL_LANMAN2,"LM1.2X002"},
-       {PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
-       {PROTOCOL_LANMAN2,"LANMAN2.1"},
-       {PROTOCOL_LANMAN2,"Samba"},
-       {PROTOCOL_NT1,"NT LANMAN 1.0"},
-       {PROTOCOL_NT1,"NT LM 0.12"},
-#if 0
-       /* we don't yet handle chaining a SMB transport onto SMB2 */
-       {PROTOCOL_SMB2_02,"SMB 2.002"},
-#endif
+struct smb_raw_negotiate_state {
+       struct smbcli_transport *transport;
 };
 
-/*
-  Send a negprot command.
-*/
-struct smbcli_request *smb_raw_negotiate_send(struct smbcli_transport *transport, 
-                                             bool unicode,
-                                             int maxprotocol)
-{
-       struct smbcli_request *req;
-       int i;
-       uint16_t flags2 = 0;
+static void smb_raw_negotiate_done(struct tevent_req *subreq);
 
-       req = smbcli_request_setup_transport(transport, SMBnegprot, 0, 0);
-       if (!req) {
+struct tevent_req *smb_raw_negotiate_send(TALLOC_CTX *mem_ctx,
+                                         struct tevent_context *ev,
+                                         struct smbcli_transport *transport,
+                                         int maxprotocol)
+{
+       struct tevent_req *req;
+       struct smb_raw_negotiate_state *state;
+       struct tevent_req *subreq;
+       uint32_t timeout_msec = transport->options.request_timeout * 1000;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct smb_raw_negotiate_state);;
+       if (req == NULL) {
                return NULL;
        }
-
-       if (transport->options.ntstatus_support) {
-               flags2 |= FLAGS2_32_BIT_ERROR_CODES;
-       }
-
-       if (unicode) {
-               flags2 |= FLAGS2_UNICODE_STRINGS;
-       }
-       flags2 |= FLAGS2_EXTENDED_ATTRIBUTES;
-       flags2 |= FLAGS2_LONG_PATH_COMPONENTS;
-       flags2 |= FLAGS2_IS_LONG_NAME;
-
-       if (transport->options.use_spnego) {
-               flags2 |= FLAGS2_EXTENDED_SECURITY;
-       }
-
-       SSVAL(req->out.hdr,HDR_FLG2, flags2);
-
-       /* setup the protocol strings */
-       for (i=0; i < ARRAY_SIZE(prots) && prots[i].prot <= maxprotocol; i++) {
-               smbcli_req_append_bytes(req, (const uint8_t *)"\2", 1);
-               smbcli_req_append_string(req, prots[i].name, STR_TERMINATE | STR_ASCII);
-       }
-
-       if (!smbcli_request_send(req)) {
-               smbcli_request_destroy(req);
-               return NULL;
+       state->transport = transport;
+
+       subreq = smbXcli_negprot_send(state, ev,
+                                     transport->conn,
+                                     timeout_msec,
+                                     PROTOCOL_CORE,
+                                     maxprotocol);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
        }
+       tevent_req_set_callback(subreq, smb_raw_negotiate_done, req);
 
        return req;
 }
 
-/*
- Send a negprot command.
-*/
-NTSTATUS smb_raw_negotiate_recv(struct smbcli_request *req)
+static void smb_raw_negotiate_done(struct tevent_req *subreq)
 {
-       struct smbcli_transport *transport = req->transport;
-       int protocol;
-
-       if (!smbcli_request_receive(req) ||
-           smbcli_request_is_error(req)) {
-               return smbcli_request_destroy(req);
+       struct tevent_req *req =
+               tevent_req_callback_data(subreq,
+               struct tevent_req);
+       struct smb_raw_negotiate_state *state =
+               tevent_req_data(req,
+               struct smb_raw_negotiate_state);
+       struct smbcli_negotiate *n = &state->transport->negotiate;
+       struct smbXcli_conn *c = state->transport->conn;
+       NTSTATUS status;
+       NTTIME ntt;
+
+       status = smbXcli_negprot_recv(subreq);
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               return;
        }
 
-       SMBCLI_CHECK_MIN_WCT(req, 1);
-
-       protocol = SVALS(req->in.vwv, VWV(0));
+       n->protocol = smbXcli_conn_protocol(c);
 
-       if (protocol >= ARRAY_SIZE(prots) || protocol < 0) {
-               req->status = NT_STATUS_UNSUCCESSFUL;
-               return smbcli_request_destroy(req);
-       }
-
-       transport->negotiate.protocol = prots[protocol].prot;
-
-       if (transport->negotiate.protocol >= PROTOCOL_NT1) {
-               NTTIME ntt;
-
-               /* NT protocol */
-               SMBCLI_CHECK_WCT(req, 17);
-               transport->negotiate.sec_mode = CVAL(req->in.vwv,VWV(1));
-               transport->negotiate.max_mux  = SVAL(req->in.vwv,VWV(1)+1);
-               transport->negotiate.max_xmit = IVAL(req->in.vwv,VWV(3)+1);
-               transport->negotiate.sesskey  = IVAL(req->in.vwv,VWV(7)+1);
-               transport->negotiate.capabilities = IVAL(req->in.vwv,VWV(9)+1);
-
-               /* this time arrives in real GMT */
-               ntt = smbcli_pull_nttime(req->in.vwv, VWV(11)+1);
-               transport->negotiate.server_time = nt_time_to_unix(ntt);                
-               transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(15)+1) * 60;
-               transport->negotiate.key_len = CVAL(req->in.vwv,VWV(16)+1);
-
-               if (transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
-                       if (req->in.data_size < 16) {
-                               goto failed;
-                       }
-                       transport->negotiate.server_guid = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, 16);
-                       transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data + 16, req->in.data_size - 16);
-               } else {
-                       if (req->in.data_size < (transport->negotiate.key_len)) {
-                               goto failed;
-                       }
-                       transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, transport->negotiate.key_len);
-                       smbcli_req_pull_string(&req->in.bufinfo, transport, &transport->negotiate.server_domain,
-                                           req->in.data+transport->negotiate.key_len,
-                                           req->in.data_size-transport->negotiate.key_len, STR_UNICODE|STR_NOALIGN);
-                       /* here comes the server name */
-               }
+       n->sec_mode = smb1cli_conn_server_security_mode(c);
+       n->max_mux  = smbXcli_conn_max_requests(c);
+       n->max_xmit = smb1cli_conn_max_xmit(c);
+       n->sesskey  = smb1cli_conn_server_session_key(c);
+       n->capabilities = smb1cli_conn_capabilities(c);;
 
-               if (transport->negotiate.capabilities & CAP_RAW_MODE) {
-                       transport->negotiate.readbraw_supported = true;
-                       transport->negotiate.writebraw_supported = true;
-               }
+       /* this time arrives in real GMT */
+       ntt = smbXcli_conn_server_system_time(c);
+       n->server_time = nt_time_to_unix(ntt);
+       n->server_zone = smb1cli_conn_server_time_zone(c);
 
-               if (transport->negotiate.capabilities & CAP_LOCK_AND_READ)
-                       transport->negotiate.lockread_supported = true;
-       } else if (transport->negotiate.protocol >= PROTOCOL_LANMAN1) {
-               SMBCLI_CHECK_WCT(req, 13);
-               transport->negotiate.sec_mode = SVAL(req->in.vwv,VWV(1));
-               transport->negotiate.max_xmit = SVAL(req->in.vwv,VWV(2));
-               transport->negotiate.sesskey =  IVAL(req->in.vwv,VWV(6));
-               transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(10)) * 60;
-               
-               /* this time is converted to GMT by raw_pull_dos_date */
-               transport->negotiate.server_time = raw_pull_dos_date(transport,
-                                                                    req->in.vwv+VWV(8));
-               if ((SVAL(req->in.vwv,VWV(5)) & 0x1)) {
-                       transport->negotiate.readbraw_supported = 1;
-               }
-               if ((SVAL(req->in.vwv,VWV(5)) & 0x2)) {
-                       transport->negotiate.writebraw_supported = 1;
+       if (n->capabilities & CAP_EXTENDED_SECURITY) {
+               const DATA_BLOB *b = smbXcli_conn_server_gss_blob(c);
+               if (b) {
+                       n->secblob = *b;
                }
-               transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, 
-                                                                req->in.data, req->in.data_size);
        } else {
-               /* the old core protocol */
-               transport->negotiate.sec_mode = 0;
-               transport->negotiate.server_time = time(NULL);
-               transport->negotiate.max_xmit = transport->options.max_xmit;
-               transport->negotiate.server_zone = get_time_zone(transport->negotiate.server_time);
-       }
-
-       /* a way to force ascii SMB */
-       if (!transport->options.unicode) {
-               transport->negotiate.capabilities &= ~CAP_UNICODE;
+               const uint8_t *p = smb1cli_conn_server_challenge(c);
+               if (p) {
+                       n->secblob = data_blob_const(p, 8);
+               }
        }
 
-       if (!transport->options.ntstatus_support) {
-               transport->negotiate.capabilities &= ~CAP_STATUS32;
-       }
+       n->readbraw_supported = smb1cli_conn_server_readbraw(c);
+       n->readbraw_supported = smb1cli_conn_server_writebraw(c);
+       n->lockread_supported = smb1cli_conn_server_lockread(c);
 
-       if (!transport->options.use_level2_oplocks) {
-               transport->negotiate.capabilities &= ~CAP_LEVEL_II_OPLOCKS;
-       }
+       tevent_req_done(req);
+}
 
-failed:
-       return smbcli_request_destroy(req);
+/*
+ Send a negprot command.
+*/
+NTSTATUS smb_raw_negotiate_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
 }
 
 
@@ -207,6 +129,27 @@ failed:
 */
 NTSTATUS smb_raw_negotiate(struct smbcli_transport *transport, bool unicode, int maxprotocol)
 {
-       struct smbcli_request *req = smb_raw_negotiate_send(transport, unicode, maxprotocol);
-       return smb_raw_negotiate_recv(req);
+       NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
+       struct tevent_req *subreq = NULL;
+       bool ok;
+
+       subreq = smb_raw_negotiate_send(transport,
+                                       transport->ev,
+                                       transport,
+                                       maxprotocol);
+       if (subreq == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ok = tevent_req_poll(subreq, transport->ev);
+       if (!ok) {
+               status = map_nt_error_from_unix_common(errno);
+               goto failed;
+       }
+
+       status = smb_raw_negotiate_recv(subreq);
+
+failed:
+       TALLOC_FREE(subreq);
+       return status;
 }
index 40256aa405f5ca2f1867bfaa1f244aad64971ce4..dcb979b28ae9626accce0a5e25930beda7cc26be 100644 (file)
@@ -18,9 +18,9 @@
 */
 
 #include "includes.h"
+#include <tevent.h>
 #include "libcli/raw/libcliraw.h"
 #include "libcli/raw/raw_proto.h"
-#include "../lib/util/dlinklist.h"
 
 /****************************************************************************
 change notify (async send)
@@ -100,38 +100,6 @@ _PUBLIC_ NTSTATUS smb_raw_changenotify_recv(struct smbcli_request *req,
        return NT_STATUS_OK;
 }
 
-/****************************************************************************
-  handle ntcancel replies from the server,
-  as the MID of the real reply and the ntcancel reply is the same
-  we need to do find out to what request the reply belongs
-****************************************************************************/
-struct smbcli_request *smbcli_handle_ntcancel_reply(struct smbcli_request *req,
-                                                   size_t len, const uint8_t *hdr)
-{
-       struct smbcli_request *ntcancel;
-
-       if (!req) return req;
-
-       if (!req->ntcancel) return req;
-
-       if (len >= MIN_SMB_SIZE + NBT_HDR_SIZE &&
-           (CVAL(hdr, HDR_FLG) & FLAG_REPLY) &&
-            CVAL(hdr,HDR_COM) == SMBntcancel) {
-               ntcancel = req->ntcancel;
-               DLIST_REMOVE(req->ntcancel, ntcancel);
-
-               /*
-                * TODO: untill we understand how the 
-                *       smb_signing works for this case we 
-                *       return NULL, to just ignore the packet
-                */
-               /*return ntcancel;*/
-               return NULL;
-       }
-
-       return req;
-}
-
 /****************************************************************************
  Send a NT Cancel request - used to hurry along a pending request. Usually
  used to cancel a pending change notify request
@@ -139,30 +107,16 @@ struct smbcli_request *smbcli_handle_ntcancel_reply(struct smbcli_request *req,
 ****************************************************************************/
 NTSTATUS smb_raw_ntcancel(struct smbcli_request *oldreq)
 {
-       struct smbcli_request *req;
-
-       req = smbcli_request_setup_transport(oldreq->transport, SMBntcancel, 0, 0);
-
-       SSVAL(req->out.hdr, HDR_MID, SVAL(oldreq->out.hdr, HDR_MID));   
-       SSVAL(req->out.hdr, HDR_PID, SVAL(oldreq->out.hdr, HDR_PID));   
-       SSVAL(req->out.hdr, HDR_TID, SVAL(oldreq->out.hdr, HDR_TID));   
-       SSVAL(req->out.hdr, HDR_UID, SVAL(oldreq->out.hdr, HDR_UID));   
+       bool ok;
 
-       /* this request does not expect a reply, so tell the signing
-          subsystem not to allocate an id for a reply */
-       req->sign_single_increment = 1;
-       req->one_way_request = 1;
-
-       /* 
-        * smbcli_request_send() free's oneway requests
-        * but we want to keep it under oldreq->ntcancel
-        */
-       req->do_not_free = true;
-       talloc_steal(oldreq, req);
-
-       smbcli_request_send(req);
+       if (oldreq->subreqs[0] == NULL) {
+               return NT_STATUS_OK;
+       }
 
-       DLIST_ADD_END(oldreq->ntcancel, req, struct smbcli_request *);
+       ok = tevent_req_cancel(oldreq->subreqs[0]);
+       if (!ok) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
 
        return NT_STATUS_OK;
 }
index 68977ebd3e04bf531f18735250cb4e9810041046..d3f5518e01a36efb7021a4897575efb969214539 100644 (file)
@@ -104,12 +104,6 @@ _PUBLIC_ struct smbcli_request *smb_raw_read_send(struct smbcli_tree *tree, unio
                return NULL;
        }
 
-       /* the transport layer needs to know that a readbraw is pending
-          and handle receives a little differently */
-       if (parms->generic.level == RAW_READ_READBRAW) {
-               tree->session->transport->readbraw_pending = 1;
-       }
-
        return req;
 }
 
index ae68fb0cd36ee6592cfd642a61ad3af6a80a9d45..1b4c8c7524aa926a21217e0002b6d611cd39a2ae 100644 (file)
 #include "includes.h"
 #include "libcli/raw/libcliraw.h"
 #include "libcli/raw/raw_proto.h"
-#include "../lib/util/dlinklist.h"
 #include "lib/events/events.h"
 #include "librpc/ndr/libndr.h"
 #include "librpc/gen_ndr/ndr_misc.h"
+#include "../libcli/smb/smbXcli_base.h"
 
 /* we over allocate the data buffer to prevent too many realloc calls */
 #define REQ_OVER_ALLOCATION 0
@@ -59,12 +59,6 @@ _PUBLIC_ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
           _send() call fails completely */
        if (!req) return NT_STATUS_UNSUCCESSFUL;
 
-       if (req->transport) {
-               /* remove it from the list of pending requests (a null op if
-                  its not in the list) */
-               DLIST_REMOVE(req->transport->pending_recv, req);
-       }
-
        if (req->state == SMBCLI_REQUEST_ERROR &&
            NT_STATUS_IS_OK(req->status)) {
                req->status = NT_STATUS_INTERNAL_ERROR;
@@ -81,52 +75,34 @@ _PUBLIC_ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
 
 
 /*
-  low-level function to setup a request buffer for a non-SMB packet 
-  at the transport level
+  setup a SMB packet at transport level
 */
-struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, size_t size)
+struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
+                                                     uint8_t command, unsigned int wct, unsigned int buflen)
 {
        struct smbcli_request *req;
+       size_t size;
 
-       req = talloc(transport, struct smbcli_request);
+       size = NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen;
+
+       req = talloc_zero(transport, struct smbcli_request);
        if (!req) {
                return NULL;
        }
-       ZERO_STRUCTP(req);
 
        /* setup the request context */
        req->state = SMBCLI_REQUEST_INIT;
        req->transport = transport;
-       req->session = NULL;
-       req->tree = NULL;
        req->out.size = size;
 
        /* over allocate by a small amount */
        req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 
 
-       req->out.buffer = talloc_array(req, uint8_t, req->out.allocated);
+       req->out.buffer = talloc_zero_array(req, uint8_t, req->out.allocated);
        if (!req->out.buffer) {
                return NULL;
        }
 
-       SIVAL(req->out.buffer, 0, 0);
-
-       return req;
-}
-
-
-/*
-  setup a SMB packet at transport level
-*/
-struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
-                                                     uint8_t command, unsigned int wct, unsigned int buflen)
-{
-       struct smbcli_request *req;
-
-       req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
-
-       if (!req) return NULL;
-       
        req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
        req->out.vwv = req->out.hdr + HDR_VWV;
        req->out.wct = wct;
@@ -143,15 +119,10 @@ struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *t
        SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
        SSVAL(req->out.hdr,HDR_FLG2, 0);
 
-       if (command != SMBtranss && command != SMBtranss2) {
-               /* assign a mid */
-               req->mid = smbcli_transport_next_mid(transport);
-       }
-
        /* copy the pid, uid and mid to the request */
        SSVAL(req->out.hdr, HDR_PID, 0);
        SSVAL(req->out.hdr, HDR_UID, 0);
-       SSVAL(req->out.hdr, HDR_MID, req->mid);
+       SSVAL(req->out.hdr, HDR_MID, 0);
        SSVAL(req->out.hdr, HDR_TID,0);
        SSVAL(req->out.hdr, HDR_PIDHIGH,0);
        SIVAL(req->out.hdr, HDR_RCLS, 0);
@@ -276,56 +247,143 @@ NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
                                      uint8_t command, 
                                      unsigned int wct, size_t buflen)
 {
-       unsigned int new_size = 1 + (wct*2) + 2 + buflen;
+       size_t wct_ofs;
+       size_t size;
 
-       SSVAL(req->out.vwv, VWV(0), command);
-       SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
+       /*
+        * here we only support one chained command
+        * If someone needs longer chains, the low
+        * level code should be used directly.
+        */
+       if (req->subreqs[0] != NULL) {
+               return NT_STATUS_INVALID_PARAMETER_MIX;
+       }
+       if (req->subreqs[1] != NULL) {
+               return NT_STATUS_INVALID_PARAMETER_MIX;
+       }
 
-       smbcli_req_grow_allocation(req, req->out.data_size + new_size);
+       req->subreqs[0] = smbcli_transport_setup_subreq(req);
+       if (req->subreqs[0] == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       wct_ofs = smb1cli_req_wct_ofs(req->subreqs, 1);
+
+       size = NBT_HDR_SIZE + wct_ofs + 1 + VWV(wct) + 2 + buflen;
+
+       req->out.size = size;
 
-       req->out.vwv = req->out.buffer + req->out.size + 1;
-       SCVAL(req->out.vwv, -1, wct);
+       /* over allocate by a small amount */
+       req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
+
+       req->out.buffer = talloc_zero_array(req, uint8_t, req->out.allocated);
+       if (!req->out.buffer) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
+       req->out.vwv = req->out.hdr + wct_ofs;
+       req->out.wct = wct;
+       req->out.data = req->out.vwv + VWV(wct) + 2;
+       req->out.data_size = buflen;
+       req->out.ptr = req->out.data;
+
+       SCVAL(req->out.hdr, HDR_WCT, wct);
        SSVAL(req->out.vwv, VWV(wct), buflen);
 
-       req->out.size += new_size;
-       req->out.data_size += new_size;
+       memcpy(req->out.hdr, "\377SMB", 4);
+       SCVAL(req->out.hdr,HDR_COM,command);
+
+       SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
+       SSVAL(req->out.hdr,HDR_FLG2, 0);
+
+       /* copy the pid, uid and mid to the request */
+       SSVAL(req->out.hdr, HDR_PID, 0);
+       SSVAL(req->out.hdr, HDR_UID, 0);
+       SSVAL(req->out.hdr, HDR_MID, 0);
+       SSVAL(req->out.hdr, HDR_TID,0);
+       SSVAL(req->out.hdr, HDR_PIDHIGH,0);
+       SIVAL(req->out.hdr, HDR_RCLS, 0);
+       memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
+
+       if (req->session != NULL) {
+               SSVAL(req->out.hdr, HDR_FLG2, req->session->flags2);
+               SSVAL(req->out.hdr, HDR_PID, req->session->pid & 0xFFFF);
+               SSVAL(req->out.hdr, HDR_PIDHIGH, req->session->pid >> 16);
+               SSVAL(req->out.hdr, HDR_UID, req->session->vuid);
+       }
+
+       if (req->tree != NULL) {
+               SSVAL(req->out.hdr, HDR_TID, req->tree->tid);
+       }
 
        return NT_STATUS_OK;
 }
 
 /*
-  aadvance to the next chained reply in a request
+  advance to the next chained reply in a request
 */
 NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
 {
-       uint8_t *buffer;
-
-       if (CVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) {
-               return NT_STATUS_NOT_FOUND;
+       struct smbcli_transport *transport = req->transport;
+       uint8_t *hdr = NULL;
+       uint8_t wct = 0;
+       uint16_t *vwv = NULL;
+       uint32_t num_bytes = 0;
+       uint8_t *bytes = NULL;
+       struct iovec *recv_iov = NULL;
+       uint8_t *inbuf = NULL;
+
+       if (req->subreqs[0] != NULL) {
+               return NT_STATUS_INVALID_PARAMETER_MIX;
        }
-
-       buffer = req->in.hdr + SVAL(req->in.vwv, VWV(1));
-
-       if (buffer + 3 > req->in.buffer + req->in.size) {
-               return NT_STATUS_BUFFER_TOO_SMALL;
+       if (req->subreqs[1] == NULL) {
+               return NT_STATUS_INVALID_PARAMETER_MIX;
        }
 
-       req->in.vwv = buffer + 1;
-       req->in.wct = CVAL(buffer, 0);
-       if (buffer + 3 + req->in.wct*2 > req->in.buffer + req->in.size) {
-               return NT_STATUS_BUFFER_TOO_SMALL;
+       req->status = smb1cli_req_recv(req->subreqs[1], req,
+                                      &recv_iov,
+                                      &hdr,
+                                      &wct,
+                                      &vwv,
+                                      NULL, /* pvwv_offset */
+                                      &num_bytes,
+                                      &bytes,
+                                      NULL, /* pbytes_offset */
+                                      &inbuf,
+                                      NULL, 0); /* expected */
+       TALLOC_FREE(req->subreqs[1]);
+       if (!NT_STATUS_IS_OK(req->status)) {
+               if (recv_iov == NULL) {
+                       req->state = SMBCLI_REQUEST_ERROR;
+                       return req->status;
+               }
        }
-       req->in.data = req->in.vwv + 2 + req->in.wct * 2;
-       req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
 
-       /* fix the bufinfo */
+       /* fill in the 'in' portion of the matching request */
+       req->in.buffer = inbuf;
+       req->in.size = NBT_HDR_SIZE + PTR_DIFF(bytes, hdr) + num_bytes;
+       req->in.allocated = req->in.size;
+
+       req->in.hdr = hdr;
+       req->in.vwv = (uint8_t *)vwv;
+       req->in.wct = wct;
+       req->in.data = bytes;
+       req->in.data_size = num_bytes;
+       req->in.ptr = req->in.data;
+       req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
+
        smb_setup_bufinfo(req);
 
-       if (buffer + 3 + req->in.wct*2 + req->in.data_size > 
-           req->in.buffer + req->in.size) {
-               return NT_STATUS_BUFFER_TOO_SMALL;
+       transport->error.e.nt_status = req->status;
+       if (NT_STATUS_IS_OK(req->status)) {
+               transport->error.etype = ETYPE_NONE;
+       } else {
+               transport->error.etype = ETYPE_SMB;
        }
 
+       req->state = SMBCLI_REQUEST_DONE;
+
        return NT_STATUS_OK;
 }
 
@@ -335,14 +393,7 @@ NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
 */
 bool smbcli_request_send(struct smbcli_request *req)
 {
-       if (IVAL(req->out.buffer, 0) == 0) {
-               _smb_setlen_nbt(req->out.buffer, req->out.size - NBT_HDR_SIZE);
-       }
-
-       smbcli_request_calculate_sign_mac(req);
-
        smbcli_transport_send(req);
-
        return true;
 }
 
@@ -366,34 +417,6 @@ bool smbcli_request_receive(struct smbcli_request *req)
        return req->state == SMBCLI_REQUEST_DONE;
 }
 
-
-/*
-  handle oplock break requests from the server - return true if the request was
-  an oplock break
-*/
-bool smbcli_handle_oplock_break(struct smbcli_transport *transport, unsigned int len, const uint8_t *hdr, const uint8_t *vwv)
-{
-       /* we must be very fussy about what we consider an oplock break to avoid
-          matching readbraw replies */
-       if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
-           (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
-           CVAL(hdr,HDR_COM) != SMBlockingX ||
-           SVAL(hdr, HDR_MID) != 0xFFFF ||
-           SVAL(vwv,VWV(6)) != 0 ||
-           SVAL(vwv,VWV(7)) != 0) {
-               return false;
-       }
-
-       if (transport->oplock.handler) {
-               uint16_t tid = SVAL(hdr, HDR_TID);
-               uint16_t fnum = SVAL(vwv,VWV(2));
-               uint8_t level = CVAL(vwv,VWV(3)+1);
-               transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private_data);
-       }
-
-       return true;
-}
-
 /*
   wait for a reply to be received for a packet that just returns an error
   code and nothing more
index dd017715c7e69fc24539069451e10eb3cf178765..8e16e5b911316cd658c41737c7bb120f56388110 100644 (file)
 */
 
 #include "includes.h"
-#include "../lib/util/dlinklist.h"
+#include <tevent.h>
 #include "libcli/raw/libcliraw.h"
 #include "libcli/raw/raw_proto.h"
+#include "../libcli/smb/smbXcli_base.h"
 
-#define TORTURE_TRANS_DATA 0
+static void smb_raw_trans_backend_done(struct tevent_req *subreq);
 
-/*
-  check out of bounds for incoming data
-*/
-static bool raw_trans_oob(struct smbcli_request *req,
-                         unsigned int offset, unsigned int count)
-{
-       uint8_t *ptr;
-
-       if (count == 0) {
-               return false;
-       }
-
-       ptr = req->in.hdr + offset;
-       
-       /* be careful with wraparound! */
-       if ((uintptr_t)ptr < (uintptr_t)req->in.data ||
-           (uintptr_t)ptr >= (uintptr_t)req->in.data + req->in.data_size ||
-           count > req->in.data_size ||
-           (uintptr_t)ptr + count > (uintptr_t)req->in.data + req->in.data_size) {
-               return true;
-       }
-       return false;   
-}
-
-static size_t raw_trans_space_left(struct smbcli_request *req)
-{
-       if (req->transport->negotiate.max_xmit <= req->out.size) {
-               return 0;
-       }
-
-       return req->transport->negotiate.max_xmit - req->out.size;
-}
-
-struct smb_raw_trans2_recv_state {
-       uint8_t command;
-       uint32_t params_total;
-       uint32_t data_total;
-       uint32_t params_left;
-       uint32_t data_left;
-       bool got_first;
-       uint32_t recvd_data;
-       uint32_t recvd_param;
-       struct smb_trans2 io;
-};
-
-NTSTATUS smb_raw_trans2_recv(struct smbcli_request *req,
-                            TALLOC_CTX *mem_ctx,
-                            struct smb_trans2 *parms)
-{
-       struct smb_raw_trans2_recv_state *state;
-
-       if (!smbcli_request_receive(req) ||
-           smbcli_request_is_error(req)) {
-               goto failed;
-       }
-
-       state = talloc_get_type(req->recv_helper.private_data,
-                               struct smb_raw_trans2_recv_state);
-
-       parms->out = state->io.out;
-       talloc_steal(mem_ctx, parms->out.setup);
-       talloc_steal(mem_ctx, parms->out.params.data);
-       talloc_steal(mem_ctx, parms->out.data.data);
-       talloc_free(state);
-
-       ZERO_STRUCT(req->recv_helper);
-
-failed:
-       return smbcli_request_destroy(req);
-}
-
-static enum smbcli_request_state smb_raw_trans2_ship_rest(struct smbcli_request *req,
-                                                         struct smb_raw_trans2_recv_state *state);
-
-/*
- * This helper returns SMBCLI_REQUEST_RECV until all data has arrived
- */
-static enum smbcli_request_state smb_raw_trans2_recv_helper(struct smbcli_request *req)
-{
-       struct smb_raw_trans2_recv_state *state = talloc_get_type(req->recv_helper.private_data,
-                                                 struct smb_raw_trans2_recv_state);
-       uint16_t param_count, param_ofs, param_disp;
-       uint16_t data_count, data_ofs, data_disp;
-       uint16_t total_data, total_param;
-       uint8_t setup_count;
-
-       /*
-        * An NT RPC pipe call can return ERRDOS, ERRmoredata
-        * to a trans call. This is not an error and should not
-        * be treated as such.
-        */
-       if (smbcli_request_is_error(req)) {
-               goto failed;
-       }
-
-       if (state->params_left > 0 || state->data_left > 0) {
-               return smb_raw_trans2_ship_rest(req, state);
-       }
-
-       SMBCLI_CHECK_MIN_WCT(req, 10);
-
-       total_data = SVAL(req->in.vwv, VWV(1));
-       total_param = SVAL(req->in.vwv, VWV(0));
-       setup_count = CVAL(req->in.vwv, VWV(9));
-
-       param_count = SVAL(req->in.vwv, VWV(3));
-       param_ofs   = SVAL(req->in.vwv, VWV(4));
-       param_disp  = SVAL(req->in.vwv, VWV(5));
-
-       data_count = SVAL(req->in.vwv, VWV(6));
-       data_ofs   = SVAL(req->in.vwv, VWV(7));
-       data_disp  = SVAL(req->in.vwv, VWV(8));
-
-       if (!state->got_first) {
-               if (total_param > 0) {
-                       state->io.out.params = data_blob_talloc(state, NULL, total_param);
-                       if (!state->io.out.params.data) {
-                               goto nomem;
-                       }
-               }
-
-               if (total_data > 0) {
-                       state->io.out.data = data_blob_talloc(state, NULL, total_data);
-                       if (!state->io.out.data.data) {
-                               goto nomem;
-                       }
-               }
-
-               if (setup_count > 0) {
-                       uint16_t i;
-
-                       SMBCLI_CHECK_WCT(req, 10 + setup_count);
-
-                       state->io.out.setup_count = setup_count;
-                       state->io.out.setup = talloc_array(state, uint16_t, setup_count);
-                       if (!state->io.out.setup) {
-                               goto nomem;
-                       }
-                       for (i=0; i < setup_count; i++) {
-                               state->io.out.setup[i] = SVAL(req->in.vwv, VWV(10+i));
-                       }
-               }
-
-               state->got_first = true;
-       }
-
-       if (total_data > state->io.out.data.length ||
-           total_param > state->io.out.params.length) {
-               /* they must *only* shrink */
-               DEBUG(1,("smb_raw_trans2_recv_helper: data/params expanded!\n"));
-               req->status = NT_STATUS_BUFFER_TOO_SMALL;
-               goto failed;
-       }
-
-       state->io.out.data.length = total_data;
-       state->io.out.params.length = total_param;
-
-       if (data_count + data_disp > total_data ||
-           param_count + param_disp > total_param) {
-               DEBUG(1,("smb_raw_trans2_recv_helper: Buffer overflow\n"));
-               req->status = NT_STATUS_BUFFER_TOO_SMALL;
-               goto failed;
-       }
-
-       /* check the server isn't being nasty */
-       if (raw_trans_oob(req, param_ofs, param_count) ||
-           raw_trans_oob(req, data_ofs, data_count)) {
-               DEBUG(1,("smb_raw_trans2_recv_helper: out of bounds parameters!\n"));
-               req->status = NT_STATUS_BUFFER_TOO_SMALL;
-               goto failed;
-       }
-
-       if (data_count) {
-               memcpy(state->io.out.data.data + data_disp,
-                      req->in.hdr + data_ofs,
-                      data_count);
-       }
-
-       if (param_count) {
-               memcpy(state->io.out.params.data + param_disp,
-                      req->in.hdr + param_ofs,
-                      param_count);
-       }
-
-       state->recvd_param += param_count;
-       state->recvd_data += data_count;
-
-       if (state->recvd_data < total_data ||
-           state->recvd_param < total_param) {
-
-               /* we don't need the in buffer any more */
-               talloc_free(req->in.buffer);
-               ZERO_STRUCT(req->in);
-
-               /* we still wait for more data */
-               DEBUG(10,("smb_raw_trans2_recv_helper: more data needed\n"));
-               return SMBCLI_REQUEST_RECV;
-       }
-
-       DEBUG(10,("smb_raw_trans2_recv_helper: done\n"));
-       return SMBCLI_REQUEST_DONE;
-
-nomem:
-       req->status = NT_STATUS_NO_MEMORY;
-failed:
-       return SMBCLI_REQUEST_ERROR;
-}
-
-_PUBLIC_ NTSTATUS smb_raw_trans_recv(struct smbcli_request *req,
-                            TALLOC_CTX *mem_ctx,
-                            struct smb_trans2 *parms)
+static struct smbcli_request *smb_raw_trans_backend_send(struct smbcli_tree *tree,
+                                                        struct smb_trans2 *parms,
+                                                        uint8_t command)
 {
-       return smb_raw_trans2_recv(req, mem_ctx, parms);
-}
-
-
-/*
-  trans/trans2 raw async interface - only BLOBs used in this interface.
-*/
-struct smbcli_request *smb_raw_trans_send_backend(struct smbcli_tree *tree,
-                                                 struct smb_trans2 *parms,
-                                                 uint8_t command)
-{
-       struct smb_raw_trans2_recv_state *state;
        struct smbcli_request *req;
-       int i;
-       int padding;
-       size_t space_left;
-       size_t namelen = 0;
-       DATA_BLOB params_chunk;
-       uint16_t ofs;
-       uint16_t params_ofs = 0;
-       DATA_BLOB data_chunk;
-       uint16_t data_ofs = 0;
-
-       if (parms->in.params.length > UINT16_MAX ||
-           parms->in.data.length > UINT16_MAX) {
-               DEBUG(3,("Attempt to send invalid trans2 request (params %u, data %u)\n",
-                        (unsigned)parms->in.params.length, (unsigned)parms->in.data.length));
+       uint8_t additional_flags;
+       uint8_t clear_flags;
+       uint16_t additional_flags2;
+       uint16_t clear_flags2;
+       uint32_t pid;
+       uint16_t tid;
+       uint16_t uid;
+       const char *pipe_name = NULL;
+       uint8_t s;
+       uint32_t timeout_msec;
+       uint32_t tmp;
+
+       tmp = parms->in.params.length + parms->in.data.length;
+
+       req = smbcli_request_setup(tree, command, parms->in.setup_count, tmp);
+       if (req == NULL) {
                return NULL;
        }
-           
-
-       if (command == SMBtrans)
-               padding = 1;
-       else
-               padding = 3;
-       
-       req = smbcli_request_setup(tree, command,
-                                  14 + parms->in.setup_count,
-                                  padding);
-       if (!req) {
-               return NULL;
-       }
-
-       state = talloc_zero(req, struct smb_raw_trans2_recv_state);
-       if (!state) {
-               smbcli_request_destroy(req);
-               return NULL;
-       }
-
-       state->command = command;
-
-       /* make sure we don't leak data via the padding */
-       memset(req->out.data, 0, padding);
-
-       /* Watch out, this changes the req->out.* pointers */
-       if (command == SMBtrans && parms->in.trans_name) {
-               namelen = smbcli_req_append_string(req, parms->in.trans_name, 
-                                               STR_TERMINATE);
-       }
-
-       ofs = PTR_DIFF(req->out.data,req->out.hdr)+padding+namelen;
-
-       /* see how much bytes of the params block we can ship in the first request */
-       space_left = raw_trans_space_left(req);
-
-       params_chunk.length = MIN(parms->in.params.length, space_left);
-       params_chunk.data = parms->in.params.data;
-       params_ofs = ofs;
-
-       state->params_left = parms->in.params.length - params_chunk.length;
-
-       if (state->params_left > 0) {
-               /* we copy the whole params block, if needed we can optimize that latter */
-               state->io.in.params = data_blob_talloc(state, NULL, parms->in.params.length);
-               if (!state->io.in.params.data) {
-                       smbcli_request_destroy(req);
-                       return NULL;
-               }
-               memcpy(state->io.in.params.data,
-                      parms->in.params.data,
-                      parms->in.params.length);
-       }
 
-       /* see how much bytes of the data block we can ship in the first request */
-       space_left -= params_chunk.length;
+       additional_flags = CVAL(req->out.hdr, HDR_FLG);
+       additional_flags2 = SVAL(req->out.hdr, HDR_FLG2);
+       pid  = SVAL(req->out.hdr, HDR_PID);
+       pid |= SVAL(req->out.hdr, HDR_PIDHIGH)<<16;
+       tid = SVAL(req->out.hdr, HDR_TID);
+       uid = SVAL(req->out.hdr, HDR_UID);
 
-#if TORTURE_TRANS_DATA
-       if (space_left > 1) {
-               space_left /= 2;
-       }
-#endif
-
-       data_chunk.length = MIN(parms->in.data.length, space_left);
-       data_chunk.data = parms->in.data.data;
-       data_ofs = params_ofs + params_chunk.length;
-
-       state->data_left = parms->in.data.length - data_chunk.length;
+       clear_flags = ~additional_flags;
+       clear_flags2 = ~additional_flags2;
 
-       if (state->data_left > 0) {
-               /* we copy the whole params block, if needed we can optimize that latter */
-               state->io.in.data = data_blob_talloc(state, NULL, parms->in.data.length);
-               if (!state->io.in.data.data) {
-                       smbcli_request_destroy(req);
-                       return NULL;
-               }
-               memcpy(state->io.in.data.data,
-                      parms->in.data.data,
-                      parms->in.data.length);
-       }
+       timeout_msec = req->transport->options.request_timeout * 1000;
 
-       state->params_total = parms->in.params.length;
-       state->data_total = parms->in.data.length;
-
-       /* primary request */
-       SSVAL(req->out.vwv,VWV(0),parms->in.params.length);
-       SSVAL(req->out.vwv,VWV(1),parms->in.data.length);
-       SSVAL(req->out.vwv,VWV(2),parms->in.max_param);
-       SSVAL(req->out.vwv,VWV(3),parms->in.max_data);
-       SCVAL(req->out.vwv,VWV(4),parms->in.max_setup);
-       SCVAL(req->out.vwv,VWV(4)+1,0); /* reserved */
-       SSVAL(req->out.vwv,VWV(5),parms->in.flags);
-       SIVAL(req->out.vwv,VWV(6),parms->in.timeout);
-       SSVAL(req->out.vwv,VWV(8),0); /* reserved */
-       SSVAL(req->out.vwv,VWV(9),params_chunk.length);
-       SSVAL(req->out.vwv,VWV(10),params_ofs);
-       SSVAL(req->out.vwv,VWV(11),data_chunk.length);
-       SSVAL(req->out.vwv,VWV(12),data_ofs);
-       SCVAL(req->out.vwv,VWV(13),parms->in.setup_count);
-       SCVAL(req->out.vwv,VWV(13)+1,0); /* reserved */
-       for (i=0;i<parms->in.setup_count;i++)   {
-               SSVAL(req->out.vwv,VWV(14)+VWV(i),parms->in.setup[i]);
+       for (s=0; s < parms->in.setup_count; s++) {
+               SSVAL(req->out.vwv, VWV(s), parms->in.setup[s]);
        }
-       smbcli_req_append_blob(req, &params_chunk);
-       smbcli_req_append_blob(req, &data_chunk);
 
-       /* add the helper which will check that all multi-part replies are
-          in before an async client callack will be issued */
-       req->recv_helper.fn = smb_raw_trans2_recv_helper;
-       req->recv_helper.private_data = state;
+       memcpy(req->out.data,
+              parms->in.params.data,
+              parms->in.params.length);
+       memcpy(req->out.data + parms->in.params.length,
+              parms->in.data.data,
+              parms->in.data.length);
 
-       if (!smbcli_request_send(req)) {
-               smbcli_request_destroy(req);
+       if (command == SMBtrans && parms->in.trans_name) {
+               pipe_name = parms->in.trans_name;
+       }
+
+       req->subreqs[0] = smb1cli_trans_send(req,
+                                            req->transport->ev,
+                                            req->transport->conn,
+                                            command,
+                                            additional_flags,
+                                            clear_flags,
+                                            additional_flags2,
+                                            clear_flags2,
+                                            timeout_msec,
+                                            pid, tid, uid,
+                                            pipe_name,
+                                            0xFFFF, /* fid */
+                                            0, /* function */
+                                            parms->in.flags,
+                                            (uint16_t *)req->out.vwv,
+                                            parms->in.setup_count,
+                                            parms->in.max_setup,
+                                            req->out.data,
+                                            parms->in.params.length,
+                                            parms->in.max_param,
+                                            req->out.data+
+                                            parms->in.params.length,
+                                            parms->in.data.length,
+                                            parms->in.max_data);
+       if (req->subreqs[0] == NULL) {
+               talloc_free(req);
                return NULL;
        }
+       tevent_req_set_callback(req->subreqs[0],
+                               smb_raw_trans_backend_done,
+                               req);
 
        return req;
 }
 
-static enum smbcli_request_state smb_raw_trans2_ship_next(struct smbcli_request *req,
-                                                         struct smb_raw_trans2_recv_state *state)
+static void smb_raw_trans_backend_done(struct tevent_req *subreq)
 {
-       struct smbcli_request *req2;
-       size_t space_left;
-       DATA_BLOB params_chunk;
-       uint16_t ofs;
-       uint16_t params_ofs = 0;
-       uint16_t params_disp = 0;
-       DATA_BLOB data_chunk;
-       uint16_t data_ofs = 0;
-       uint16_t data_disp = 0;
-       uint8_t wct;
-
-       if (state->command == SMBtrans2) {
-               wct = 9;
-       } else {
-               wct = 8;
+       struct smbcli_request *req =
+               tevent_req_callback_data(subreq,
+               struct smbcli_request);
+       struct smbcli_transport *transport = req->transport;
+       uint16_t *setup = NULL;
+       uint8_t num_setup = 0;
+       uint8_t s;
+       uint8_t *param = NULL;
+       uint32_t num_param = 0;
+       uint8_t *data = NULL;
+       uint32_t num_data = 0;
+
+       req->status = smb1cli_trans_recv(req->subreqs[0], req,
+                                        &req->flags2,
+                                        &setup,
+                                        0, /* min_setup */
+                                        &num_setup,
+                                        &param,
+                                        0, /* min_param */
+                                        &num_param,
+                                        &data,
+                                        0, /* min_data */
+                                        &num_data);
+       TALLOC_FREE(req->subreqs[0]);
+       if (NT_STATUS_IS_ERR(req->status)) {
+               req->state = SMBCLI_REQUEST_ERROR;
+               transport->error.e.nt_status = req->status;
+               transport->error.etype = ETYPE_SMB;
+               if (req->async.fn) {
+                       req->async.fn(req);
+               }
+               return;
+       }
+
+       req->trans2.out.setup_count = num_setup;
+       req->trans2.out.setup = talloc_array(req, uint16_t, num_setup);
+       if (req->trans2.out.setup == NULL) {
+               req->state = SMBCLI_REQUEST_ERROR;
+               req->status = NT_STATUS_NO_MEMORY;
+               transport->error.e.nt_status = req->status;
+               transport->error.etype = ETYPE_SMB;
+               if (req->async.fn) {
+                       req->async.fn(req);
+               }
+               return;
        }
-
-       req2 = smbcli_request_setup(req->tree, state->command+1, wct, 0);
-       if (!req2) {
-               goto nomem;
+       for (s = 0; s < num_setup; s++) {
+               req->trans2.out.setup[s] = SVAL(setup, VWV(s));
        }
-       req2->mid = req->mid;
-       SSVAL(req2->out.hdr, HDR_MID, req2->mid);
-
-       ofs = PTR_DIFF(req2->out.data,req2->out.hdr);
-
-       /* see how much bytes of the params block we can ship in the first request */
-       space_left = raw_trans_space_left(req2);
-
-       params_disp = state->io.in.params.length - state->params_left;
-       params_chunk.length = MIN(state->params_left, space_left);
-       params_chunk.data = state->io.in.params.data + params_disp;
-       params_ofs = ofs;
 
-       state->params_left -= params_chunk.length;
-
-       /* see how much bytes of the data block we can ship in the first request */
-       space_left -= params_chunk.length;
-
-#if TORTURE_TRANS_DATA
-       if (space_left > 1) {
-               space_left /= 2;
-       }
-#endif
-
-       data_disp = state->io.in.data.length - state->data_left;
-       data_chunk.length = MIN(state->data_left, space_left);
-       data_chunk.data = state->io.in.data.data + data_disp;
-       data_ofs = params_ofs+params_chunk.length;
-
-       state->data_left -= data_chunk.length;
-
-       SSVAL(req2->out.vwv,VWV(0), state->params_total);
-       SSVAL(req2->out.vwv,VWV(1), state->data_total);
-       SSVAL(req2->out.vwv,VWV(2), params_chunk.length);
-       SSVAL(req2->out.vwv,VWV(3), params_ofs);
-       SSVAL(req2->out.vwv,VWV(4), params_disp);
-       SSVAL(req2->out.vwv,VWV(5), data_chunk.length);
-       SSVAL(req2->out.vwv,VWV(6), data_ofs);
-       SSVAL(req2->out.vwv,VWV(7), data_disp);
-       if (wct == 9) {
-               SSVAL(req2->out.vwv,VWV(8), 0xFFFF);
-       }
+       req->trans2.out.params.data = param;
+       req->trans2.out.params.length = num_param;
 
-       smbcli_req_append_blob(req2, &params_chunk);
-       smbcli_req_append_blob(req2, &data_chunk);
+       req->trans2.out.data.data = data;
+       req->trans2.out.data.length = num_data;
 
-       /*
-        * it's a one way request but we need
-        * the seq_num, so we destroy req2 by hand
-        */
-       if (!smbcli_request_send(req2)) {
-               goto failed;
+       transport->error.e.nt_status = req->status;
+       if (NT_STATUS_IS_OK(req->status)) {
+               transport->error.etype = ETYPE_NONE;
+       } else {
+               transport->error.etype = ETYPE_SMB;
        }
 
-       req->seq_num = req2->seq_num;
-       smbcli_request_destroy(req2);
-
-       return SMBCLI_REQUEST_RECV;
-
-nomem:
-       req->status = NT_STATUS_NO_MEMORY;
-failed:
-       if (req2) {
-               req->status = smbcli_request_destroy(req2);
+       req->state = SMBCLI_REQUEST_DONE;
+       if (req->async.fn) {
+               req->async.fn(req);
        }
-       return SMBCLI_REQUEST_ERROR;
 }
 
-static enum smbcli_request_state smb_raw_trans2_ship_rest(struct smbcli_request *req,
-                                                         struct smb_raw_trans2_recv_state *state)
+static NTSTATUS smb_raw_trans_backend_recv(struct smbcli_request *req,
+                                          TALLOC_CTX *mem_ctx,
+                                          struct smb_trans2 *parms)
 {
-       enum smbcli_request_state ret = SMBCLI_REQUEST_ERROR;
-
-       while (state->params_left > 0 || state->data_left > 0) {
-               ret = smb_raw_trans2_ship_next(req, state);
-               if (ret != SMBCLI_REQUEST_RECV) {
-                       break;
-               }
+       if (!smbcli_request_receive(req) ||
+           smbcli_request_is_error(req)) {
+               goto failed;
        }
 
-       return ret;
-}
-
+       parms->out = req->trans2.out;
+       talloc_steal(mem_ctx, parms->out.setup);
+       talloc_steal(mem_ctx, parms->out.params.data);
+       talloc_steal(mem_ctx, parms->out.data.data);
 
-/*
-  trans/trans2 raw async interface - only BLOBs used in this interface.
-  note that this doesn't yet support multi-part requests
-*/
-_PUBLIC_ struct smbcli_request *smb_raw_trans_send(struct smbcli_tree *tree,
-                                      struct smb_trans2 *parms)
-{
-       return smb_raw_trans_send_backend(tree, parms, SMBtrans);
+failed:
+       return smbcli_request_destroy(req);
 }
 
-struct smbcli_request *smb_raw_trans2_send(struct smbcli_tree *tree,
+_PUBLIC_ struct smbcli_request *smb_raw_trans_send(struct smbcli_tree *tree,
                                       struct smb_trans2 *parms)
 {
-       return smb_raw_trans_send_backend(tree, parms, SMBtrans2);
+       return smb_raw_trans_backend_send(tree, parms, SMBtrans);
 }
 
-/*
-  trans2 synchronous blob interface
-*/
-NTSTATUS smb_raw_trans2(struct smbcli_tree *tree,
-                       TALLOC_CTX *mem_ctx,
-                       struct smb_trans2 *parms)
+_PUBLIC_ NTSTATUS smb_raw_trans_recv(struct smbcli_request *req,
+                            TALLOC_CTX *mem_ctx,
+                            struct smb_trans2 *parms)
 {
-       struct smbcli_request *req;
-       req = smb_raw_trans2_send(tree, parms);
-       if (!req) return NT_STATUS_UNSUCCESSFUL;
-       return smb_raw_trans2_recv(req, mem_ctx, parms);
+       return smb_raw_trans_backend_recv(req, mem_ctx, parms);
 }
 
-
-/*
-  trans synchronous blob interface
-*/
 _PUBLIC_ NTSTATUS smb_raw_trans(struct smbcli_tree *tree,
                       TALLOC_CTX *mem_ctx,
                       struct smb_trans2 *parms)
@@ -536,413 +224,185 @@ _PUBLIC_ NTSTATUS smb_raw_trans(struct smbcli_tree *tree,
        return smb_raw_trans_recv(req, mem_ctx, parms);
 }
 
-struct smb_raw_nttrans_recv_state {
-       uint32_t params_total;
-       uint32_t data_total;
-       uint32_t params_left;
-       uint32_t data_left;
-       bool got_first;
-       uint32_t recvd_data;
-       uint32_t recvd_param;
-       struct smb_nttrans io;
-};
-
-NTSTATUS smb_raw_nttrans_recv(struct smbcli_request *req,
-                             TALLOC_CTX *mem_ctx,
-                             struct smb_nttrans *parms)
+struct smbcli_request *smb_raw_trans2_send(struct smbcli_tree *tree,
+                                      struct smb_trans2 *parms)
 {
-       struct smb_raw_nttrans_recv_state *state;
-
-       if (!smbcli_request_receive(req) ||
-           smbcli_request_is_error(req)) {
-               goto failed;
-       }
-
-       state = talloc_get_type(req->recv_helper.private_data,
-                               struct smb_raw_nttrans_recv_state);
-
-       parms->out = state->io.out;
-       talloc_steal(mem_ctx, parms->out.setup);
-       talloc_steal(mem_ctx, parms->out.params.data);
-       talloc_steal(mem_ctx, parms->out.data.data);
-       talloc_free(state);
-
-       ZERO_STRUCT(req->recv_helper);
-
-failed:
-       return smbcli_request_destroy(req);
+       return smb_raw_trans_backend_send(tree, parms, SMBtrans2);
 }
 
-static enum smbcli_request_state smb_raw_nttrans_ship_rest(struct smbcli_request *req,
-                                                          struct smb_raw_nttrans_recv_state *state);
-
-/*
- * This helper returns SMBCLI_REQUEST_RECV until all data has arrived
- */
-static enum smbcli_request_state smb_raw_nttrans_recv_helper(struct smbcli_request *req)
+NTSTATUS smb_raw_trans2_recv(struct smbcli_request *req,
+                            TALLOC_CTX *mem_ctx,
+                            struct smb_trans2 *parms)
 {
-       struct smb_raw_nttrans_recv_state *state = talloc_get_type(req->recv_helper.private_data,
-                                                  struct smb_raw_nttrans_recv_state);
-       uint32_t param_count, param_ofs, param_disp;
-       uint32_t data_count, data_ofs, data_disp;
-       uint32_t total_data, total_param;
-       uint8_t setup_count;
-
-       /*
-        * An NT RPC pipe call can return ERRDOS, ERRmoredata
-        * to a trans call. This is not an error and should not
-        * be treated as such.
-        */
-       if (smbcli_request_is_error(req)) {
-               goto failed;
-       }
-
-       /* sanity check */
-       if (CVAL(req->in.hdr, HDR_COM) != SMBnttrans) {
-               DEBUG(0,("smb_raw_nttrans_recv_helper: Expected %s response, got command 0x%02x\n",
-                        "SMBnttrans", 
-                        CVAL(req->in.hdr,HDR_COM)));
-               req->status = NT_STATUS_INVALID_NETWORK_RESPONSE;
-               goto failed;
-       }
-
-       if (state->params_left > 0 || state->data_left > 0) {
-               return smb_raw_nttrans_ship_rest(req, state);
-       }
-
-       /* this is the first packet of the response */
-       SMBCLI_CHECK_MIN_WCT(req, 18);
-
-       total_param = IVAL(req->in.vwv, 3);
-       total_data  = IVAL(req->in.vwv, 7);
-       setup_count = CVAL(req->in.vwv, 35);
-
-       param_count = IVAL(req->in.vwv, 11);
-       param_ofs   = IVAL(req->in.vwv, 15);
-       param_disp  = IVAL(req->in.vwv, 19);
-
-       data_count = IVAL(req->in.vwv, 23);
-       data_ofs   = IVAL(req->in.vwv, 27);
-       data_disp  = IVAL(req->in.vwv, 31);
-
-       if (!state->got_first) {
-               if (total_param > 0) {
-                       state->io.out.params = data_blob_talloc(state, NULL, total_param);
-                       if (!state->io.out.params.data) {
-                               goto nomem;
-                       }
-               }
-
-               if (total_data > 0) {
-                       state->io.out.data = data_blob_talloc(state, NULL, total_data);
-                       if (!state->io.out.data.data) {
-                               goto nomem;
-                       }
-               }
-
-               if (setup_count > 0) {
-                       SMBCLI_CHECK_WCT(req, 18 + setup_count);
-
-                       state->io.out.setup_count = setup_count;
-                       state->io.out.setup = talloc_array(state, uint8_t,
-                                                          setup_count * VWV(1));
-                       if (!state->io.out.setup) {
-                               goto nomem;
-                       }
-                       memcpy(state->io.out.setup, (uint8_t *)req->out.vwv + VWV(18),
-                              setup_count * VWV(1));
-               }
-
-               state->got_first = true;
-       }
-
-       if (total_data > state->io.out.data.length ||
-           total_param > state->io.out.params.length) {
-               /* they must *only* shrink */
-               DEBUG(1,("smb_raw_nttrans_recv_helper: data/params expanded!\n"));
-               req->status = NT_STATUS_BUFFER_TOO_SMALL;
-               goto failed;
-       }
-
-       state->io.out.data.length = total_data;
-       state->io.out.params.length = total_param;
-
-       if (data_count + data_disp > total_data ||
-           param_count + param_disp > total_param) {
-               DEBUG(1,("smb_raw_nttrans_recv_helper: Buffer overflow\n"));
-               req->status = NT_STATUS_BUFFER_TOO_SMALL;
-               goto failed;
-       }
-
-       /* check the server isn't being nasty */
-       if (raw_trans_oob(req, param_ofs, param_count) ||
-           raw_trans_oob(req, data_ofs, data_count)) {
-               DEBUG(1,("smb_raw_nttrans_recv_helper: out of bounds parameters!\n"));
-               req->status = NT_STATUS_BUFFER_TOO_SMALL;
-               goto failed;
-       }
-
-       if (data_count) {
-               memcpy(state->io.out.data.data + data_disp,
-                      req->in.hdr + data_ofs,
-                      data_count);
-       }
-
-       if (param_count) {
-               memcpy(state->io.out.params.data + param_disp,
-                      req->in.hdr + param_ofs,
-                      param_count);
-       }
-
-       state->recvd_param += param_count;
-       state->recvd_data += data_count;
-
-       if (state->recvd_data < total_data ||
-           state->recvd_param < total_param) {
-
-               /* we don't need the in buffer any more */
-               talloc_free(req->in.buffer);
-               ZERO_STRUCT(req->in);
-
-               /* we still wait for more data */
-               DEBUG(10,("smb_raw_nttrans_recv_helper: more data needed\n"));
-               return SMBCLI_REQUEST_RECV;
-       }
-
-       DEBUG(10,("smb_raw_nttrans_recv_helper: done\n"));
-       return SMBCLI_REQUEST_DONE;
+       return smb_raw_trans_backend_recv(req, mem_ctx, parms);
+}
 
-nomem:
-       req->status = NT_STATUS_NO_MEMORY;
-failed:
-       return SMBCLI_REQUEST_ERROR;
+NTSTATUS smb_raw_trans2(struct smbcli_tree *tree,
+                       TALLOC_CTX *mem_ctx,
+                       struct smb_trans2 *parms)
+{
+       struct smbcli_request *req;
+       req = smb_raw_trans2_send(tree, parms);
+       if (!req) return NT_STATUS_UNSUCCESSFUL;
+       return smb_raw_trans2_recv(req, mem_ctx, parms);
 }
 
-/****************************************************************************
- nttrans raw - only BLOBs used in this interface.
- at the moment we only handle a single primary request 
-****************************************************************************/
+static void smb_raw_nttrans_done(struct tevent_req *subreq);
+
 struct smbcli_request *smb_raw_nttrans_send(struct smbcli_tree *tree,
-                                        struct smb_nttrans *parms)
+                                           struct smb_nttrans *parms)
 {
-       struct smbcli_request *req; 
-       struct smb_raw_nttrans_recv_state *state;
-       uint32_t ofs;
-       size_t space_left;
-       DATA_BLOB params_chunk;
-       uint32_t params_ofs;
-       DATA_BLOB data_chunk;
-       uint32_t data_ofs;
-       int align = 0;
-
-       /* only align if there are parameters or data */
-       if (parms->in.params.length || parms->in.data.length) {
-               align = 3;
-       }
-       
-       req = smbcli_request_setup(tree, SMBnttrans, 
-                               19 + parms->in.setup_count, align);
-       if (!req) {
+       struct smbcli_request *req;
+       uint8_t additional_flags;
+       uint8_t clear_flags;
+       uint16_t additional_flags2;
+       uint16_t clear_flags2;
+       uint32_t pid;
+       uint16_t tid;
+       uint16_t uid;
+       uint32_t timeout_msec;
+       uint32_t tmp;
+
+       tmp = parms->in.params.length + parms->in.data.length;
+
+       req = smbcli_request_setup(tree, SMBnttrans, parms->in.setup_count, tmp);
+       if (req == NULL) {
                return NULL;
        }
 
-       state = talloc_zero(req, struct smb_raw_nttrans_recv_state);
-       if (!state) {
+       additional_flags = CVAL(req->out.hdr, HDR_FLG);
+       additional_flags2 = SVAL(req->out.hdr, HDR_FLG2);
+       pid  = SVAL(req->out.hdr, HDR_PID);
+       pid |= SVAL(req->out.hdr, HDR_PIDHIGH)<<16;
+       tid = SVAL(req->out.hdr, HDR_TID);
+       uid = SVAL(req->out.hdr, HDR_UID);
+
+       clear_flags = ~additional_flags;
+       clear_flags2 = ~additional_flags2;
+
+       timeout_msec = req->transport->options.request_timeout * 1000;
+
+       memcpy(req->out.vwv,
+              parms->in.setup,
+              parms->in.setup_count * 2);
+
+       memcpy(req->out.data,
+              parms->in.params.data,
+              parms->in.params.length);
+       memcpy(req->out.data + parms->in.params.length,
+              parms->in.data.data,
+              parms->in.data.length);
+
+       req->subreqs[0] = smb1cli_trans_send(req,
+                                            req->transport->ev,
+                                            req->transport->conn,
+                                            SMBnttrans,
+                                            additional_flags,
+                                            clear_flags,
+                                            additional_flags2,
+                                            clear_flags2,
+                                            timeout_msec,
+                                            pid, tid, uid,
+                                            NULL, /* pipe_name */
+                                            0xFFFF, /* fid */
+                                            parms->in.function,
+                                            0, /* flags */
+                                            (uint16_t *)req->out.vwv,
+                                            parms->in.setup_count,
+                                            parms->in.max_setup,
+                                            req->out.data,
+                                            parms->in.params.length,
+                                            parms->in.max_param,
+                                            req->out.data+
+                                            parms->in.params.length,
+                                            parms->in.data.length,
+                                            parms->in.max_data);
+       if (req->subreqs[0] == NULL) {
                talloc_free(req);
                return NULL;
        }
+       tevent_req_set_callback(req->subreqs[0],
+                               smb_raw_nttrans_done,
+                               req);
 
-       /* fill in SMB parameters */
-
-       if (align != 0) {
-               memset(req->out.data, 0, align);
-       }
-
-       ofs = PTR_DIFF(req->out.data,req->out.hdr)+align;
-
-       /* see how much bytes of the params block we can ship in the first request */
-       space_left = raw_trans_space_left(req);
-
-       params_chunk.length = MIN(parms->in.params.length, space_left);
-       params_chunk.data = parms->in.params.data;
-       params_ofs = ofs;
-
-       state->params_left = parms->in.params.length - params_chunk.length;
+       return req;
+}
 
-       if (state->params_left > 0) {
-               /* we copy the whole params block, if needed we can optimize that latter */
-               state->io.in.params = data_blob_talloc(state, NULL, parms->in.params.length);
-               if (!state->io.in.params.data) {
-                       smbcli_request_destroy(req);
-                       return NULL;
+static void smb_raw_nttrans_done(struct tevent_req *subreq)
+{
+       struct smbcli_request *req =
+               tevent_req_callback_data(subreq,
+               struct smbcli_request);
+       struct smbcli_transport *transport = req->transport;
+       uint16_t *setup = NULL;
+       uint8_t num_setup = 0;
+       uint8_t *param = NULL;
+       uint32_t num_param = 0;
+       uint8_t *data = NULL;
+       uint32_t num_data = 0;
+
+       req->status = smb1cli_trans_recv(req->subreqs[0], req,
+                                        &req->flags2,
+                                        &setup,
+                                        0, /* min_setup */
+                                        &num_setup,
+                                        &param,
+                                        0, /* min_param */
+                                        &num_param,
+                                        &data,
+                                        0, /* min_data */
+                                        &num_data);
+       TALLOC_FREE(req->subreqs[0]);
+       if (NT_STATUS_IS_ERR(req->status)) {
+               req->state = SMBCLI_REQUEST_ERROR;
+               transport->error.e.nt_status = req->status;
+               transport->error.etype = ETYPE_SMB;
+               if (req->async.fn) {
+                       req->async.fn(req);
                }
-               memcpy(state->io.in.params.data,
-                      parms->in.params.data,
-                      parms->in.params.length);
+               return;
        }
 
-       /* see how much bytes of the data block we can ship in the first request */
-       space_left -= params_chunk.length;
-
-#if TORTURE_TRANS_DATA
-       if (space_left > 1) {
-               space_left /= 2;
-       }
-#endif
+       req->nttrans.out.setup_count = num_setup;
+       req->nttrans.out.setup = (uint8_t *)setup;
 
-       data_chunk.length = MIN(parms->in.data.length, space_left);
-       data_chunk.data = parms->in.data.data;
-       data_ofs = params_ofs + params_chunk.length;
+       req->nttrans.out.params.data = param;
+       req->nttrans.out.params.length = num_param;
 
-       state->data_left = parms->in.data.length - data_chunk.length;
+       req->nttrans.out.data.data = data;
+       req->nttrans.out.data.length = num_data;
 
-       if (state->data_left > 0) {
-               /* we copy the whole params block, if needed we can optimize that latter */
-               state->io.in.data = data_blob_talloc(state, NULL, parms->in.data.length);
-               if (!state->io.in.data.data) {
-                       smbcli_request_destroy(req);
-                       return NULL;
-               }
-               memcpy(state->io.in.data.data,
-                      parms->in.data.data,
-                      parms->in.data.length);
+       transport->error.e.nt_status = req->status;
+       if (NT_STATUS_IS_OK(req->status)) {
+               transport->error.etype = ETYPE_NONE;
+       } else {
+               transport->error.etype = ETYPE_SMB;
        }
 
-       state->params_total = parms->in.params.length;
-       state->data_total = parms->in.data.length;
-
-       SCVAL(req->out.vwv,  0, parms->in.max_setup);
-       SSVAL(req->out.vwv,  1, 0); /* reserved */
-       SIVAL(req->out.vwv,  3, parms->in.params.length);
-       SIVAL(req->out.vwv,  7, parms->in.data.length);
-       SIVAL(req->out.vwv, 11, parms->in.max_param);
-       SIVAL(req->out.vwv, 15, parms->in.max_data);
-       SIVAL(req->out.vwv, 19, params_chunk.length);
-       SIVAL(req->out.vwv, 23, params_ofs);
-       SIVAL(req->out.vwv, 27, data_chunk.length);
-       SIVAL(req->out.vwv, 31, data_ofs);
-       SCVAL(req->out.vwv, 35, parms->in.setup_count);
-       SSVAL(req->out.vwv, 36, parms->in.function);
-       memcpy(req->out.vwv + VWV(19), parms->in.setup,
-              sizeof(uint16_t) * parms->in.setup_count);
-
-       smbcli_req_append_blob(req, &params_chunk);
-       smbcli_req_append_blob(req, &data_chunk);
-
-       /* add the helper which will check that all multi-part replies are
-          in before an async client callack will be issued */
-       req->recv_helper.fn = smb_raw_nttrans_recv_helper;
-       req->recv_helper.private_data = state;
-
-       if (!smbcli_request_send(req)) {
-               smbcli_request_destroy(req);
-               return NULL;
+       req->state = SMBCLI_REQUEST_DONE;
+       if (req->async.fn) {
+               req->async.fn(req);
        }
-
-       return req;
 }
 
-static enum smbcli_request_state smb_raw_nttrans_ship_next(struct smbcli_request *req,
-                                                          struct smb_raw_nttrans_recv_state *state)
+NTSTATUS smb_raw_nttrans_recv(struct smbcli_request *req,
+                             TALLOC_CTX *mem_ctx,
+                             struct smb_nttrans *parms)
 {
-       struct smbcli_request *req2;
-       size_t space_left;
-       DATA_BLOB params_chunk;
-       uint32_t ofs;
-       uint32_t params_ofs = 0;
-       uint32_t params_disp = 0;
-       DATA_BLOB data_chunk;
-       uint32_t data_ofs = 0;
-       uint32_t data_disp = 0;
-
-       req2 = smbcli_request_setup(req->tree, SMBnttranss, 18, 0);
-       if (!req2) {
-               goto nomem;
-       }
-       req2->mid = req->mid;
-       SSVAL(req2->out.hdr, HDR_MID, req2->mid);
-
-       ofs = PTR_DIFF(req2->out.data,req2->out.hdr);
-
-       /* see how much bytes of the params block we can ship in the first request */
-       space_left = raw_trans_space_left(req2);
-
-       params_disp = state->io.in.params.length - state->params_left;
-       params_chunk.length = MIN(state->params_left, space_left);
-       params_chunk.data = state->io.in.params.data + params_disp;
-       params_ofs = ofs;
-
-       state->params_left -= params_chunk.length;
-
-       /* see how much bytes of the data block we can ship in the first request */
-       space_left -= params_chunk.length;
-
-#if TORTURE_TRANS_DATA
-       if (space_left > 1) {
-               space_left /= 2;
-       }
-#endif
-
-       data_disp = state->io.in.data.length - state->data_left;
-       data_chunk.length = MIN(state->data_left, space_left);
-       data_chunk.data = state->io.in.data.data + data_disp;
-       data_ofs = params_ofs+params_chunk.length;
-
-       state->data_left -= data_chunk.length;
-
-       SSVAL(req2->out.vwv,0, 0); /* reserved */
-       SCVAL(req2->out.vwv,2, 0); /* reserved */
-       SIVAL(req2->out.vwv,3, state->params_total);
-       SIVAL(req2->out.vwv,7, state->data_total);
-       SIVAL(req2->out.vwv,11, params_chunk.length);
-       SIVAL(req2->out.vwv,15, params_ofs);
-       SIVAL(req2->out.vwv,19, params_disp);
-       SIVAL(req2->out.vwv,23, data_chunk.length);
-       SIVAL(req2->out.vwv,27, data_ofs);
-       SIVAL(req2->out.vwv,31, data_disp);
-       SCVAL(req2->out.vwv,35, 0); /* reserved */
-
-       smbcli_req_append_blob(req2, &params_chunk);
-       smbcli_req_append_blob(req2, &data_chunk);
-
-       /*
-        * it's a one way request but we need
-        * the seq_num, so we destroy req2 by hand
-        */
-       if (!smbcli_request_send(req2)) {
+       if (!smbcli_request_receive(req) ||
+           smbcli_request_is_error(req)) {
                goto failed;
        }
 
-       req->seq_num = req2->seq_num;
-       smbcli_request_destroy(req2);
-
-       return SMBCLI_REQUEST_RECV;
+       parms->out = req->nttrans.out;
+       talloc_steal(mem_ctx, parms->out.setup);
+       talloc_steal(mem_ctx, parms->out.params.data);
+       talloc_steal(mem_ctx, parms->out.data.data);
 
-nomem:
-       req->status = NT_STATUS_NO_MEMORY;
 failed:
-       if (req2) {
-               req->status = smbcli_request_destroy(req2);
-       }
-       return SMBCLI_REQUEST_ERROR;
-}
-
-static enum smbcli_request_state smb_raw_nttrans_ship_rest(struct smbcli_request *req,
-                                                          struct smb_raw_nttrans_recv_state *state)
-{
-       enum smbcli_request_state ret = SMBCLI_REQUEST_ERROR;
-
-       while (state->params_left > 0 || state->data_left > 0) {
-               ret = smb_raw_nttrans_ship_next(req, state);
-               if (ret != SMBCLI_REQUEST_RECV) {
-                       break;
-               }
-       }
-
-       return ret;
+       return smbcli_request_destroy(req);
 }
 
-
 /****************************************************************************
   receive a SMB nttrans response allocating the necessary memory
   ****************************************************************************/
index e1d7a2d1878fc1b61783718f9740eef99c42e810..5d2f92874797539f26a5d4aa4f8d41d4863de195 100644 (file)
@@ -42,28 +42,6 @@ bool set_smb_signing_common(struct smb_signing_context *sign_info)
        return true;
 }
 
-/***********************************************************
- SMB signing - Common code before we set a new signing implementation
-************************************************************/
-static bool smbcli_set_smb_signing_common(struct smbcli_transport *transport)
-{
-       if (!set_smb_signing_common(&transport->negotiate.sign_info)) {
-               return false;
-       }
-
-       if (!(transport->negotiate.sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)
-           && !transport->negotiate.sign_info.mandatory_signing) {
-               DEBUG(5, ("SMB Signing is not negotiated by the peer\n"));
-               return false;
-       }
-
-       /* These calls are INCOMPATIBLE with SMB signing */
-       transport->negotiate.readbraw_supported = false;
-       transport->negotiate.writebraw_supported = false;
-
-       return true;
-}
-
 void mark_packet_signed(struct smb_request_buffer *out) 
 {
        uint16_t flags2;
@@ -202,55 +180,6 @@ bool check_signed_incoming_message(struct smb_request_buffer *in, DATA_BLOB *mac
        return good;
 }
 
-static void smbcli_req_allocate_seq_num(struct smbcli_request *req) 
-{
-       req->seq_num = req->transport->negotiate.sign_info.next_seq_num;
-       
-       /* some requests (eg. NTcancel) are one way, and the sequence number
-          should be increased by 1 not 2 */
-       if (req->sign_single_increment) {
-               req->transport->negotiate.sign_info.next_seq_num += 1;
-       } else {
-               req->transport->negotiate.sign_info.next_seq_num += 2;
-       }
-}
-
-/***********************************************************
- SMB signing - Simple implementation - calculate a MAC to send.
-************************************************************/
-void smbcli_request_calculate_sign_mac(struct smbcli_request *req)
-{
-#if 0
-       /* enable this when packet signing is preventing you working out why valgrind 
-          says that data is uninitialised */
-       file_save("pkt.dat", req->out.buffer, req->out.size);
-#endif
-
-       switch (req->transport->negotiate.sign_info.signing_state) {
-       case SMB_SIGNING_ENGINE_OFF:
-               break;
-
-       case SMB_SIGNING_ENGINE_BSRSPYL:
-               /* mark the packet as signed - BEFORE we sign it...*/
-               mark_packet_signed(&req->out);
-               
-               /* I wonder what BSRSPYL stands for - but this is what MS 
-                  actually sends! */
-               memcpy((req->out.hdr + HDR_SS_FIELD), "BSRSPYL ", 8);
-               break;
-
-       case SMB_SIGNING_ENGINE_ON:
-                       
-               smbcli_req_allocate_seq_num(req);
-               sign_outgoing_message(&req->out, 
-                                     &req->transport->negotiate.sign_info.mac_key, 
-                                     req->seq_num);
-               break;
-       }
-       return;
-}
-
-
 /**
  SMB signing - NULL implementation
 
@@ -266,68 +195,6 @@ bool smbcli_set_signing_off(struct smb_signing_context *sign_info)
        return true;
 }
 
-/**
- SMB signing - TEMP implementation - setup the MAC key.
-
-*/
-bool smbcli_temp_set_signing(struct smbcli_transport *transport)
-{
-       if (!smbcli_set_smb_signing_common(transport)) {
-               return false;
-       }
-       DEBUG(5, ("BSRSPYL SMB signing enabled\n"));
-       smbcli_set_signing_off(&transport->negotiate.sign_info);
-
-       transport->negotiate.sign_info.mac_key = data_blob(NULL, 0);
-       transport->negotiate.sign_info.signing_state = SMB_SIGNING_ENGINE_BSRSPYL;
-
-       return true;
-}
-
-/***********************************************************
- SMB signing - Simple implementation - check a MAC sent by server.
-************************************************************/
-/**
- * Check a packet supplied by the server.
- * @return false if we had an established signing connection
- *         which had a back checksum, true otherwise
- */
-bool smbcli_request_check_sign_mac(struct smbcli_request *req) 
-{
-       bool good;
-
-       if (!req->transport->negotiate.sign_info.doing_signing &&
-           req->sign_caller_checks) {
-               return true;
-       }
-
-       req->sign_caller_checks = false;
-
-       switch (req->transport->negotiate.sign_info.signing_state) 
-       {
-       case SMB_SIGNING_ENGINE_OFF:
-               return true;
-       case SMB_SIGNING_ENGINE_BSRSPYL:
-               return true;
-
-       case SMB_SIGNING_ENGINE_ON:
-       {                       
-               if (req->in.size < (HDR_SS_FIELD + 8)) {
-                       return false;
-               } else {
-                       good = check_signed_incoming_message(&req->in, 
-                                                            &req->transport->negotiate.sign_info.mac_key, 
-                                                            req->seq_num+1);
-                       
-                       return signing_good(&req->transport->negotiate.sign_info, 
-                                           req->seq_num+1, good);
-               }
-       }
-       }
-       return false;
-}
-
-
 /***********************************************************
  SMB signing - Simple implementation - setup the MAC key.
 ************************************************************/
@@ -362,45 +229,3 @@ bool smbcli_simple_set_signing(TALLOC_CTX *mem_ctx,
        return true;
 }
 
-
-/***********************************************************
- SMB signing - Simple implementation - setup the MAC key.
-************************************************************/
-bool smbcli_transport_simple_set_signing(struct smbcli_transport *transport,
-                                        const DATA_BLOB user_session_key, 
-                                        const DATA_BLOB response)
-{
-       if (!smbcli_set_smb_signing_common(transport)) {
-               return false;
-       }
-
-       return smbcli_simple_set_signing(transport,
-                                        &transport->negotiate.sign_info,
-                                        &user_session_key,
-                                        &response);
-}
-
-
-bool smbcli_init_signing(struct smbcli_transport *transport) 
-{
-       transport->negotiate.sign_info.next_seq_num = 0;
-       transport->negotiate.sign_info.mac_key = data_blob(NULL, 0);
-       if (!smbcli_set_signing_off(&transport->negotiate.sign_info)) {
-               return false;
-       }
-       
-       switch (transport->options.signing) {
-       case SMB_SIGNING_OFF:
-               transport->negotiate.sign_info.allow_smb_signing = false;
-               break;
-       case SMB_SIGNING_DEFAULT:
-       case SMB_SIGNING_IF_REQUIRED:
-               transport->negotiate.sign_info.allow_smb_signing = true;
-               break;
-       case SMB_SIGNING_REQUIRED:
-               transport->negotiate.sign_info.allow_smb_signing = true;
-               transport->negotiate.sign_info.mandatory_signing = true;
-               break;
-       }
-       return true;
-}
index 0f66f2873d0feb8c4511e6c89e72e106c1f8c13f..0688684e954ba6b01f50ee7862d18afd8fcc07c0 100644 (file)
@@ -232,7 +232,8 @@ static NTSTATUS connect_negprot(struct composite_context *c,
        struct connect_state *state = talloc_get_type(c->private_data, struct connect_state);
        NTSTATUS status;
 
-       status = smb_raw_negotiate_recv(state->req);
+       status = smb_raw_negotiate_recv(state->subreq);
+       TALLOC_FREE(state->subreq);
        NT_STATUS_NOT_OK_RETURN(status);
 
        /* next step is a session setup */
@@ -283,13 +284,19 @@ static NTSTATUS connect_send_negprot(struct composite_context *c,
 {
        struct connect_state *state = talloc_get_type(c->private_data, struct connect_state);
 
-       state->req = smb_raw_negotiate_send(state->transport, io->in.options.unicode, io->in.options.max_protocol);
-       NT_STATUS_HAVE_NO_MEMORY(state->req);
+       /* the socket is up - we can initialise the smbcli transport layer */
+       state->transport = smbcli_transport_init(state->sock, state, true,
+                                                &io->in.options);
+       NT_STATUS_HAVE_NO_MEMORY(state->transport);
 
-       state->req->async.fn = request_handler;
-       state->req->async.private_data = c;
+       state->subreq = smb_raw_negotiate_send(state,
+                                              state->transport->ev,
+                                              state->transport,
+                                              io->in.options.max_protocol);
+       NT_STATUS_HAVE_NO_MEMORY(state->subreq);
+       tevent_req_set_callback(state->subreq, subreq_handler, c);
        state->stage = CONNECT_NEGPROT;
-       
+
        return NT_STATUS_OK;
 }
 
@@ -305,11 +312,6 @@ static NTSTATUS connect_socket(struct composite_context *c,
        status = smbcli_sock_connect_recv(state->creq, state, &state->sock);
        NT_STATUS_NOT_OK_RETURN(status);
 
-       /* the socket is up - we can initialise the smbcli transport layer */
-       state->transport = smbcli_transport_init(state->sock, state, true, 
-                                                &io->in.options);
-       NT_STATUS_HAVE_NO_MEMORY(state->transport);
-
        if (is_ipaddress(state->sock->hostname) &&
            (state->io->in.called_name != NULL)) {
                /* If connecting to an IP address, we might want the real name
@@ -320,10 +322,6 @@ static NTSTATUS connect_socket(struct composite_context *c,
                NT_STATUS_HAVE_NO_MEMORY(state->sock->hostname);
        }
 
-       status = nbt_name_dup(state->transport, &state->called,
-                             &state->transport->called);
-       NT_STATUS_NOT_OK_RETURN(status);
-
        /* next step is a negprot */
        return connect_send_negprot(c, io);
 }
index cafaacd8bbdf351eec72c9d4ffe57c87b88ea42d..63f3a8e10d48301ff53aefad1dacd2d2d5d20a32 100644 (file)
@@ -31,6 +31,7 @@
 #include "auth/credentials/credentials.h"
 #include "version.h"
 #include "param/param.h"
+#include "libcli/smb/smbXcli_base.h"
 
 struct sesssetup_state {
        union smb_sesssetup setup;
@@ -200,7 +201,9 @@ static void request_handler(struct smbcli_request *req)
                        }
                        session_key_err = gensec_session_key(session->gensec, session, &session->user_session_key);
                        if (NT_STATUS_IS_OK(session_key_err)) {
-                               smbcli_transport_simple_set_signing(session->transport, session->user_session_key, null_data_blob);
+                               smb1cli_conn_activate_signing(session->transport->conn,
+                                                             session->user_session_key,
+                                                             null_data_blob);
                        }
                }
 
@@ -213,7 +216,8 @@ static void request_handler(struct smbcli_request *req)
                        session->vuid = state->io->out.vuid;
                        state->req = smb_raw_sesssetup_send(session, &state->setup);
                        session->vuid = vuid;
-                       if (state->req) {
+                       if (state->req &&
+                           !smb1cli_conn_signing_is_active(state->req->transport->conn)) {
                                state->req->sign_caller_checks = true;
                        }
                        composite_continue_smb(c, state->req, request_handler, c);
@@ -229,23 +233,19 @@ static void request_handler(struct smbcli_request *req)
        }
 
        if (check_req) {
+               bool ok;
+
                check_req->sign_caller_checks = false;
-               if (!smbcli_request_check_sign_mac(check_req)) {
+
+               ok = smb1cli_conn_check_signing(check_req->transport->conn,
+                                               check_req->in.buffer, 1);
+               if (!ok) {
                        c->status = NT_STATUS_ACCESS_DENIED;
                }
                talloc_free(check_req);
                check_req = NULL;
        }
 
-       /* enforce the local signing required flag */
-       if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) {
-               if (!session->transport->negotiate.sign_info.doing_signing 
-                   && session->transport->negotiate.sign_info.mandatory_signing) {
-                       DEBUG(0, ("SMB signing required, but server does not support it\n"));
-                       c->status = NT_STATUS_ACCESS_DENIED;
-               }
-       }
-
        if (!NT_STATUS_IS_OK(c->status)) {
                composite_error(c, c->status);
                return;
@@ -291,8 +291,6 @@ static NTSTATUS session_setup_nt1(struct composite_context *c,
        DATA_BLOB session_key = data_blob(NULL, 0);
        int flags = CLI_CRED_NTLM_AUTH;
 
-       smbcli_temp_set_signing(session->transport);
-
        if (session->options.lanman_auth) {
                flags |= CLI_CRED_LANMAN_AUTH;
        }
@@ -339,10 +337,11 @@ static NTSTATUS session_setup_nt1(struct composite_context *c,
        }
 
        if (NT_STATUS_IS_OK(nt_status)) {
-               smbcli_transport_simple_set_signing(session->transport, session_key, 
-                                                   state->setup.nt1.in.password2);
+               smb1cli_conn_activate_signing(session->transport->conn,
+                                             session_key,
+                                             state->setup.nt1.in.password2);
                set_user_session_key(session, &session_key);
-               
+
                data_blob_free(&session_key);
        }
 
@@ -441,8 +440,6 @@ static NTSTATUS session_setup_spnego(struct composite_context *c,
        state->setup.spnego.in.lanman       = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING);
        state->setup.spnego.in.workgroup    = io->in.workgroup;
 
-       smbcli_temp_set_signing(session->transport);
-
        status = gensec_client_start(session, &session->gensec,
                                     io->in.gensec_settings);
        if (!NT_STATUS_IS_OK(status)) {
@@ -459,7 +456,8 @@ static NTSTATUS session_setup_spnego(struct composite_context *c,
                return status;
        }
 
-       status = gensec_set_target_hostname(session->gensec, session->transport->socket->hostname);
+       status = gensec_set_target_hostname(session->gensec,
+                       smbXcli_conn_remote_name(session->transport->conn));
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", 
                          nt_errstr(status)));
@@ -530,7 +528,9 @@ static NTSTATUS session_setup_spnego(struct composite_context *c,
         * as the session key might be the acceptor subkey
         * which comes within the response itself
         */
-       (*req)->sign_caller_checks = true;
+       if (!smb1cli_conn_signing_is_active((*req)->transport->conn)) {
+               (*req)->sign_caller_checks = true;
+       }
 
        return (*req)->status;
 }
index bdba21734c8450f07ba071f1e0fbe6b7c0e63714..f4f44577f4d06ff2fb3562e7252e3ce8aae86d24 100644 (file)
@@ -26,6 +26,7 @@
 #include "librpc/rpc/dcerpc.h"
 #include "librpc/rpc/dcerpc_proto.h"
 #include "librpc/rpc/rpc_common.h"
+#include "../libcli/smb/smbXcli_base.h"
 
 /* transport private information used by SMB pipe transport */
 struct smb_private {
@@ -417,7 +418,7 @@ static const char *smb_target_hostname(struct dcecli_connection *c)
 {
        struct smb_private *smb = talloc_get_type(c->transport.private_data, struct smb_private);
        if (smb == NULL) return "";
-       return smb->tree->session->transport->socket->hostname;
+       return smbXcli_conn_remote_name(smb->tree->session->transport->conn);
 }
 
 /*
@@ -456,9 +457,10 @@ struct composite_context *dcerpc_pipe_open_smb_send(struct dcerpc_pipe *p,
        /* if we don't have a binding on this pipe yet, then create one */
        if (p->binding == NULL) {
                NTSTATUS status;
+               const char *r = smbXcli_conn_remote_name(tree->session->transport->conn);
                char *s;
-               SMB_ASSERT(tree->session->transport->socket->hostname != NULL);
-               s = talloc_asprintf(p, "ncacn_np:%s", tree->session->transport->socket->hostname);
+               SMB_ASSERT(r != NULL);
+               s = talloc_asprintf(p, "ncacn_np:%s", r);
                if (s == NULL) return NULL;
                status = dcerpc_parse_binding(p, s, &p->binding);
                talloc_free(s);
@@ -549,7 +551,7 @@ static void pipe_open_recv(struct smbcli_request *req)
        smb->fnum       = state->open->ntcreatex.out.file.fnum;
        smb->tree       = talloc_reference(smb, state->tree);
        smb->server_name= strupper_talloc(smb,
-                         state->tree->session->transport->called.name);
+               smbXcli_conn_remote_name(state->tree->session->transport->conn));
        if (composite_nomem(smb->server_name, ctx)) return;
        smb->dead       = false;
 
index 91ca08d2de0b68b52d85058640bedb4c63b00e3f..72dff99ccf5ad1b5b91fecb555adafc9163fbc0b 100644 (file)
@@ -34,6 +34,7 @@
 #include "../lib/util/dlinklist.h"
 #include "param/param.h"
 #include "libcli/resolve/resolve.h"
+#include "../libcli/smb/smbXcli_base.h"
 
 struct cvfs_file {
        struct cvfs_file *prev, *next;
@@ -66,7 +67,7 @@ struct async_info {
 NTSTATUS ntvfs_cifs_init(void);
 
 #define CHECK_UPSTREAM_OPEN do { \
-       if (! p->transport->socket->sock) { \
+       if (!smbXcli_conn_is_connected(p->transport->conn)) { \
                req->async_states->state|=NTVFS_ASYNC_STATE_CLOSE; \
                return NT_STATUS_CONNECTION_DISCONNECTED; \
        } \
index d1005d0bdce2ce20de4a3c9f234efca46206688e..56461005e80997561ca4394c82430f60332b99f3 100644 (file)
@@ -65,6 +65,14 @@ static struct smbcli_state *open_nbt_connection(struct torture_context *tctx)
                goto failed;
        }
 
+       cli->transport = smbcli_transport_init(cli->sock, cli,
+                                              true, &cli->options);
+       cli->sock = NULL;
+       if (!cli->transport) {
+               torture_comment(tctx, "smbcli_transport_init failed\n");
+               goto failed;
+       }
+
        return cli;
 
 failed:
@@ -360,15 +368,23 @@ static bool run_negprot_nowait(struct torture_context *tctx)
        torture_comment(tctx, "Filling send buffer\n");
 
        for (i=0;i<100;i++) {
-               struct smbcli_request *req;
-               req = smb_raw_negotiate_send(cli->transport, lpcfg_unicode(tctx->lp_ctx), PROTOCOL_NT1);
+               struct tevent_req *req;
+               req = smb_raw_negotiate_send(cli, tctx->ev,
+                                            cli->transport,
+                                            PROTOCOL_NT1);
                tevent_loop_once(tctx->ev);
-               if (req->state == SMBCLI_REQUEST_ERROR) {
+               if (!tevent_req_is_in_progress(req)) {
+                       NTSTATUS status;
+
+                       status = smb_raw_negotiate_recv(req);
+                       TALLOC_FREE(req);
                        if (i > 0) {
-                               torture_comment(tctx, "Failed to fill pipe packet[%d] - %s (ignored)\n", i+1, nt_errstr(req->status));
+                               torture_comment(tctx, "Failed to fill pipe packet[%d] - %s (ignored)\n",
+                                               i+1, nt_errstr(status));
                                break;
                        } else {
-                               torture_comment(tctx, "Failed to fill pipe - %s \n", nt_errstr(req->status));
+                               torture_comment(tctx, "Failed to fill pipe - %s \n",
+                                               nt_errstr(status));
                                torture_close_connection(cli);
                                return false;
                        }
index 0a4faface875ff9d5b51aa13c41c481dcf459df5..1f016f0ee0f284a8b56e48e7b27c58dde88dd41a 100644 (file)
@@ -33,6 +33,8 @@
 #include "libcli/resolve/resolve.h"
 #include "param/param.h"
 #include "torture/raw/proto.h"
+#include "libcli/smb/smbXcli_base.h"
+#include "../lib/util/util_net.h"
 
 #define BASEDIR "\\benchlock"
 #define FNAME BASEDIR "\\lock.dat"
@@ -336,6 +338,11 @@ bool torture_bench_lock(struct torture_context *torture)
 
        printf("Opening %d connections\n", nprocs);
        for (i=0;i<nprocs;i++) {
+               const struct sockaddr_storage *dest_ss;
+               char addrstr[INET6_ADDRSTRLEN];
+               const char *dest_str;
+               uint16_t dest_port;
+
                state[i].tctx = torture;
                state[i].mem_ctx = talloc_new(state);
                state[i].client_num = i;
@@ -343,20 +350,23 @@ bool torture_bench_lock(struct torture_context *torture)
                if (!torture_open_connection_ev(&cli, i, torture, torture->ev)) {
                        return false;
                }
-               talloc_steal(mem_ctx, state);
+               talloc_steal(state[i].mem_ctx, cli);
                state[i].tree = cli->tree;
-               state[i].dest_host = talloc_strdup(state[i].mem_ctx, 
-                                                  cli->tree->session->transport->socket->hostname);
+
+               dest_ss = smbXcli_conn_remote_sockaddr(
+                               state[i].tree->session->transport->conn);
+               dest_str = print_sockaddr(addrstr, sizeof(addrstr), dest_ss);
+               dest_port = get_sockaddr_port(dest_ss);
+
+               state[i].dest_host = talloc_strdup(state[i].mem_ctx, dest_str);
                state[i].dest_ports = talloc_array(state[i].mem_ctx, 
                                                   const char *, 2);
                state[i].dest_ports[0] = talloc_asprintf(state[i].dest_ports, 
-                                                        "%u", 
-                                                        cli->tree->session->transport->socket->port);
+                                                        "%u", dest_port);
                state[i].dest_ports[1] = NULL;
                state[i].called_name  = talloc_strdup(state[i].mem_ctx,
-                                                     cli->tree->session->transport->called.name);
-               state[i].service_type = talloc_strdup(state[i].mem_ctx,
-                                                     cli->tree->device);
+                               smbXcli_conn_remote_name(cli->tree->session->transport->conn));
+               state[i].service_type = talloc_strdup(state[i].mem_ctx, "?????");
        }
 
        num_connected = i;
index 9543eea1b10813c70078c2e115e4d97ca7737f16..7533c4fb65ccf2bd1fccd9c27dbf00ff4186b1bc 100644 (file)
@@ -34,6 +34,8 @@
 #include "libcli/resolve/resolve.h"
 #include "param/param.h"
 #include "torture/raw/proto.h"
+#include "libcli/smb/smbXcli_base.h"
+#include "../lib/util/util_net.h"
 
 #define BASEDIR "\\benchopen"
 
@@ -390,6 +392,11 @@ bool torture_bench_open(struct torture_context *torture)
 
        printf("Opening %d connections\n", nprocs);
        for (i=0;i<nprocs;i++) {
+               const struct sockaddr_storage *dest_ss;
+               char addrstr[INET6_ADDRSTRLEN];
+               const char *dest_str;
+               uint16_t dest_port;
+
                state[i].tctx = torture;
                state[i].mem_ctx = talloc_new(state);
                state[i].client_num = i;
@@ -397,19 +404,23 @@ bool torture_bench_open(struct torture_context *torture)
                if (!torture_open_connection_ev(&state[i].cli, i, torture, torture->ev)) {
                        return false;
                }
-               talloc_steal(mem_ctx, state);
+               talloc_steal(state[i].mem_ctx, state[i].cli);
                state[i].tree = state[i].cli->tree;
-               state[i].dest_host = talloc_strdup(state[i].mem_ctx, 
-                                                  state[i].cli->tree->session->transport->socket->hostname);
+
+               dest_ss = smbXcli_conn_remote_sockaddr(
+                               state[i].tree->session->transport->conn);
+               dest_str = print_sockaddr(addrstr, sizeof(addrstr), dest_ss);
+               dest_port = get_sockaddr_port(dest_ss);
+
+               state[i].dest_host = talloc_strdup(state[i].mem_ctx, dest_str);
                state[i].dest_ports = talloc_array(state[i].mem_ctx, 
                                                   const char *, 2);
                state[i].dest_ports[0] = talloc_asprintf(state[i].dest_ports, 
-                                                        "%u", state[i].cli->tree->session->transport->socket->port);
+                                                        "%u", dest_port);
                state[i].dest_ports[1] = NULL;
                state[i].called_name  = talloc_strdup(state[i].mem_ctx,
-                                                     state[i].cli->tree->session->transport->called.name);
-               state[i].service_type = talloc_strdup(state[i].mem_ctx,
-                                                     state[i].cli->tree->device);
+                               smbXcli_conn_remote_name(state[i].tree->session->transport->conn));
+               state[i].service_type = talloc_strdup(state[i].mem_ctx, "?????");
        }
 
        num_connected = i;