mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
r11771: - split out the setinfo blob construction in the libcli/raw code
- added a smb2_setinfo call
- added smb2_setinfo_file*() calls
(This used to be commit da0b6fb936
)
This commit is contained in:
parent
58bf4b160e
commit
2ff21db535
@ -22,13 +22,14 @@
|
||||
#include "includes.h"
|
||||
#include "libcli/raw/libcliraw.h"
|
||||
|
||||
/****************************************************************************
|
||||
Handle setfileinfo/setpathinfo trans2 backend.
|
||||
****************************************************************************/
|
||||
static BOOL smb_raw_setinfo_backend(struct smbcli_tree *tree,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
union smb_setfileinfo *parms,
|
||||
DATA_BLOB *blob)
|
||||
|
||||
/*
|
||||
Handle setfileinfo/setpathinfo passthu constructions
|
||||
*/
|
||||
BOOL smb_raw_setfileinfo_passthru(TALLOC_CTX *mem_ctx,
|
||||
enum smb_setfileinfo_level level,
|
||||
union smb_setfileinfo *parms,
|
||||
DATA_BLOB *blob)
|
||||
{
|
||||
uint_t len;
|
||||
|
||||
@ -37,6 +38,77 @@ static BOOL smb_raw_setinfo_backend(struct smbcli_tree *tree,
|
||||
if (blob->data == NULL) return False; \
|
||||
} while (0)
|
||||
|
||||
switch (level) {
|
||||
case RAW_SFILEINFO_BASIC_INFORMATION:
|
||||
NEED_BLOB(40);
|
||||
smbcli_push_nttime(blob->data, 0, parms->basic_info.in.create_time);
|
||||
smbcli_push_nttime(blob->data, 8, parms->basic_info.in.access_time);
|
||||
smbcli_push_nttime(blob->data, 16, parms->basic_info.in.write_time);
|
||||
smbcli_push_nttime(blob->data, 24, parms->basic_info.in.change_time);
|
||||
SIVAL(blob->data, 32, parms->basic_info.in.attrib);
|
||||
SIVAL(blob->data, 36, 0); /* padding */
|
||||
return True;
|
||||
|
||||
case RAW_SFILEINFO_DISPOSITION_INFORMATION:
|
||||
NEED_BLOB(4);
|
||||
SIVAL(blob->data, 0, parms->disposition_info.in.delete_on_close);
|
||||
return True;
|
||||
|
||||
case RAW_SFILEINFO_ALLOCATION_INFORMATION:
|
||||
NEED_BLOB(8);
|
||||
SBVAL(blob->data, 0, parms->allocation_info.in.alloc_size);
|
||||
return True;
|
||||
|
||||
case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
|
||||
NEED_BLOB(8);
|
||||
SBVAL(blob->data, 0, parms->end_of_file_info.in.size);
|
||||
return True;
|
||||
|
||||
case RAW_SFILEINFO_RENAME_INFORMATION:
|
||||
NEED_BLOB(12);
|
||||
SIVAL(blob->data, 0, parms->rename_information.in.overwrite);
|
||||
SIVAL(blob->data, 4, parms->rename_information.in.root_fid);
|
||||
len = smbcli_blob_append_string(NULL, mem_ctx, blob,
|
||||
parms->rename_information.in.new_name,
|
||||
STR_UNICODE|STR_TERMINATE);
|
||||
SIVAL(blob->data, 8, len - 2);
|
||||
return True;
|
||||
|
||||
case RAW_SFILEINFO_POSITION_INFORMATION:
|
||||
NEED_BLOB(8);
|
||||
SBVAL(blob->data, 0, parms->position_information.in.position);
|
||||
return True;
|
||||
|
||||
case RAW_SFILEINFO_MODE_INFORMATION:
|
||||
NEED_BLOB(4);
|
||||
SIVAL(blob->data, 0, parms->mode_information.in.mode);
|
||||
return True;
|
||||
|
||||
/* Unhandled levels */
|
||||
case RAW_SFILEINFO_1023:
|
||||
case RAW_SFILEINFO_1025:
|
||||
case RAW_SFILEINFO_1029:
|
||||
case RAW_SFILEINFO_1032:
|
||||
case RAW_SFILEINFO_1039:
|
||||
case RAW_SFILEINFO_1040:
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG(0,("Unhandled setfileinfo passthru level %d\n", level));
|
||||
return False;
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/*
|
||||
Handle setfileinfo/setpathinfo trans2 backend.
|
||||
*/
|
||||
static BOOL smb_raw_setinfo_backend(struct smbcli_tree *tree,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
union smb_setfileinfo *parms,
|
||||
DATA_BLOB *blob)
|
||||
{
|
||||
switch (parms->generic.level) {
|
||||
case RAW_SFILEINFO_GENERIC:
|
||||
case RAW_SFILEINFO_SETATTR:
|
||||
@ -62,14 +134,8 @@ static BOOL smb_raw_setinfo_backend(struct smbcli_tree *tree,
|
||||
|
||||
case RAW_SFILEINFO_BASIC_INFO:
|
||||
case RAW_SFILEINFO_BASIC_INFORMATION:
|
||||
NEED_BLOB(40);
|
||||
smbcli_push_nttime(blob->data, 0, parms->basic_info.in.create_time);
|
||||
smbcli_push_nttime(blob->data, 8, parms->basic_info.in.access_time);
|
||||
smbcli_push_nttime(blob->data, 16, parms->basic_info.in.write_time);
|
||||
smbcli_push_nttime(blob->data, 24, parms->basic_info.in.change_time);
|
||||
SIVAL(blob->data, 32, parms->basic_info.in.attrib);
|
||||
SIVAL(blob->data, 36, 0); /* padding */
|
||||
return True;
|
||||
return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_BASIC_INFORMATION,
|
||||
parms, blob);
|
||||
|
||||
case RAW_SFILEINFO_UNIX_BASIC:
|
||||
NEED_BLOB(92);
|
||||
@ -89,52 +155,45 @@ static BOOL smb_raw_setinfo_backend(struct smbcli_tree *tree,
|
||||
|
||||
case RAW_SFILEINFO_DISPOSITION_INFO:
|
||||
case RAW_SFILEINFO_DISPOSITION_INFORMATION:
|
||||
NEED_BLOB(4);
|
||||
SIVAL(blob->data, 0, parms->disposition_info.in.delete_on_close);
|
||||
return True;
|
||||
return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_DISPOSITION_INFORMATION,
|
||||
parms, blob);
|
||||
|
||||
case RAW_SFILEINFO_ALLOCATION_INFO:
|
||||
case RAW_SFILEINFO_ALLOCATION_INFORMATION:
|
||||
NEED_BLOB(8);
|
||||
SBVAL(blob->data, 0, parms->allocation_info.in.alloc_size);
|
||||
return True;
|
||||
return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_ALLOCATION_INFORMATION,
|
||||
parms, blob);
|
||||
|
||||
case RAW_SFILEINFO_END_OF_FILE_INFO:
|
||||
case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
|
||||
NEED_BLOB(8);
|
||||
SBVAL(blob->data, 0, parms->end_of_file_info.in.size);
|
||||
return True;
|
||||
return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_END_OF_FILE_INFORMATION,
|
||||
parms, blob);
|
||||
|
||||
case RAW_SFILEINFO_RENAME_INFORMATION:
|
||||
NEED_BLOB(12);
|
||||
SIVAL(blob->data, 0, parms->rename_information.in.overwrite);
|
||||
SIVAL(blob->data, 4, parms->rename_information.in.root_fid);
|
||||
len = smbcli_blob_append_string(tree->session, mem_ctx, blob,
|
||||
parms->rename_information.in.new_name,
|
||||
STR_UNICODE|STR_TERMINATE);
|
||||
SIVAL(blob->data, 8, len - 2);
|
||||
return True;
|
||||
return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_RENAME_INFORMATION,
|
||||
parms, blob);
|
||||
|
||||
case RAW_SFILEINFO_POSITION_INFORMATION:
|
||||
NEED_BLOB(8);
|
||||
SBVAL(blob->data, 0, parms->position_information.in.position);
|
||||
return True;
|
||||
return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_POSITION_INFORMATION,
|
||||
parms, blob);
|
||||
|
||||
case RAW_SFILEINFO_MODE_INFORMATION:
|
||||
NEED_BLOB(4);
|
||||
SIVAL(blob->data, 0, parms->mode_information.in.mode);
|
||||
return True;
|
||||
return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_MODE_INFORMATION,
|
||||
parms, blob);
|
||||
|
||||
/* Unhandled levels */
|
||||
|
||||
case RAW_SFILEINFO_UNIX_LINK:
|
||||
case RAW_SFILEINFO_UNIX_HLINK:
|
||||
/* Unhandled passthru levels */
|
||||
case RAW_SFILEINFO_1023:
|
||||
case RAW_SFILEINFO_1025:
|
||||
case RAW_SFILEINFO_1029:
|
||||
case RAW_SFILEINFO_1032:
|
||||
case RAW_SFILEINFO_1039:
|
||||
case RAW_SFILEINFO_1040:
|
||||
return smb_raw_setfileinfo_passthru(mem_ctx, parms->generic.level,
|
||||
parms, blob);
|
||||
|
||||
/* Unhandled levels */
|
||||
|
||||
case RAW_SFILEINFO_UNIX_LINK:
|
||||
case RAW_SFILEINFO_UNIX_HLINK:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -10,5 +10,6 @@ OBJ_FILES = \
|
||||
connect.o \
|
||||
getinfo.o \
|
||||
write.o \
|
||||
read.o
|
||||
read.o \
|
||||
setinfo.o
|
||||
REQUIRED_SUBSYSTEMS = LIBCLI_RAW LIBPACKET
|
||||
|
@ -86,6 +86,44 @@ NTSTATUS smb2_getinfo(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
map a generic info level to a SMB2 info level
|
||||
*/
|
||||
uint16_t smb2_getinfo_map_level(uint16_t level, uint8_t class)
|
||||
{
|
||||
if ((level & 0xFF) == class) {
|
||||
return level;
|
||||
} else if (level > 1000) {
|
||||
return ((level-1000)<<8) | class;
|
||||
}
|
||||
DEBUG(0,("Unable to map SMB2 info level 0x%04x of class %d\n", level, class));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
level specific getinfo call - async send
|
||||
*/
|
||||
struct smb2_request *smb2_getinfo_file_send(struct smb2_tree *tree, union smb_fileinfo *io)
|
||||
{
|
||||
struct smb2_getinfo b;
|
||||
uint16_t smb2_level = smb2_getinfo_map_level(io->generic.level, SMB2_GETINFO_FILE);
|
||||
|
||||
if (smb2_level == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(b);
|
||||
b.in.max_response_size = 0x10000;
|
||||
b.in.handle = io->generic.in.handle;
|
||||
b.in.level = smb2_level;
|
||||
|
||||
if (io->generic.level == RAW_FILEINFO_SEC_DESC) {
|
||||
b.in.flags = io->query_secdesc.secinfo_flags;
|
||||
}
|
||||
|
||||
return smb2_getinfo_send(tree, &b);
|
||||
}
|
||||
|
||||
/*
|
||||
recv a getinfo reply and parse the level info
|
||||
*/
|
||||
@ -110,36 +148,31 @@ NTSTATUS smb2_getinfo_file_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
|
||||
NTSTATUS smb2_getinfo_file(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
|
||||
union smb_fileinfo *io)
|
||||
{
|
||||
struct smb2_getinfo b;
|
||||
struct smb2_request *req;
|
||||
uint16_t smb2_level;
|
||||
|
||||
if (io->generic.level == RAW_FILEINFO_SEC_DESC) {
|
||||
smb2_level = SMB2_GETINFO_SECURITY;
|
||||
} else if ((io->generic.level & 0xFF) == SMB2_GETINFO_FILE) {
|
||||
smb2_level = io->generic.level;
|
||||
} else if (io->generic.level > 1000) {
|
||||
smb2_level = ((io->generic.level-1000)<<8) | SMB2_GETINFO_FILE;
|
||||
} else {
|
||||
/* SMB2 only does the passthru levels */
|
||||
return NT_STATUS_INVALID_LEVEL;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(b);
|
||||
b.in.max_response_size = 0x10000;
|
||||
b.in.handle = io->generic.in.handle;
|
||||
b.in.level = smb2_level;
|
||||
|
||||
if (io->generic.level == RAW_FILEINFO_SEC_DESC) {
|
||||
b.in.flags = io->query_secdesc.secinfo_flags;
|
||||
}
|
||||
|
||||
req = smb2_getinfo_send(tree, &b);
|
||||
|
||||
struct smb2_request *req = smb2_getinfo_file_send(tree, io);
|
||||
return smb2_getinfo_file_recv(req, mem_ctx, io);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
level specific getinfo call - async send
|
||||
*/
|
||||
struct smb2_request *smb2_getinfo_fs_send(struct smb2_tree *tree, union smb_fsinfo *io)
|
||||
{
|
||||
struct smb2_getinfo b;
|
||||
uint16_t smb2_level = smb2_getinfo_map_level(io->generic.level, SMB2_GETINFO_FS);
|
||||
|
||||
if (smb2_level == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(b);
|
||||
b.in.max_response_size = 0x10000;
|
||||
b.in.handle = io->generic.handle;
|
||||
b.in.level = smb2_level;
|
||||
|
||||
return smb2_getinfo_send(tree, &b);
|
||||
}
|
||||
|
||||
/*
|
||||
recv a getinfo reply and parse the level info
|
||||
*/
|
||||
@ -164,26 +197,7 @@ NTSTATUS smb2_getinfo_fs_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
|
||||
NTSTATUS smb2_getinfo_fs(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
|
||||
union smb_fsinfo *io)
|
||||
{
|
||||
struct smb2_getinfo b;
|
||||
struct smb2_request *req;
|
||||
uint16_t smb2_level;
|
||||
|
||||
if ((io->generic.level & 0xFF) == SMB2_GETINFO_FS) {
|
||||
smb2_level = io->generic.level;
|
||||
} else if (io->generic.level > 1000) {
|
||||
smb2_level = ((io->generic.level-1000)<<8) | SMB2_GETINFO_FS;
|
||||
} else {
|
||||
/* SMB2 only does the passthru levels */
|
||||
return NT_STATUS_INVALID_LEVEL;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(b);
|
||||
b.in.max_response_size = 0x10000;
|
||||
b.in.handle = io->generic.handle;
|
||||
b.in.level = smb2_level;
|
||||
|
||||
req = smb2_getinfo_send(tree, &b);
|
||||
|
||||
struct smb2_request *req = smb2_getinfo_fs_send(tree, io);
|
||||
return smb2_getinfo_fs_recv(req, mem_ctx, io);
|
||||
}
|
||||
|
||||
|
@ -390,6 +390,57 @@ NTSTATUS smb2_push_o32s32_blob(struct smb2_request_buffer *buf,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
push a uint32_t length/ uint32_t ofs/blob triple into a data blob
|
||||
the ofs points to the start of the length/offset pair, and is relative
|
||||
to the body start
|
||||
*/
|
||||
NTSTATUS smb2_push_s32o32_blob(struct smb2_request_buffer *buf,
|
||||
uint32_t ofs, DATA_BLOB blob)
|
||||
{
|
||||
NTSTATUS status;
|
||||
size_t offset;
|
||||
size_t padding_length;
|
||||
uint8_t *ptr = buf->body+ofs;
|
||||
|
||||
if (buf->dynamic == NULL) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* check if there're enough room for ofs and size */
|
||||
if (smb2_oob(buf, ptr, 8)) {
|
||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (blob.length == 0) {
|
||||
SIVAL(ptr, 0, 0);
|
||||
SIVAL(ptr, 4, 0);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
offset = buf->dynamic - buf->hdr;
|
||||
padding_length = smb2_padding_size(offset, 8);
|
||||
offset += padding_length;
|
||||
|
||||
SIVAL(ptr, 0, blob.length);
|
||||
SIVAL(ptr, 4, offset);
|
||||
|
||||
status = smb2_grow_buffer(buf, padding_length + blob.length);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
memset(buf->dynamic, 0, padding_length);
|
||||
buf->dynamic += padding_length;
|
||||
|
||||
memcpy(buf->dynamic, blob.data, blob.length);
|
||||
buf->dynamic += blob.length;
|
||||
|
||||
buf->size += blob.length + padding_length;
|
||||
buf->body_size += blob.length + padding_length;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
pull a uint16_t ofs/ uint32_t length/blob triple from a data blob
|
||||
the ptr points to the start of the offset/length pair
|
||||
|
109
source4/libcli/smb2/setinfo.c
Normal file
109
source4/libcli/smb2/setinfo.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
SMB2 client setinfo calls
|
||||
|
||||
Copyright (C) Andrew Tridgell 2005
|
||||
|
||||
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
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "libcli/raw/libcliraw.h"
|
||||
#include "libcli/smb2/smb2.h"
|
||||
#include "libcli/smb2/smb2_calls.h"
|
||||
|
||||
/*
|
||||
send a setinfo request
|
||||
*/
|
||||
struct smb2_request *smb2_setinfo_send(struct smb2_tree *tree, struct smb2_setinfo *io)
|
||||
{
|
||||
struct smb2_request *req;
|
||||
|
||||
req = smb2_request_init_tree(tree, SMB2_OP_SETINFO, 0x20, io->in.blob.length);
|
||||
if (req == NULL) return NULL;
|
||||
|
||||
SSVAL(req->out.body, 0x02, io->in.level);
|
||||
smb2_push_s32o32_blob(&req->out, 0x04, io->in.blob);
|
||||
SIVAL(req->out.body, 0x0C, io->in.flags);
|
||||
smb2_push_handle(req->out.body+0x10, &io->in.handle);
|
||||
|
||||
smb2_transport_send(req);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
recv a setinfo reply
|
||||
*/
|
||||
NTSTATUS smb2_setinfo_recv(struct smb2_request *req)
|
||||
{
|
||||
if (!smb2_request_receive(req) ||
|
||||
smb2_request_is_error(req)) {
|
||||
return smb2_request_destroy(req);
|
||||
}
|
||||
|
||||
SMB2_CHECK_PACKET_RECV(req, 0x02, False);
|
||||
|
||||
return smb2_request_destroy(req);
|
||||
}
|
||||
|
||||
/*
|
||||
sync setinfo request
|
||||
*/
|
||||
NTSTATUS smb2_setinfo(struct smb2_tree *tree, struct smb2_setinfo *io)
|
||||
{
|
||||
struct smb2_request *req = smb2_setinfo_send(tree, io);
|
||||
return smb2_setinfo_recv(req);
|
||||
}
|
||||
|
||||
/*
|
||||
level specific file setinfo call - async send
|
||||
*/
|
||||
struct smb2_request *smb2_setinfo_file_send(struct smb2_tree *tree, union smb_setfileinfo *io)
|
||||
{
|
||||
struct smb2_setinfo b;
|
||||
uint16_t smb2_level = smb2_getinfo_map_level(io->generic.level, SMB2_GETINFO_FILE);
|
||||
struct smb2_request *req;
|
||||
|
||||
if (smb2_level == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(b);
|
||||
b.in.level = smb2_level;
|
||||
b.in.handle = io->generic.file.handle;
|
||||
if (!smb_raw_setfileinfo_passthru(tree, io->generic.level, io, &b.in.blob)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (io->generic.level == RAW_SFILEINFO_SEC_DESC) {
|
||||
b.in.flags = io->set_secdesc.in.secinfo_flags;
|
||||
}
|
||||
|
||||
req = smb2_setinfo_send(tree, &b);
|
||||
data_blob_free(&b.in.blob);
|
||||
return req;
|
||||
}
|
||||
|
||||
/*
|
||||
level specific file setinfo call - sync
|
||||
*/
|
||||
NTSTATUS smb2_setinfo_file(struct smb2_tree *tree, union smb_setfileinfo *io)
|
||||
{
|
||||
struct smb2_request *req = smb2_setinfo_file_send(tree, io);
|
||||
return smb2_setinfo_recv(req);
|
||||
}
|
@ -215,6 +215,15 @@ struct smb2_getinfo {
|
||||
} out;
|
||||
};
|
||||
|
||||
struct smb2_setinfo {
|
||||
struct {
|
||||
uint16_t level;
|
||||
uint32_t flags;
|
||||
struct smb2_handle handle;
|
||||
DATA_BLOB blob;
|
||||
} in;
|
||||
};
|
||||
|
||||
struct smb2_write {
|
||||
struct {
|
||||
/* static body buffer 48 (0x30) bytes */
|
||||
|
Loading…
Reference in New Issue
Block a user