Fix include paths to new location of libutil.
[samba.git] / source4 / libcli / raw / rawrequest.c
index 6a4f4320880007d872e9bdac7db79b8a3f9175d0..353b66c6220271a808688a73ef5e121e41aebaed 100644 (file)
 
 #include "includes.h"
 #include "libcli/raw/libcliraw.h"
-#include "lib/util/dlinklist.h"
+#include "libcli/raw/raw_proto.h"
+#include "../lib/util/dlinklist.h"
 #include "lib/events/events.h"
+#include "param/param.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ndr_misc.h"
 
 /* we over allocate the data buffer to prevent too many realloc calls */
 #define REQ_OVER_ALLOCATION 0
 /* assume that a character will not consume more than 3 bytes per char */
 #define MAX_BYTES_PER_CHAR 3
 
+/* setup the bufinfo used for strings and range checking */
+void smb_setup_bufinfo(struct smbcli_request *req)
+{
+       req->in.bufinfo.mem_ctx    = req;
+       req->in.bufinfo.flags      = 0;
+       if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
+               req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE;
+       }
+       req->in.bufinfo.align_base = req->in.buffer;
+       req->in.bufinfo.data       = req->in.data;
+       req->in.bufinfo.data_size  = req->in.data_size;
+}
+
+
 /* destroy a request structure and return final status */
-NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
+_PUBLIC_ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
 {
        NTSTATUS status;
 
@@ -54,7 +72,11 @@ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
        }
 
        status = req->status;
-       talloc_free(req);
+
+       if (!req->do_not_free) {
+               talloc_free(req);
+       }
+
        return status;
 }
 
@@ -297,6 +319,9 @@ NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
        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 */
+       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;
@@ -343,19 +368,6 @@ bool smbcli_request_receive(struct smbcli_request *req)
 }
 
 
-/*
-  receive another reply to a request - this is used for requests that
-  have multi-part replies (such as SMBtrans2)
-*/
-bool smbcli_request_receive_more(struct smbcli_request *req)
-{
-       req->state = SMBCLI_REQUEST_RECV;
-       DLIST_ADD(req->transport->pending_recv, req);
-
-       return smbcli_request_receive(req);
-}
-
-
 /*
   handle oplock break requests from the server - return true if the request was
   an oplock break
@@ -387,7 +399,7 @@ bool smbcli_handle_oplock_break(struct smbcli_transport *transport, uint_t len,
   wait for a reply to be received for a packet that just returns an error
   code and nothing more
 */
-NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
+_PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
 {
        (void) smbcli_request_receive(req);
        return smbcli_request_destroy(req);
@@ -418,7 +430,7 @@ size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uin
 
        smbcli_req_grow_allocation(req, len + req->out.data_size);
 
-       len = push_string(req->out.data + req->out.data_size, str, len, flags);
+       len = push_string(lp_iconv_convenience(global_loadparm), req->out.data + req->out.data_size, str, len, flags);
 
        smbcli_req_grow_data(req, len + req->out.data_size);
 
@@ -543,13 +555,13 @@ size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *by
   on failure zero is returned and *dest is set to NULL, otherwise 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,
+static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
                                char **dest, const uint8_t *src, int byte_len, uint_t flags)
 {
        int src_len, src_len2, alignment=0;
        ssize_t ret;
 
-       if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
+       if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
                src++;
                alignment=1;
                if (byte_len != -1) {
@@ -557,7 +569,7 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c
                }
        }
 
-       src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
+       src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
        if (src_len < 0) {
                *dest = NULL;
                return 0;
@@ -574,7 +586,7 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c
                return 0;
        }
 
-       ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest);
+       ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX, src, src_len2, (void **)dest);
        if (ret == -1) {
                *dest = NULL;
                return 0;
@@ -596,13 +608,13 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c
   on failure zero is returned and *dest is set to NULL, otherwise the number
   of bytes consumed in the packet is returned
 */
-size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
+size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
                             char **dest, const uint8_t *src, int byte_len, uint_t flags)
 {
        int src_len, src_len2;
        ssize_t ret;
 
-       src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
+       src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
        if (src_len < 0) {
                *dest = NULL;
                return 0;
@@ -616,7 +628,7 @@ size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
                src_len2++;
        }
 
-       ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest);
+       ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_DOS, CH_UNIX, src, src_len2, (void **)dest);
 
        if (ret == -1) {
                *dest = NULL;
@@ -626,7 +638,7 @@ size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-/*
+/**
   pull a string from a request packet, returning a talloced string
 
   the string length is limited by the 3 things:
@@ -639,29 +651,29 @@ size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
   on failure zero is returned and *dest is set to NULL, otherwise the number
   of bytes consumed in the packet is returned
 */
-size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx, 
+size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, 
                           char **dest, const uint8_t *src, int byte_len, uint_t flags)
 {
        if (!(flags & STR_ASCII) && 
-           (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
-               return smbcli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
+           (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
+               return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
        }
 
-       return smbcli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags);
+       return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
 }
 
 
-/*
+/**
   pull a DATA_BLOB from a reply packet, returning a talloced blob
   make sure we don't go past end of packet
 
   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 uint8_t *src, int byte_len)
+DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
 {
        int src_len;
 
-       src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
+       src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
 
        if (src_len < 0) {
                return data_blob(NULL, 0);
@@ -676,13 +688,13 @@ 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 uint8_t *ptr, uint32_t count)
+static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
 {
        /* be careful with wraparound! */
-       if (ptr < req->in.data ||
-           ptr >= req->in.data + req->in.data_size ||
-           count > req->in.data_size ||
-           ptr + count > req->in.data + req->in.data_size) {
+       if ((uintptr_t)ptr < (uintptr_t)bufinfo->data ||
+           (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size ||
+           count > bufinfo->data_size ||
+           (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) {
                return true;
        }
        return false;
@@ -693,11 +705,11 @@ static bool smbcli_req_data_oob(struct smbcli_request *req, const uint8_t *ptr,
 
   return false if any part is outside the data portion of the packet
 */
-bool smbcli_raw_pull_data(struct smbcli_request *req, const uint8_t *src, int len, uint8_t *dest)
+bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
 {
        if (len == 0) return true;
 
-       if (smbcli_req_data_oob(req, src, len)) {
+       if (smbcli_req_data_oob(bufinfo, src, len)) {
                return false;
        }
 
@@ -723,7 +735,7 @@ NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
        return ret;
 }
 
-/*
+/**
   pull a UCS2 string from a blob, returning a talloced unix string
 
   the string length is limited by the 3 things:
@@ -769,7 +781,7 @@ size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
 
        src_len2 = utf16_len_n(src, src_len);
 
-       ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
+       ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
        if (ret == -1) {
                *dest = NULL;
                return 0;
@@ -779,7 +791,7 @@ size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
        return src_len2 + alignment;
 }
 
-/*
+/**
   pull a ascii string from a blob, returning a talloced string
 
   the string length is limited by the 3 things:
@@ -815,7 +827,7 @@ static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
                src_len2++;
        }
 
-       ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
+       ret = convert_string_talloc(mem_ctx, lp_iconv_convenience(global_loadparm), CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
 
        if (ret == -1) {
                *dest = NULL;
@@ -826,7 +838,7 @@ static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-/*
+/**
   pull a string from a blob, returning a talloced struct smb_wire_string
 
   the string length is limited by the 3 things:
@@ -895,7 +907,7 @@ size_t smbcli_blob_pull_string(struct smbcli_session *session,
                                           blob->data+str_offset, dest->private_length, flags);
 }
 
-/*
+/**
   pull a string from a blob, returning a talloced char *
 
   Currently only used by the UNIX search info level.
@@ -965,9 +977,50 @@ size_t smbcli_blob_append_string(struct smbcli_session *session,
                return 0;
        }
 
-       len = push_string(blob->data + blob->length, str, max_len, flags);
+       len = push_string(lp_iconv_convenience(global_loadparm), blob->data + blob->length, str, max_len, flags);
 
        blob->length += len;
 
        return len;
 }
+
+/*
+  pull a GUID structure from the wire. The buffer must be at least 16
+  bytes long
+ */
+enum ndr_err_code smbcli_pull_guid(void *base, uint16_t offset, 
+                                  struct GUID *guid)
+{
+       DATA_BLOB blob;
+       TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+       enum ndr_err_code ndr_err;
+
+       ZERO_STRUCTP(guid);
+
+       blob.data       = offset + (uint8_t *)base;
+       blob.length     = 16;
+       ndr_err = ndr_pull_struct_blob(&blob, tmp_ctx, NULL, guid, 
+                                      (ndr_pull_flags_fn_t)ndr_pull_GUID);
+       talloc_free(tmp_ctx);
+       return ndr_err;
+}
+
+/*
+  push a guid onto the wire. The buffer must hold 16 bytes
+ */
+enum ndr_err_code smbcli_push_guid(void *base, uint16_t offset, 
+                                  const struct GUID *guid)
+{
+       TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+       enum ndr_err_code ndr_err;
+       DATA_BLOB blob;
+       ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL,
+                                      guid, (ndr_push_flags_fn_t)ndr_push_GUID);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || blob.length != 16) {
+               talloc_free(tmp_ctx);
+               return ndr_err;
+       }
+       memcpy(offset + (uint8_t *)base, blob.data, blob.length);
+       talloc_free(tmp_ctx);
+       return ndr_err;
+}