Finish removal of iconv_convenience in public API's.
[samba.git] / source4 / smb_server / blob.c
index 4cf484f6a080afdd98d20ecd12c85f21e81cf130..c17cde070d6b53845105edabc8088e5f8c435230 100644 (file)
@@ -6,7 +6,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "dlinklist.h"
 #include "smb_server/smb_server.h"
 #include "librpc/gen_ndr/ndr_misc.h"
-#include "ntvfs/ntvfs.h"
 #include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
 
 #define BLOB_CHECK(cmd) do { \
        NTSTATUS _status; \
 
 #define BLOB_CHECK_MIN_SIZE(blob, size) do { \
        if ((blob)->length < (size)) { \
-               return NT_STATUS_INFO_LENGTH_MISMATCH; \
+               return NT_STATUS_INVALID_PARAMETER; \
+       } \
+} while (0)
+
+
+/* align the end of the blob on an 8 byte boundary */
+#define BLOB_ALIGN(blob, alignment) do { \
+       if ((blob)->length & ((alignment)-1)) { \
+               uint8_t _pad = (alignment) - ((blob)->length & ((alignment)-1)); \
+               BLOB_CHECK(smbsrv_blob_fill_data(blob, blob, (blob)->length+_pad)); \
        } \
 } while (0)
 
@@ -69,7 +76,7 @@ NTSTATUS smbsrv_blob_fill_data(TALLOC_CTX *mem_ctx,
 /*
   pull a string from a blob in a trans2 request
 */
-size_t smbsrv_blob_pull_string(struct smbsrv_request *req
+size_t smbsrv_blob_pull_string(struct request_bufinfo *bufinfo
                               const DATA_BLOB *blob,
                               uint16_t offset,
                               const char **str,
@@ -83,7 +90,7 @@ size_t smbsrv_blob_pull_string(struct smbsrv_request *req,
                return 0;
        }
        
-       return req_pull_string(req, str, 
+       return req_pull_string(bufinfo, str, 
                               blob->data + offset, 
                               blob->length - offset,
                               STR_NO_RANGE_CHECK | flags);
@@ -166,7 +173,7 @@ size_t smbsrv_blob_push_string(TALLOC_CTX *mem_ctx,
 NTSTATUS smbsrv_blob_append_string(TALLOC_CTX *mem_ctx,
                                   DATA_BLOB *blob,
                                   const char *str,
-                                  uint_t len_offset,
+                                  unsigned int len_offset,
                                   int default_flags,
                                   int flags)
 {
@@ -190,7 +197,7 @@ NTSTATUS smbsrv_push_passthru_fsinfo(TALLOC_CTX *mem_ctx,
                                     union smb_fsinfo *fsinfo,
                                     int default_str_flags)
 {
-       uint_t i;
+       unsigned int i;
        DATA_BLOB guid_blob;
 
        switch (level) {
@@ -264,12 +271,16 @@ NTSTATUS smbsrv_push_passthru_fsinfo(TALLOC_CTX *mem_ctx,
 
                return NT_STATUS_OK;
 
-       case RAW_QFS_OBJECTID_INFORMATION:
+       case RAW_QFS_OBJECTID_INFORMATION: {
+               NTSTATUS status;
+
                BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 64));
 
-               BLOB_CHECK(ndr_push_struct_blob(&guid_blob, mem_ctx, 
-                                               &fsinfo->objectid_information.out.guid,
-                                               (ndr_push_flags_fn_t)ndr_push_GUID));
+               status = GUID_to_ndr_blob(&fsinfo->objectid_information.out.guid, mem_ctx, &guid_blob);
+               if (!NT_STATUS_IS_OK(status)) {
+                       BLOB_CHECK(status);
+               }
+
                memcpy(blob->data, guid_blob.data, guid_blob.length);
 
                for (i=0;i<6;i++) {
@@ -277,7 +288,7 @@ NTSTATUS smbsrv_push_passthru_fsinfo(TALLOC_CTX *mem_ctx,
                }
 
                return NT_STATUS_OK;
-
+       }
        default:
                return NT_STATUS_INVALID_LEVEL;
        }
@@ -291,7 +302,7 @@ NTSTATUS smbsrv_push_passthru_fileinfo(TALLOC_CTX *mem_ctx,
                                       union smb_fileinfo *st,
                                       int default_str_flags)
 {
-       uint_t i;
+       unsigned int i;
        size_t list_size;
 
        switch (level) {
@@ -460,12 +471,12 @@ NTSTATUS smbsrv_push_passthru_fileinfo(TALLOC_CTX *mem_ctx,
                }
 
                list_size = ea_list_size_chained(st->all_eas.out.num_eas,
-                                                st->all_eas.out.eas);
+                                                st->all_eas.out.eas, 4);
                BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size));
 
                ea_put_list_chained(blob->data,
                                    st->all_eas.out.num_eas,
-                                   st->all_eas.out.eas);
+                                   st->all_eas.out.eas, 4);
                return NT_STATUS_OK;
 
        case RAW_FILEINFO_SMB2_ALL_INFORMATION:
@@ -482,11 +493,13 @@ NTSTATUS smbsrv_push_passthru_fileinfo(TALLOC_CTX *mem_ctx,
                SIVAL(blob->data,       0x38, st->all_info2.out.nlink);
                SCVAL(blob->data,       0x3C, st->all_info2.out.delete_pending);
                SCVAL(blob->data,       0x3D, st->all_info2.out.directory);
+               SSVAL(blob->data,       0x3E, 0); /* padding */
                SBVAL(blob->data,       0x40, st->all_info2.out.file_id);
                SIVAL(blob->data,       0x48, st->all_info2.out.ea_size);
                SIVAL(blob->data,       0x4C, st->all_info2.out.access_mask);
                SBVAL(blob->data,       0x50, st->all_info2.out.position);
-               SBVAL(blob->data,       0x58, st->all_info2.out.mode);
+               SIVAL(blob->data,       0x58, st->all_info2.out.mode);
+               SIVAL(blob->data,       0x5C, st->all_info2.out.alignment_requirement);
                BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
                                                     st->all_info2.out.fname.s,
                                                     0x60, default_str_flags,
@@ -505,20 +518,21 @@ NTSTATUS smbsrv_pull_passthru_sfileinfo(TALLOC_CTX *mem_ctx,
                                        union smb_setfileinfo *st,
                                        const DATA_BLOB *blob,
                                        int default_str_flags,
-                                       struct smbsrv_request *req)
+                                       struct request_bufinfo *bufinfo)
 {
-       uint32_t len;
+       uint32_t len, ofs;
        DATA_BLOB str_blob;
 
        switch (level) {
        case SMB_SFILEINFO_BASIC_INFORMATION:
-               BLOB_CHECK_MIN_SIZE(blob, 36);
+               BLOB_CHECK_MIN_SIZE(blob, 40);
 
                st->basic_info.in.create_time = pull_nttime(blob->data,  0);
                st->basic_info.in.access_time = pull_nttime(blob->data,  8);
                st->basic_info.in.write_time =  pull_nttime(blob->data, 16);
                st->basic_info.in.change_time = pull_nttime(blob->data, 24);
-               st->basic_info.in.attrib =      IVAL(blob->data,        32);
+               st->basic_info.in.attrib      = IVAL(blob->data,        32);
+               st->basic_info.in.reserved    = IVAL(blob->data,        36);
 
                return NT_STATUS_OK;
 
@@ -544,21 +558,59 @@ NTSTATUS smbsrv_pull_passthru_sfileinfo(TALLOC_CTX *mem_ctx,
                return NT_STATUS_OK;
 
        case RAW_SFILEINFO_RENAME_INFORMATION:
-               if (!req) {
-                       /* 
-                        * TODO: get rid of smbsrv_request argument of
-                        * smbsrv_blob_pull_string()
-                        */
-                       return NT_STATUS_NOT_IMPLEMENTED;
+               if (!bufinfo) {
+                       return NT_STATUS_INTERNAL_ERROR;
                }
                BLOB_CHECK_MIN_SIZE(blob, 12);
-
                st->rename_information.in.overwrite = CVAL(blob->data, 0);
                st->rename_information.in.root_fid  = IVAL(blob->data, 4);
                len                                 = IVAL(blob->data, 8);
-               str_blob.data = blob->data+12;
-               str_blob.length = MIN(blob->length, len);
-               smbsrv_blob_pull_string(req, &str_blob, 0,
+               ofs                                 = 12;
+               str_blob = *blob;
+               str_blob.length = MIN(str_blob.length, ofs+len);
+               smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
+                                       &st->rename_information.in.new_name,
+                                       STR_UNICODE);
+               if (st->rename_information.in.new_name == NULL) {
+                       return NT_STATUS_FOOBAR;
+               }
+
+               return NT_STATUS_OK;
+
+
+       case RAW_SFILEINFO_LINK_INFORMATION:
+               if (!bufinfo) {
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+               BLOB_CHECK_MIN_SIZE(blob, 20);
+               st->link_information.in.overwrite = CVAL(blob->data, 0);
+               st->link_information.in.root_fid  = IVAL(blob->data, 8);
+               len                                 = IVAL(blob->data, 16);
+               ofs                                 = 20;
+               str_blob = *blob;
+               str_blob.length = MIN(str_blob.length, ofs+len);
+               smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
+                                       &st->link_information.in.new_name,
+                                       STR_UNICODE);
+               if (st->link_information.in.new_name == NULL) {
+                       return NT_STATUS_FOOBAR;
+               }
+
+               return NT_STATUS_OK;
+
+       case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
+               /* SMB2 uses a different format for rename information */
+               if (!bufinfo) {
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+               BLOB_CHECK_MIN_SIZE(blob, 20);
+               st->rename_information.in.overwrite = CVAL(blob->data, 0);
+               st->rename_information.in.root_fid  = BVAL(blob->data, 8);
+               len                                 = IVAL(blob->data,16);
+               ofs                                 = 20;                       
+               str_blob = *blob;
+               str_blob.length = MIN(str_blob.length, ofs+len);
+               smbsrv_blob_pull_string(bufinfo, &str_blob, ofs,
                                        &st->rename_information.in.new_name,
                                        STR_UNICODE);
                if (st->rename_information.in.new_name == NULL) {
@@ -587,3 +639,151 @@ NTSTATUS smbsrv_pull_passthru_sfileinfo(TALLOC_CTX *mem_ctx,
 
        return NT_STATUS_INVALID_LEVEL;
 }
+
+/*
+  fill a single entry in a trans2 find reply 
+*/
+NTSTATUS smbsrv_push_passthru_search(TALLOC_CTX *mem_ctx,
+                                    DATA_BLOB *blob,
+                                    enum smb_search_data_level level,
+                                    const union smb_search_data *file,
+                                    int default_str_flags)
+{
+       uint8_t *data;
+       unsigned int ofs = blob->length;
+
+       switch (level) {
+       case RAW_SEARCH_DATA_DIRECTORY_INFO:
+               BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 64));
+               data = blob->data + ofs;
+               SIVAL(data,          4, file->directory_info.file_index);
+               push_nttime(data,    8, file->directory_info.create_time);
+               push_nttime(data,   16, file->directory_info.access_time);
+               push_nttime(data,   24, file->directory_info.write_time);
+               push_nttime(data,   32, file->directory_info.change_time);
+               SBVAL(data,         40, file->directory_info.size);
+               SBVAL(data,         48, file->directory_info.alloc_size);
+               SIVAL(data,         56, file->directory_info.attrib);
+               BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->directory_info.name.s,
+                                                    ofs + 60, default_str_flags,
+                                                    STR_TERMINATE_ASCII));
+               BLOB_ALIGN(blob, 8);
+               data = blob->data + ofs;
+               SIVAL(data,          0, blob->length - ofs);
+               return NT_STATUS_OK;
+
+       case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
+               BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 68));
+               data = blob->data + ofs;
+               SIVAL(data,          4, file->full_directory_info.file_index);
+               push_nttime(data,    8, file->full_directory_info.create_time);
+               push_nttime(data,   16, file->full_directory_info.access_time);
+               push_nttime(data,   24, file->full_directory_info.write_time);
+               push_nttime(data,   32, file->full_directory_info.change_time);
+               SBVAL(data,         40, file->full_directory_info.size);
+               SBVAL(data,         48, file->full_directory_info.alloc_size);
+               SIVAL(data,         56, file->full_directory_info.attrib);
+               SIVAL(data,         64, file->full_directory_info.ea_size);
+               BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->full_directory_info.name.s, 
+                                                    ofs + 60, default_str_flags,
+                                                    STR_TERMINATE_ASCII));
+               BLOB_ALIGN(blob, 8);
+               data = blob->data + ofs;
+               SIVAL(data,          0, blob->length - ofs);
+               return NT_STATUS_OK;
+
+       case RAW_SEARCH_DATA_NAME_INFO:
+               BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 12));
+               data = blob->data + ofs;
+               SIVAL(data,          4, file->name_info.file_index);
+               BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->name_info.name.s, 
+                                                    ofs + 8, default_str_flags,
+                                                    STR_TERMINATE_ASCII));
+               BLOB_ALIGN(blob, 8);
+               data = blob->data + ofs;
+               SIVAL(data,          0, blob->length - ofs);
+               return NT_STATUS_OK;
+
+       case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
+               BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 94));
+               data = blob->data + ofs;
+               SIVAL(data,          4, file->both_directory_info.file_index);
+               push_nttime(data,    8, file->both_directory_info.create_time);
+               push_nttime(data,   16, file->both_directory_info.access_time);
+               push_nttime(data,   24, file->both_directory_info.write_time);
+               push_nttime(data,   32, file->both_directory_info.change_time);
+               SBVAL(data,         40, file->both_directory_info.size);
+               SBVAL(data,         48, file->both_directory_info.alloc_size);
+               SIVAL(data,         56, file->both_directory_info.attrib);
+               SIVAL(data,         64, file->both_directory_info.ea_size);
+               SCVAL(data,         69, 0); /* reserved */
+               memset(data+70,0,24);
+               smbsrv_blob_push_string(mem_ctx, blob, 
+                                       68 + ofs, 70 + ofs, 
+                                       file->both_directory_info.short_name.s, 
+                                       24, default_str_flags,
+                                       STR_UNICODE | STR_LEN8BIT);
+               BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->both_directory_info.name.s, 
+                                                    ofs + 60, default_str_flags,
+                                                    STR_TERMINATE_ASCII));
+               BLOB_ALIGN(blob, 8);
+               data = blob->data + ofs;
+               SIVAL(data,          0, blob->length - ofs);
+               return NT_STATUS_OK;
+
+       case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
+               BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 80));
+               data = blob->data + ofs;
+               SIVAL(data,          4, file->id_full_directory_info.file_index);
+               push_nttime(data,    8, file->id_full_directory_info.create_time);
+               push_nttime(data,   16, file->id_full_directory_info.access_time);
+               push_nttime(data,   24, file->id_full_directory_info.write_time);
+               push_nttime(data,   32, file->id_full_directory_info.change_time);
+               SBVAL(data,         40, file->id_full_directory_info.size);
+               SBVAL(data,         48, file->id_full_directory_info.alloc_size);
+               SIVAL(data,         56, file->id_full_directory_info.attrib);
+               SIVAL(data,         64, file->id_full_directory_info.ea_size);
+               SIVAL(data,         68, 0); /* padding */
+               SBVAL(data,         72, file->id_full_directory_info.file_id);
+               BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->id_full_directory_info.name.s, 
+                                                    ofs + 60, default_str_flags,
+                                                    STR_TERMINATE_ASCII));
+               BLOB_ALIGN(blob, 8);
+               data = blob->data + ofs;
+               SIVAL(data,          0, blob->length - ofs);
+               return NT_STATUS_OK;
+
+       case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
+               BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, ofs + 104));
+               data = blob->data + ofs;
+               SIVAL(data,          4, file->id_both_directory_info.file_index);
+               push_nttime(data,    8, file->id_both_directory_info.create_time);
+               push_nttime(data,   16, file->id_both_directory_info.access_time);
+               push_nttime(data,   24, file->id_both_directory_info.write_time);
+               push_nttime(data,   32, file->id_both_directory_info.change_time);
+               SBVAL(data,         40, file->id_both_directory_info.size);
+               SBVAL(data,         48, file->id_both_directory_info.alloc_size);
+               SIVAL(data,         56, file->id_both_directory_info.attrib);
+               SIVAL(data,         64, file->id_both_directory_info.ea_size);
+               SCVAL(data,         69, 0); /* reserved */
+               memset(data+70,0,26);
+               smbsrv_blob_push_string(mem_ctx, blob, 
+                                       68 + ofs, 70 + ofs, 
+                                       file->id_both_directory_info.short_name.s, 
+                                       24, default_str_flags,
+                                       STR_UNICODE | STR_LEN8BIT);
+               SBVAL(data,         96, file->id_both_directory_info.file_id);
+               BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, file->id_both_directory_info.name.s, 
+                                                    ofs + 60, default_str_flags,
+                                                    STR_TERMINATE_ASCII));
+               BLOB_ALIGN(blob, 8);
+               data = blob->data + ofs;
+               SIVAL(data,          0, blob->length - ofs);
+               return NT_STATUS_OK;
+
+       default:
+               return NT_STATUS_INVALID_LEVEL;
+       }
+
+       return NT_STATUS_INVALID_LEVEL;
+}