r4229: - added support for multi-part SMBtrans and SMBtrans2 requests in the
[samba.git] / source4 / libcli / raw / rawrequest.c
index 1ff36d0a8dc96956e45c2863868732bf362900a0..5c35618e000002aff7b7ed2b34c43b588aa2b31b 100644 (file)
 */
 
 #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
@@ -46,8 +48,11 @@ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
                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_free(req);
        return status;
@@ -62,7 +67,7 @@ struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *tran
 {
        struct smbcli_request *req;
 
-       req = talloc_named(NULL, sizeof(struct smbcli_request), "smcli_request");
+       req = talloc_p(transport, struct smbcli_request);
        if (!req) {
                return NULL;
        }
@@ -93,7 +98,7 @@ struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *tran
   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;
 
@@ -117,8 +122,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);
 
-       /* 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);
@@ -139,35 +146,17 @@ struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *t
   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);
@@ -203,7 +192,7 @@ struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
 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) {
@@ -213,7 +202,7 @@ static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_si
 
        /* we need to realloc */
        req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
-       buf2 = talloc_realloc(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");
        }
@@ -241,7 +230,7 @@ static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_si
   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;
 
@@ -311,7 +300,7 @@ BOOL smbcli_request_receive_more(struct smbcli_request *req)
   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 */
@@ -495,7 +484,7 @@ size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *by
   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;
@@ -517,11 +506,7 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c
                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) {
@@ -552,7 +537,7 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c
   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;
@@ -565,7 +550,7 @@ size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
        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++;
@@ -595,7 +580,7 @@ size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
   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)))) {
@@ -612,7 +597,7 @@ size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
 
   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;
 
@@ -631,7 +616,7 @@ DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
 
 /* 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 ||
@@ -648,7 +633,7 @@ static BOOL smbcli_req_data_oob(struct smbcli_request *req, const char *ptr, uin
 
   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;
 
@@ -693,14 +678,14 @@ NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
 */
 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;
        }
@@ -722,12 +707,7 @@ static size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
                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_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
        if (ret == -1) {
@@ -754,7 +734,7 @@ static size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
 */
 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;
@@ -768,7 +748,7 @@ static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
        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 */
@@ -911,7 +891,7 @@ size_t smbcli_blob_append_string(struct smbcli_session *session,
 
        max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;         
 
-       blob->data = talloc_realloc(blob->data, blob->length + max_len);
+       blob->data = talloc_realloc(mem_ctx, blob->data, blob->length + max_len);
        if (!blob->data) {
                return 0;
        }