*/
#include "includes.h"
+#include "libcli/raw/libcliraw.h"
+#include "dlinklist.h"
/* we over allocate the data buffer to prevent too many realloc calls */
-#define REQ_OVER_ALLOCATION 256
+#define REQ_OVER_ALLOCATION 0
/* assume that a character will not consume more than 3 bytes per char */
#define MAX_BYTES_PER_CHAR 3
DLIST_REMOVE(req->transport->pending_recv, req);
}
- /* ahh, its so nice to destroy a complex structure in such a
- simple way! */
+ if (req->state == SMBCLI_REQUEST_ERROR &&
+ NT_STATUS_IS_OK(req->status)) {
+ req->status = NT_STATUS_INTERNAL_ERROR;
+ }
+
status = req->status;
- talloc_destroy(req->mem_ctx);
+ talloc_free(req);
return status;
}
struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, uint_t size)
{
struct smbcli_request *req;
- TALLOC_CTX *mem_ctx;
-
- /* each request gets its own talloc context. The request
- structure itself is also allocated inside this context,
- so we need to allocate it before we construct the request
- */
- mem_ctx = talloc_init("smbcli_request");
- if (!mem_ctx) {
- return NULL;
- }
- req = talloc(mem_ctx, sizeof(struct smbcli_request));
+ req = talloc_p(transport, struct smbcli_request);
if (!req) {
return NULL;
}
/* setup the request context */
req->state = SMBCLI_REQUEST_INIT;
- req->mem_ctx = mem_ctx;
req->transport = transport;
req->session = NULL;
req->tree = NULL;
/* over allocate by a small amount */
req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
- req->out.buffer = talloc(req->mem_ctx, req->out.allocated);
+ req->out.buffer = talloc(req, req->out.allocated);
if (!req->out.buffer) {
return NULL;
}
setup a SMB packet at transport level
*/
struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
- uint8_t command, uint_t wct, uint_t buflen)
+ uint8_t command, uint_t wct, uint_t buflen)
{
struct smbcli_request *req;
SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
SSVAL(req->out.hdr,HDR_FLG2, 0);
- /* assign a mid */
- req->mid = smbcli_transport_next_mid(transport);
+ 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);
way. This interface is used before a session is setup.
*/
struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
- uint8_t command, uint_t wct, uint_t buflen)
+ uint8_t command, uint_t wct, uint_t buflen)
{
struct smbcli_request *req;
- uint16_t flags2;
- uint32_t capabilities;
req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
if (!req) return NULL;
req->session = session;
-
- flags2 = FLAGS2_LONG_PATH_COMPONENTS;
- capabilities = session->transport->negotiate.capabilities;
- if (capabilities & CAP_UNICODE) {
- flags2 |= FLAGS2_UNICODE_STRINGS;
- }
- if (capabilities & CAP_STATUS32) {
- flags2 |= FLAGS2_32_BIT_ERROR_CODES;
- }
- if (capabilities & CAP_EXTENDED_SECURITY) {
- flags2 |= FLAGS2_EXTENDED_SECURITY;
- }
- if (session->transport->negotiate.sign_info.doing_signing) {
- flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
- }
-
- SSVAL(req->out.hdr, HDR_FLG2, flags2);
+ SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
SSVAL(req->out.hdr, HDR_UID, session->vuid);
static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
{
int delta;
- char *buf2;
+ uint8_t *buf2;
delta = new_size - req->out.data_size;
if (delta + req->out.size <= req->out.allocated) {
/* we need to realloc */
req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
- buf2 = talloc_realloc(req->mem_ctx, req->out.buffer, req->out.allocated);
+ buf2 = talloc_realloc(req, req->out.buffer, req->out.allocated);
if (buf2 == NULL) {
smb_panic("out of memory in req_grow_allocation");
}
To cope with this req->out.ptr is supplied. This will be updated to
point at the same offset into the packet as before this call
*/
-void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
+static void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
{
int delta;
/* keep receiving packets until this one is replied to */
while (req->state <= SMBCLI_REQUEST_RECV) {
- event_loop_once(req->transport->event.ctx);
+ if (event_loop_once(req->transport->event.ctx) != 0) {
+ return False;
+ }
}
return req->state == SMBCLI_REQUEST_DONE;
handle oplock break requests from the server - return True if the request was
an oplock break
*/
-BOOL handle_oplock_break(struct smbcli_transport *transport, uint_t len, const char *hdr, const char *vwv)
+BOOL handle_oplock_break(struct smbcli_transport *transport, uint_t 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 */
smbcli_req_grow_allocation(req, len + req->out.data_size);
- len = push_string(NULL, req->out.data + req->out.data_size, str, len, flags);
+ len = push_string(req->out.data + req->out.data_size, str, len, flags);
smbcli_req_grow_data(req, len + req->out.data_size);
return len;
}
+
/*
this is like smbcli_req_append_string but it also return the
non-terminated string byte length, which can be less than the number
of bytes consumed in the packet is returned
*/
static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
- char **dest, const char *src, int byte_len, uint_t flags)
+ char **dest, const uint8_t *src, int byte_len, uint_t flags)
{
int src_len, src_len2, alignment=0;
ssize_t ret;
src_len = byte_len;
}
- src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
- if (src_len2 < src_len - 2) {
- /* include the termination if we didn't reach the end of the packet */
- src_len2 += 2;
- }
+ src_len2 = utf16_len_n(src, src_len);
/* ucs2 strings must be at least 2 bytes long */
if (src_len2 < 2) {
return 0;
}
- ret = convert_string_talloc(mem_ctx, CH_UCS2, CH_UNIX, src, src_len2, (const void **)dest);
+ ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest);
if (ret == -1) {
*dest = NULL;
return 0;
of bytes consumed in the packet is returned
*/
size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
- char **dest, const char *src, int byte_len, uint_t flags)
+ char **dest, const uint8_t *src, int byte_len, uint_t flags)
{
int src_len, src_len2;
ssize_t ret;
if (byte_len != -1 && src_len > byte_len) {
src_len = byte_len;
}
- src_len2 = strnlen(src, src_len);
+ src_len2 = strnlen((const char *)src, src_len);
if (src_len2 < src_len - 1) {
/* include the termination if we didn't reach the end of the packet */
src_len2++;
}
- ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (const void **)dest);
+ ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest);
if (ret == -1) {
*dest = NULL;
of bytes consumed in the packet is returned
*/
size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
- char **dest, const char *src, int byte_len, uint_t flags)
+ char **dest, const uint8_t *src, int byte_len, uint_t flags)
{
if (!(flags & STR_ASCII) &&
(((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
if byte_len is -1 then limit the blob only by packet size
*/
-DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, const char *src, int byte_len)
+DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
{
int src_len;
/* check that a lump of data in a request is within the bounds of the data section of
the packet */
-static BOOL smbcli_req_data_oob(struct smbcli_request *req, const char *ptr, uint32_t count)
+static BOOL smbcli_req_data_oob(struct smbcli_request *req, const uint8_t *ptr, uint32_t count)
{
/* be careful with wraparound! */
if (ptr < req->in.data ||
return False if any part is outside the data portion of the packet
*/
-BOOL smbcli_raw_pull_data(struct smbcli_request *req, const char *src, int len, char *dest)
+BOOL smbcli_raw_pull_data(struct smbcli_request *req, const uint8_t *src, int len, uint8_t *dest)
{
if (len == 0) return True;
*/
static size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
DATA_BLOB *blob, const char **dest,
- const char *src, int byte_len, uint_t flags)
+ const uint8_t *src, int byte_len, uint_t flags)
{
int src_len, src_len2, alignment=0;
ssize_t ret;
+ char *dest2;
- if (src < (const char *)blob->data ||
- src >= (const char *)(blob->data + blob->length)) {
+ if (src < blob->data ||
+ src >= (blob->data + blob->length)) {
*dest = NULL;
return 0;
}
return 0;
}
- src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
-
- if (src_len2 < src_len - 2) {
- /* include the termination if we didn't reach the end of the packet */
- src_len2 += 2;
- }
+ src_len2 = utf16_len_n(src, src_len);
- ret = convert_string_talloc(mem_ctx, CH_UCS2, CH_UNIX, src, src_len2, (const void **)dest);
+ ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
if (ret == -1) {
*dest = NULL;
return 0;
}
+ *dest = dest2;
return src_len2 + alignment;
}
*/
static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
DATA_BLOB *blob, const char **dest,
- const char *src, int byte_len, uint_t flags)
+ const uint8_t *src, int byte_len, uint_t flags)
{
int src_len, src_len2;
ssize_t ret;
+ char *dest2;
src_len = blob->length - PTR_DIFF(src, blob->data);
if (src_len < 0) {
if (byte_len != -1 && src_len > byte_len) {
src_len = byte_len;
}
- src_len2 = strnlen(src, src_len);
+ src_len2 = strnlen((const char *)src, src_len);
if (src_len2 < src_len - 1) {
/* include the termination if we didn't reach the end of the packet */
src_len2++;
}
- ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (const void **)dest);
+ ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
if (ret == -1) {
*dest = NULL;
return 0;
}
+ *dest = dest2;
return ret;
}
return 0;
}
- len = push_string(NULL, blob->data + blob->length, str, max_len, flags);
+ len = push_string(blob->data + blob->length, str, max_len, flags);
blob->length += len;