summaryrefslogtreecommitdiff
path: root/source4/libcli/raw/rawrequest.c
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/libcli/raw/rawrequest.c
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/libcli/raw/rawrequest.c')
-rw-r--r--source4/libcli/raw/rawrequest.c227
1 files changed, 125 insertions, 102 deletions
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