summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-09-23 08:35:17 +0200
committerStefan Metzmacher <metze@samba.org>2011-11-30 15:13:36 +0100
commit4afbda221c20ffa36a1d1e37ef11f86073a49da6 (patch)
tree8d9cc7d03f5bb4ea4ffa761dfee0ba7e9cdc005c /source4
parent99ef6a4bec1058b3649e5e72f8ea85f6df93a154 (diff)
downloadsamba-4afbda221c20ffa36a1d1e37ef11f86073a49da6.tar.gz
samba-4afbda221c20ffa36a1d1e37ef11f86073a49da6.tar.bz2
samba-4afbda221c20ffa36a1d1e37ef11f86073a49da6.zip
s4:libcli/raw: implement on top of smbXcli_conn/req
metze Autobuild-User: Stefan Metzmacher <metze@samba.org> Autobuild-Date: Wed Nov 30 15:13:36 CET 2011 on sn-devel-104
Diffstat (limited to 'source4')
-rw-r--r--source4/libcli/cliconnect.c23
-rw-r--r--source4/libcli/libcli.h3
-rw-r--r--source4/libcli/raw/clioplock.c11
-rw-r--r--source4/libcli/raw/clisession.c3
-rw-r--r--source4/libcli/raw/clisocket.c13
-rw-r--r--source4/libcli/raw/clitransport.c713
-rw-r--r--source4/libcli/raw/libcliraw.h68
-rw-r--r--source4/libcli/raw/rawnegotiate.c253
-rw-r--r--source4/libcli/raw/rawnotify.c64
-rw-r--r--source4/libcli/raw/rawreadwrite.c6
-rw-r--r--source4/libcli/raw/rawrequest.c227
-rw-r--r--source4/libcli/raw/rawtrans.c1126
-rw-r--r--source4/libcli/raw/smb_signing.c175
-rw-r--r--source4/libcli/smb_composite/connect.c28
-rw-r--r--source4/libcli/smb_composite/sesssetup.c42
-rw-r--r--source4/librpc/rpc/dcerpc_smb.c10
-rw-r--r--source4/ntvfs/cifs/vfs_cifs.c3
-rw-r--r--source4/torture/basic/base.c26
-rw-r--r--source4/torture/raw/lockbench.c26
-rw-r--r--source4/torture/raw/openbench.c25
20 files changed, 1033 insertions, 1812 deletions
diff --git a/source4/libcli/cliconnect.c b/source4/libcli/cliconnect.c
index a8e86a0488..45d8d2a776 100644
--- a/source4/libcli/cliconnect.c
+++ b/source4/libcli/cliconnect.c
@@ -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);
}
diff --git a/source4/libcli/libcli.h b/source4/libcli/libcli.h
index 9f661e3f4d..9e817408de 100644
--- a/source4/libcli/libcli.h
+++ b/source4/libcli/libcli.h
@@ -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;
diff --git a/source4/libcli/raw/clioplock.c b/source4/libcli/raw/clioplock.c
index 42ac6b517b..396ab96445 100644
--- a/source4/libcli/raw/clioplock.c
+++ b/source4/libcli/raw/clioplock.c
@@ -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;
}
diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c
index 41765bfb2b..d68f309519 100644
--- a/source4/libcli/raw/clisession.c
+++ b/source4/libcli/raw/clisession.c
@@ -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;
}
diff --git a/source4/libcli/raw/clisocket.c b/source4/libcli/raw/clisocket.c
index 258fe8b091..dd3ea3971c 100644
--- a/source4/libcli/raw/clisocket.c
+++ b/source4/libcli/raw/clisocket.c
@@ -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;
-}
-
diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c
index b83a07063c..f1f41bcb78 100644
--- a/source4/libcli/raw/clitransport.c
+++ b/source4/libcli/raw/clitransport.c
@@ -20,33 +20,17 @@
*/
#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);
}
diff --git a/source4/libcli/raw/libcliraw.h b/source4/libcli/raw/libcliraw.h
index b3d32273b2..81bf715f08 100644
--- a/source4/libcli/raw/libcliraw.h
+++ b/source4/libcli/raw/libcliraw.h
@@ -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__ */
diff --git a/source4/libcli/raw/rawnegotiate.c b/source4/libcli/raw/rawnegotiate.c
index 9d6c9ffaf2..9b0ed38cf0 100644
--- a/source4/libcli/raw/rawnegotiate.c
+++ b/source4/libcli/raw/rawnegotiate.c
@@ -21,184 +21,106 @@
*/
#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;
}
diff --git a/source4/libcli/raw/rawnotify.c b/source4/libcli/raw/rawnotify.c
index 40256aa405..dcb979b28a 100644
--- a/source4/libcli/raw/rawnotify.c
+++ b/source4/libcli/raw/rawnotify.c
@@ -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)
@@ -101,68 +101,22 @@ _PUBLIC_ NTSTATUS smb_raw_changenotify_recv(struct smbcli_request *req,
}
/****************************************************************************
- 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
note that this request does not expect a response!
****************************************************************************/
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;
}
diff --git a/source4/libcli/raw/rawreadwrite.c b/source4/libcli/raw/rawreadwrite.c
index 68977ebd3e..d3f5518e01 100644
--- a/source4/libcli/raw/rawreadwrite.c
+++ b/source4/libcli/raw/rawreadwrite.c
@@ -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;
}
diff --git a/source4/libcli/raw/rawrequest.c b/source4/libcli/raw/rawrequest.c
index ae68fb0cd3..1b4c8c7524 100644
--- a/source4/libcli/raw/rawrequest.c
+++ b/source4/libcli/raw/rawrequest.c
@@ -25,10 +25,10 @@
#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
diff --git a/source4/libcli/raw/rawtrans.c b/source4/libcli/raw/rawtrans.c
index dd017715c7..8e16e5b911 100644
--- a/source4/libcli/raw/rawtrans.c
+++ b/source4/libcli/raw/rawtrans.c
@@ -19,513 +19,201 @@
*/
#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
****************************************************************************/
diff --git a/source4/libcli/raw/smb_signing.c b/source4/libcli/raw/smb_signing.c
index e1d7a2d187..5d2f928747 100644
--- a/source4/libcli/raw/smb_signing.c
+++ b/source4/libcli/raw/smb_signing.c
@@ -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;
-}
diff --git a/source4/libcli/smb_composite/connect.c b/source4/libcli/smb_composite/connect.c
index 0f66f2873d..0688684e95 100644
--- a/source4/libcli/smb_composite/connect.c
+++ b/source4/libcli/smb_composite/connect.c
@@ -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);
}
diff --git a/source4/libcli/smb_composite/sesssetup.c b/source4/libcli/smb_composite/sesssetup.c
index cafaacd8bb..63f3a8e10d 100644
--- a/source4/libcli/smb_composite/sesssetup.c
+++ b/source4/libcli/smb_composite/sesssetup.c
@@ -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;
}
diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c
index bdba21734c..f4f44577f4 100644
--- a/source4/librpc/rpc/dcerpc_smb.c
+++ b/source4/librpc/rpc/dcerpc_smb.c
@@ -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;
diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c
index 91ca08d2de..72dff99ccf 100644
--- a/source4/ntvfs/cifs/vfs_cifs.c
+++ b/source4/ntvfs/cifs/vfs_cifs.c
@@ -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; \
} \
diff --git a/source4/torture/basic/base.c b/source4/torture/basic/base.c
index d1005d0bdc..56461005e8 100644
--- a/source4/torture/basic/base.c
+++ b/source4/torture/basic/base.c
@@ -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;
}
diff --git a/source4/torture/raw/lockbench.c b/source4/torture/raw/lockbench.c
index 0a4faface8..1f016f0ee0 100644
--- a/source4/torture/raw/lockbench.c
+++ b/source4/torture/raw/lockbench.c
@@ -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;
diff --git a/source4/torture/raw/openbench.c b/source4/torture/raw/openbench.c
index 9543eea1b1..7533c4fb65 100644
--- a/source4/torture/raw/openbench.c
+++ b/source4/torture/raw/openbench.c
@@ -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;