⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trans2.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    Unix SMB/CIFS implementation.   transaction2 handling   Copyright (C) Andrew Tridgell 2003   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 3 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, see <http://www.gnu.org/licenses/>.*//*   This file handles the parsing of transact2 requests*/#include "includes.h"#include "lib/util/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 TRANS2_CHECK_ASYNC_STATUS_SIMPLE do { \	if (!NT_STATUS_IS_OK(req->ntvfs->async_states->status)) { \		trans2_setup_reply(trans, 0, 0, 0);\		return req->ntvfs->async_states->status; \	} \} while (0)#define TRANS2_CHECK_ASYNC_STATUS(ptr, type) do { \	TRANS2_CHECK_ASYNC_STATUS_SIMPLE; \	ptr = talloc_get_type(op->op_info, type); \} while (0)#define TRANS2_CHECK(cmd) do { \	NTSTATUS _status; \	_status = cmd; \	NT_STATUS_NOT_OK_RETURN(_status); \} while (0)/*  hold the state of a nttrans op while in progress. Needed to allow for async backend  functions.*/struct trans_op {	struct smbsrv_request *req;	struct smb_trans2 *trans;	uint8_t command;	NTSTATUS (*send_fn)(struct trans_op *);	void *op_info;};#define CHECK_MIN_BLOB_SIZE(blob, size) do { \	if ((blob)->length < (size)) { \		return NT_STATUS_INFO_LENGTH_MISMATCH; \	}} while (0)/* setup a trans2 reply, given the data and params sizes */static NTSTATUS trans2_setup_reply(struct smb_trans2 *trans,				   uint16_t param_size, uint16_t data_size,				   uint16_t setup_count){	trans->out.setup_count = setup_count;	if (setup_count > 0) {		trans->out.setup = talloc_zero_array(trans, uint16_t, setup_count);		NT_STATUS_HAVE_NO_MEMORY(trans->out.setup);	}	trans->out.params = data_blob_talloc(trans, NULL, param_size);	if (param_size > 0) NT_STATUS_HAVE_NO_MEMORY(trans->out.params.data);	trans->out.data = data_blob_talloc(trans, NULL, data_size);	if (data_size > 0) NT_STATUS_HAVE_NO_MEMORY(trans->out.data.data);	return NT_STATUS_OK;}static NTSTATUS trans2_push_fsinfo(struct smbsrv_connection *smb_conn,				   TALLOC_CTX *mem_ctx,				   DATA_BLOB *blob,				   union smb_fsinfo *fsinfo,				   int default_str_flags){	enum smb_fsinfo_level passthru_level;	switch (fsinfo->generic.level) {	case RAW_QFS_ALLOCATION:		TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 18));		SIVAL(blob->data,  0, fsinfo->allocation.out.fs_id);		SIVAL(blob->data,  4, fsinfo->allocation.out.sectors_per_unit);		SIVAL(blob->data,  8, fsinfo->allocation.out.total_alloc_units);		SIVAL(blob->data, 12, fsinfo->allocation.out.avail_alloc_units);		SSVAL(blob->data, 16, fsinfo->allocation.out.bytes_per_sector);		return NT_STATUS_OK;	case RAW_QFS_VOLUME:		TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 5));		SIVAL(blob->data,       0, fsinfo->volume.out.serial_number);		/* w2k3 implements this incorrectly for unicode - it		 * leaves the last byte off the string */		TRANS2_CHECK(smbsrv_blob_append_string(mem_ctx, blob,						       fsinfo->volume.out.volume_name.s,						       4, default_str_flags,						       STR_LEN8BIT|STR_NOALIGN));		return NT_STATUS_OK;	case RAW_QFS_VOLUME_INFO:		passthru_level = RAW_QFS_VOLUME_INFORMATION;		break;	case RAW_QFS_SIZE_INFO:		passthru_level = RAW_QFS_SIZE_INFORMATION;		break;	case RAW_QFS_DEVICE_INFO:		passthru_level = RAW_QFS_DEVICE_INFORMATION;		break;	case RAW_QFS_ATTRIBUTE_INFO:		passthru_level = RAW_QFS_ATTRIBUTE_INFORMATION;		break;	default:		passthru_level = fsinfo->generic.level;		break;	}	return smbsrv_push_passthru_fsinfo(mem_ctx, blob,					   passthru_level, fsinfo,					   default_str_flags);}/*  trans2 qfsinfo implementation send*/static NTSTATUS trans2_qfsinfo_send(struct trans_op *op){	struct smbsrv_request *req = op->req;	struct smb_trans2 *trans = op->trans;	union smb_fsinfo *fsinfo;	TRANS2_CHECK_ASYNC_STATUS(fsinfo, union smb_fsinfo);	TRANS2_CHECK(trans2_setup_reply(trans, 0, 0, 0));	TRANS2_CHECK(trans2_push_fsinfo(req->smb_conn, trans,					&trans->out.data, fsinfo,					SMBSRV_REQ_DEFAULT_STR_FLAGS(req)));	return NT_STATUS_OK;}/*  trans2 qfsinfo implementation*/static NTSTATUS trans2_qfsinfo(struct smbsrv_request *req, struct trans_op *op){	struct smb_trans2 *trans = op->trans;	union smb_fsinfo *fsinfo;	uint16_t level;	/* make sure we got enough parameters */	if (trans->in.params.length != 2) {		return NT_STATUS_FOOBAR;	}	fsinfo = talloc(op, union smb_fsinfo);	NT_STATUS_HAVE_NO_MEMORY(fsinfo);	level = SVAL(trans->in.params.data, 0);	/* work out the backend level - we make it 1-1 in the header */	fsinfo->generic.level = (enum smb_fsinfo_level)level;	if (fsinfo->generic.level >= RAW_QFS_GENERIC) {		return NT_STATUS_INVALID_LEVEL;	}	op->op_info = fsinfo;	op->send_fn = trans2_qfsinfo_send;	return ntvfs_fsinfo(req->ntvfs, fsinfo);}/*  trans2 open implementation send*/static NTSTATUS trans2_open_send(struct trans_op *op){	struct smbsrv_request *req = op->req;	struct smb_trans2 *trans = op->trans;	union smb_open *io;	TRANS2_CHECK_ASYNC_STATUS(io, union smb_open);	TRANS2_CHECK(trans2_setup_reply(trans, 30, 0, 0));	smbsrv_push_fnum(trans->out.params.data, VWV(0), io->t2open.out.file.ntvfs);	SSVAL(trans->out.params.data, VWV(1), io->t2open.out.attrib);	srv_push_dos_date3(req->smb_conn, trans->out.params.data, 			   VWV(2), io->t2open.out.write_time);	SIVAL(trans->out.params.data, VWV(4), io->t2open.out.size);	SSVAL(trans->out.params.data, VWV(6), io->t2open.out.access);	SSVAL(trans->out.params.data, VWV(7), io->t2open.out.ftype);	SSVAL(trans->out.params.data, VWV(8), io->t2open.out.devstate);	SSVAL(trans->out.params.data, VWV(9), io->t2open.out.action);	SIVAL(trans->out.params.data, VWV(10), 0); /* reserved */	SSVAL(trans->out.params.data, VWV(12), 0); /* EaErrorOffset */	SIVAL(trans->out.params.data, VWV(13), 0); /* EaLength */	return NT_STATUS_OK;}/*  trans2 open implementation*/static NTSTATUS trans2_open(struct smbsrv_request *req, struct trans_op *op){	struct smb_trans2 *trans = op->trans;	union smb_open *io;	/* make sure we got enough parameters */	if (trans->in.params.length < 29) {		return NT_STATUS_FOOBAR;	}	io = talloc(op, union smb_open);	NT_STATUS_HAVE_NO_MEMORY(io);	io->t2open.level           = RAW_OPEN_T2OPEN;	io->t2open.in.flags        = SVAL(trans->in.params.data, VWV(0));	io->t2open.in.open_mode    = SVAL(trans->in.params.data, VWV(1));	io->t2open.in.search_attrs = SVAL(trans->in.params.data, VWV(2));	io->t2open.in.file_attrs   = SVAL(trans->in.params.data, VWV(3));	io->t2open.in.write_time   = srv_pull_dos_date(req->smb_conn, 						    trans->in.params.data + VWV(4));	io->t2open.in.open_func    = SVAL(trans->in.params.data, VWV(6));	io->t2open.in.size         = IVAL(trans->in.params.data, VWV(7));	io->t2open.in.timeout      = IVAL(trans->in.params.data, VWV(9));	io->t2open.in.num_eas      = 0;	io->t2open.in.eas          = NULL;	smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 28, &io->t2open.in.fname, 0);	if (io->t2open.in.fname == NULL) {		return NT_STATUS_FOOBAR;	}	TRANS2_CHECK(ea_pull_list(&trans->in.data, io, &io->t2open.in.num_eas, &io->t2open.in.eas));	op->op_info = io;	op->send_fn = trans2_open_send;	return ntvfs_open(req->ntvfs, io);}/*  trans2 simple send*/static NTSTATUS trans2_simple_send(struct trans_op *op){	struct smbsrv_request *req = op->req;	struct smb_trans2 *trans = op->trans;	TRANS2_CHECK_ASYNC_STATUS_SIMPLE;	TRANS2_CHECK(trans2_setup_reply(trans, 2, 0, 0));	SSVAL(trans->out.params.data, VWV(0), 0);	return NT_STATUS_OK;}/*  trans2 mkdir implementation*/static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct trans_op *op){	struct smb_trans2 *trans = op->trans;	union smb_mkdir *io;	/* make sure we got enough parameters */	if (trans->in.params.length < 5) {		return NT_STATUS_FOOBAR;	}	io = talloc(op, union smb_mkdir);	NT_STATUS_HAVE_NO_MEMORY(io);	io->t2mkdir.level = RAW_MKDIR_T2MKDIR;	smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 4, &io->t2mkdir.in.path, 0);	if (io->t2mkdir.in.path == NULL) {		return NT_STATUS_FOOBAR;	}	TRANS2_CHECK(ea_pull_list(&trans->in.data, io, 				  &io->t2mkdir.in.num_eas, 				  &io->t2mkdir.in.eas));	op->op_info = io;	op->send_fn = trans2_simple_send;	return ntvfs_mkdir(req->ntvfs, io);}static NTSTATUS trans2_push_fileinfo(struct smbsrv_connection *smb_conn,				     TALLOC_CTX *mem_ctx,				     DATA_BLOB *blob,				     union smb_fileinfo *st,				     int default_str_flags){	uint32_t list_size;	enum smb_fileinfo_level passthru_level;	switch (st->generic.level) {	case RAW_FILEINFO_GENERIC:	case RAW_FILEINFO_GETATTR:	case RAW_FILEINFO_GETATTRE:	case RAW_FILEINFO_SEC_DESC:	case RAW_FILEINFO_SMB2_ALL_EAS:	case RAW_FILEINFO_SMB2_ALL_INFORMATION:		/* handled elsewhere */		return NT_STATUS_INVALID_LEVEL;	case RAW_FILEINFO_UNIX_BASIC:	case RAW_FILEINFO_UNIX_LINK:		/* not implemented yet */		return NT_STATUS_INVALID_LEVEL;	case RAW_FILEINFO_STANDARD:		TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 22));		srv_push_dos_date2(smb_conn, blob->data, 0, st->standard.out.create_time);		srv_push_dos_date2(smb_conn, blob->data, 4, st->standard.out.access_time);		srv_push_dos_date2(smb_conn, blob->data, 8, st->standard.out.write_time);		SIVAL(blob->data,        12, st->standard.out.size);		SIVAL(blob->data,        16, st->standard.out.alloc_size);		SSVAL(blob->data,        20, st->standard.out.attrib);		return NT_STATUS_OK;	case RAW_FILEINFO_EA_SIZE:		TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 26));		srv_push_dos_date2(smb_conn, blob->data, 0, st->ea_size.out.create_time);		srv_push_dos_date2(smb_conn, blob->data, 4, st->ea_size.out.access_time);		srv_push_dos_date2(smb_conn, blob->data, 8, st->ea_size.out.write_time);		SIVAL(blob->data,        12, st->ea_size.out.size);		SIVAL(blob->data,        16, st->ea_size.out.alloc_size);		SSVAL(blob->data,        20, st->ea_size.out.attrib);		SIVAL(blob->data,        22, st->ea_size.out.ea_size);		return NT_STATUS_OK;	case RAW_FILEINFO_EA_LIST:		list_size = ea_list_size(st->ea_list.out.num_eas,					 st->ea_list.out.eas);		TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size));		ea_put_list(blob->data, 			    st->ea_list.out.num_eas, st->ea_list.out.eas);		return NT_STATUS_OK;	case RAW_FILEINFO_ALL_EAS:		list_size = ea_list_size(st->all_eas.out.num_eas,						  st->all_eas.out.eas);		TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size));		ea_put_list(blob->data, 			    st->all_eas.out.num_eas, st->all_eas.out.eas);		return NT_STATUS_OK;	case RAW_FILEINFO_IS_NAME_VALID:		return NT_STATUS_OK;	case RAW_FILEINFO_BASIC_INFO:		passthru_level = RAW_FILEINFO_BASIC_INFORMATION;		break;	case RAW_FILEINFO_STANDARD_INFO:		passthru_level = RAW_FILEINFO_STANDARD_INFORMATION;		break;	case RAW_FILEINFO_EA_INFO:		passthru_level = RAW_FILEINFO_EA_INFORMATION;		break;	case RAW_FILEINFO_COMPRESSION_INFO:		passthru_level = RAW_FILEINFO_COMPRESSION_INFORMATION;		break;	case RAW_FILEINFO_ALL_INFO:		passthru_level = RAW_FILEINFO_ALL_INFORMATION;		break;	case RAW_FILEINFO_NAME_INFO:		passthru_level = RAW_FILEINFO_NAME_INFORMATION;		break;	case RAW_FILEINFO_ALT_NAME_INFO:		passthru_level = RAW_FILEINFO_ALT_NAME_INFORMATION;		break;	case RAW_FILEINFO_STREAM_INFO:		passthru_level = RAW_FILEINFO_STREAM_INFORMATION;		break;	default:		passthru_level = st->generic.level;		break;	}	return smbsrv_push_passthru_fileinfo(mem_ctx, blob,					     passthru_level, st,					     default_str_flags);}/*  fill in the reply from a qpathinfo or qfileinfo call*/static NTSTATUS trans2_fileinfo_send(struct trans_op *op){	struct smbsrv_request *req = op->req;	struct smb_trans2 *trans = op->trans;	union smb_fileinfo *st;	TRANS2_CHECK_ASYNC_STATUS(st, union smb_fileinfo);	TRANS2_CHECK(trans2_setup_reply(trans, 2, 0, 0));	SSVAL(trans->out.params.data, 0, 0);	TRANS2_CHECK(trans2_push_fileinfo(req->smb_conn, trans,					  &trans->out.data, st,					  SMBSRV_REQ_DEFAULT_STR_FLAGS(req)));	return NT_STATUS_OK;}/*  trans2 qpathinfo implementation*/static NTSTATUS trans2_qpathinfo(struct smbsrv_request *req, struct trans_op *op){	struct smb_trans2 *trans = op->trans;	union smb_fileinfo *st;	uint16_t level;	/* make sure we got enough parameters */	if (trans->in.params.length < 2) {		return NT_STATUS_FOOBAR;	}	st = talloc(op, union smb_fileinfo);	NT_STATUS_HAVE_NO_MEMORY(st);	level = SVAL(trans->in.params.data, 0);	smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 6, &st->generic.in.file.path, 0);	if (st->generic.in.file.path == NULL) {		return NT_STATUS_FOOBAR;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -