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)
/*
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,
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);
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)
{
union smb_fsinfo *fsinfo,
int default_str_flags)
{
- uint_t i;
+ unsigned int i;
DATA_BLOB guid_blob;
switch (level) {
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++) {
}
return NT_STATUS_OK;
-
+ }
default:
return NT_STATUS_INVALID_LEVEL;
}
union smb_fileinfo *st,
int default_str_flags)
{
- uint_t i;
+ unsigned int i;
size_t list_size;
switch (level) {
}
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:
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,
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;
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) {
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;
+}