s4: Use same function signature for convert_* as s3.
[bbaumbach/samba-autobuild/.git] / source4 / smb_server / smb / request.c
index 8f6d66450026178264a03cfb58eef143d81e4373..6846f80594f937c73b10395e4397953a1fb0786e 100644 (file)
 #include "smbd/service_stream.h"
 #include "lib/stream/packet.h"
 #include "ntvfs/ntvfs.h"
-#include "param/param.h"
 
 
 /* we over allocate the data buffer to prevent too many realloc calls */
 #define REQ_OVER_ALLOCATION 0
 
+/* setup the bufinfo used for strings and range checking */
+void smbsrv_setup_bufinfo(struct smbsrv_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;
+}
+
+
 static int smbsrv_request_destructor(struct smbsrv_request *req)
 {
        DLIST_REMOVE(req->smb_conn->requests, req);
@@ -121,7 +134,12 @@ void smbsrv_setup_reply(struct smbsrv_request *req, uint_t wct, size_t buflen)
        flags2 = FLAGS2_LONG_PATH_COMPONENTS | 
                FLAGS2_EXTENDED_ATTRIBUTES | 
                FLAGS2_IS_LONG_NAME;
-       flags2 |= (req->flags2 & (FLAGS2_UNICODE_STRINGS|FLAGS2_EXTENDED_SECURITY));
+#define _SMB_FLAGS2_ECHOED_FLAGS ( \
+       FLAGS2_UNICODE_STRINGS | \
+       FLAGS2_EXTENDED_SECURITY | \
+       FLAGS2_SMB_SECURITY_SIGNATURES \
+)
+       flags2 |= (req->flags2 & _SMB_FLAGS2_ECHOED_FLAGS);
        if (req->smb_conn->negotiate.client_caps & CAP_STATUS32) {
                flags2 |= FLAGS2_32_BIT_ERROR_CODES;
        }
@@ -409,7 +427,7 @@ size_t req_push_str(struct smbsrv_request *req, uint8_t *dest, const char *str,
                dest = req->out.buffer + PTR_DIFF(dest, buf0);
        }
 
-       len = push_string(lp_iconv_convenience(global_loadparm), dest, str, len, flags);
+       len = push_string(dest, str, len, flags);
 
        grow_size = len + PTR_DIFF(dest, req->out.data);
 
@@ -461,13 +479,13 @@ size_t req_append_var_block(struct smbsrv_request *req,
   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 req_pull_ucs2(struct smbsrv_request *req, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
+static size_t req_pull_ucs2(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
 {
        int src_len, src_len2, alignment=0;
-       ssize_t ret;
+       bool ret;
        char *dest2;
 
-       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) {
@@ -478,7 +496,7 @@ static size_t req_pull_ucs2(struct smbsrv_request *req, const char **dest, const
        if (flags & STR_NO_RANGE_CHECK) {
                src_len = byte_len;
        } else {
-               src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
+               src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
                if (byte_len != -1 && src_len > byte_len) {
                        src_len = byte_len;
                }
@@ -491,13 +509,13 @@ static size_t req_pull_ucs2(struct smbsrv_request *req, const char **dest, const
        
        src_len2 = utf16_len_n(src, src_len);
        if (src_len2 == 0) {
-               *dest = talloc_strdup(req, "");
+               *dest = talloc_strdup(bufinfo->mem_ctx, "");
                return src_len2 + alignment;
        }
 
-       ret = convert_string_talloc(req, lp_iconv_convenience(global_loadparm), CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2);
+       ret = convert_string_talloc(bufinfo->mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, NULL, false);
 
-       if (ret == -1) {
+       if (!ret) {
                *dest = NULL;
                return 0;
        }
@@ -519,16 +537,16 @@ static size_t req_pull_ucs2(struct smbsrv_request *req, const char **dest, const
   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 req_pull_ascii(struct smbsrv_request *req, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
+static size_t req_pull_ascii(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
 {
        int src_len, src_len2;
-       ssize_t ret;
+       bool ret;
        char *dest2;
 
        if (flags & STR_NO_RANGE_CHECK) {
                src_len = byte_len;
        } else {
-               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;
@@ -544,9 +562,9 @@ static size_t req_pull_ascii(struct smbsrv_request *req, const char **dest, cons
                src_len2++;
        }
 
-       ret = convert_string_talloc(req, lp_iconv_convenience(global_loadparm), CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2);
+       ret = convert_string_talloc(bufinfo->mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, NULL, false);
 
-       if (ret == -1) {
+       if (!ret) {
                *dest = NULL;
                return 0;
        }
@@ -568,14 +586,14 @@ static size_t req_pull_ascii(struct smbsrv_request *req, const char **dest, cons
   on failure zero is returned and *dest is set to NULL, otherwise the number
   of bytes consumed in the packet is returned
 */
-size_t req_pull_string(struct smbsrv_request *req, const char **dest, const uint8_t *src, int byte_len, uint_t flags)
+size_t req_pull_string(struct request_bufinfo *bufinfo, const 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 req_pull_ucs2(req, dest, src, byte_len, flags);
+           (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
+               return req_pull_ucs2(bufinfo, dest, src, byte_len, flags);
        }
 
-       return req_pull_ascii(req, dest, src, byte_len, flags);
+       return req_pull_ascii(bufinfo, dest, src, byte_len, flags);
 }
 
 
@@ -588,13 +606,13 @@ size_t req_pull_string(struct smbsrv_request *req, const char **dest, const uint
   on failure *dest is set to the zero length string. This seems to
   match win2000 behaviour
 */
-size_t req_pull_ascii4(struct smbsrv_request *req, const char **dest, const uint8_t *src, uint_t flags)
+size_t req_pull_ascii4(struct request_bufinfo *bufinfo, const char **dest, const uint8_t *src, uint_t flags)
 {
        ssize_t ret;
 
-       if (PTR_DIFF(src, req->in.data) + 1 > req->in.data_size) {
+       if (PTR_DIFF(src, bufinfo->data) + 1 > bufinfo->data_size) {
                /* win2000 treats this as the empty string! */
-               (*dest) = talloc_strdup(req, "");
+               (*dest) = talloc_strdup(bufinfo->mem_ctx, "");
                return 0;
        }
 
@@ -603,9 +621,9 @@ size_t req_pull_ascii4(struct smbsrv_request *req, const char **dest, const uint
           behaviour */
        src++;
 
-       ret = req_pull_string(req, dest, src, -1, flags);
+       ret = req_pull_string(bufinfo, dest, src, -1, flags);
        if (ret == -1) {
-               (*dest) = talloc_strdup(req, "");
+               (*dest) = talloc_strdup(bufinfo->mem_ctx, "");
                return 1;
        }
        
@@ -617,30 +635,30 @@ size_t req_pull_ascii4(struct smbsrv_request *req, const char **dest, const uint
 
   return false if any part is outside the data portion of the packet
 */
-bool req_pull_blob(struct smbsrv_request *req, const uint8_t *src, int len, DATA_BLOB *blob)
+bool req_pull_blob(struct request_bufinfo *bufinfo, const uint8_t *src, int len, DATA_BLOB *blob)
 {
-       if (len != 0 && req_data_oob(req, src, len)) {
+       if (len != 0 && req_data_oob(bufinfo, src, len)) {
                return false;
        }
 
-       (*blob) = data_blob_talloc(req, src, len);
+       (*blob) = data_blob_talloc(bufinfo->mem_ctx, src, len);
 
        return true;
 }
 
 /* check that a lump of data in a request is within the bounds of the data section of
    the packet */
-bool req_data_oob(struct smbsrv_request *req, const uint8_t *ptr, uint32_t count)
+bool req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
 {
        if (count == 0) {
                return false;
        }
        
        /* 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;