📄 nttrans.c
字号:
/* Unix SMB/CIFS implementation. NT transaction handling Copyright (C) Andrew Tridgell 2003 Copyright (C) James J Myers 2003 <myersjj@samba.org> 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 "smb_server/smb_server.h"#include "ntvfs/ntvfs.h"#include "libcli/raw/libcliraw.h"#include "libcli/raw/raw_proto.h"#include "librpc/gen_ndr/ndr_security.h"#include "param/param.h"/* hold the state of a nttrans op while in progress. Needed to allow for async backend functions.*/struct nttrans_op { struct smb_nttrans *trans; NTSTATUS (*send_fn)(struct nttrans_op *); void *op_info;};/* setup a nttrans reply, given the data and params sizes */static NTSTATUS nttrans_setup_reply(struct nttrans_op *op, struct smb_nttrans *trans, uint32_t param_size, uint32_t data_size, uint8_t setup_count){ trans->out.setup_count = setup_count; if (setup_count != 0) { trans->out.setup = talloc_zero_array(op, uint8_t, setup_count*2); NT_STATUS_HAVE_NO_MEMORY(trans->out.setup); } trans->out.params = data_blob_talloc(op, NULL, param_size); if (param_size != 0) { NT_STATUS_HAVE_NO_MEMORY(trans->out.params.data); } trans->out.data = data_blob_talloc(op, NULL, data_size); if (data_size != 0) { NT_STATUS_HAVE_NO_MEMORY(trans->out.data.data); } return NT_STATUS_OK;}/* send a nttrans create reply*/static NTSTATUS nttrans_create_send(struct nttrans_op *op){ union smb_open *io = talloc_get_type(op->op_info, union smb_open); uint8_t *params; NTSTATUS status; status = nttrans_setup_reply(op, op->trans, 69, 0, 0); NT_STATUS_NOT_OK_RETURN(status); params = op->trans->out.params.data; SSVAL(params, 0, io->ntcreatex.out.oplock_level); smbsrv_push_fnum(params, 2, io->ntcreatex.out.file.ntvfs); SIVAL(params, 4, io->ntcreatex.out.create_action); SIVAL(params, 8, 0); /* ea error offset */ push_nttime(params, 12, io->ntcreatex.out.create_time); push_nttime(params, 20, io->ntcreatex.out.access_time); push_nttime(params, 28, io->ntcreatex.out.write_time); push_nttime(params, 36, io->ntcreatex.out.change_time); SIVAL(params, 44, io->ntcreatex.out.attrib); SBVAL(params, 48, io->ntcreatex.out.alloc_size); SBVAL(params, 56, io->ntcreatex.out.size); SSVAL(params, 64, io->ntcreatex.out.file_type); SSVAL(params, 66, io->ntcreatex.out.ipc_state); SCVAL(params, 68, io->ntcreatex.out.is_directory); return NT_STATUS_OK;}/* parse NTTRANS_CREATE request */static NTSTATUS nttrans_create(struct smbsrv_request *req, struct nttrans_op *op){ struct smb_nttrans *trans = op->trans; union smb_open *io; uint16_t fname_len; uint32_t sd_length, ea_length; NTSTATUS status; uint8_t *params; enum ndr_err_code ndr_err; if (trans->in.params.length < 54) { return NT_STATUS_INVALID_PARAMETER; } /* parse the request */ io = talloc(op, union smb_open); NT_STATUS_HAVE_NO_MEMORY(io); io->ntcreatex.level = RAW_OPEN_NTTRANS_CREATE; params = trans->in.params.data; io->ntcreatex.in.flags = IVAL(params, 0); io->ntcreatex.in.root_fid = IVAL(params, 4); io->ntcreatex.in.access_mask = IVAL(params, 8); io->ntcreatex.in.alloc_size = BVAL(params, 12); io->ntcreatex.in.file_attr = IVAL(params, 20); io->ntcreatex.in.share_access = IVAL(params, 24); io->ntcreatex.in.open_disposition = IVAL(params, 28); io->ntcreatex.in.create_options = IVAL(params, 32); sd_length = IVAL(params, 36); ea_length = IVAL(params, 40); fname_len = IVAL(params, 44); io->ntcreatex.in.impersonation = IVAL(params, 48); io->ntcreatex.in.security_flags = CVAL(params, 52); io->ntcreatex.in.sec_desc = NULL; io->ntcreatex.in.ea_list = NULL; req_pull_string(&req->in.bufinfo, &io->ntcreatex.in.fname, params + 53, MIN(fname_len+1, trans->in.params.length - 53), STR_NO_RANGE_CHECK | STR_TERMINATE); if (!io->ntcreatex.in.fname) { return NT_STATUS_INVALID_PARAMETER; } if (sd_length > trans->in.data.length || ea_length > trans->in.data.length || (sd_length+ea_length) > trans->in.data.length) { return NT_STATUS_INVALID_PARAMETER; } /* this call has an optional security descriptor */ if (sd_length != 0) { DATA_BLOB blob; blob.data = trans->in.data.data; blob.length = sd_length; io->ntcreatex.in.sec_desc = talloc(io, struct security_descriptor); if (io->ntcreatex.in.sec_desc == NULL) { return NT_STATUS_NO_MEMORY; } ndr_err = ndr_pull_struct_blob(&blob, io, NULL, io->ntcreatex.in.sec_desc, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); } } /* and an optional ea_list */ if (ea_length > 4) { DATA_BLOB blob; blob.data = trans->in.data.data + sd_length; blob.length = ea_length; io->ntcreatex.in.ea_list = talloc(io, struct smb_ea_list); if (io->ntcreatex.in.ea_list == NULL) { return NT_STATUS_NO_MEMORY; } status = ea_pull_list_chained(&blob, io, &io->ntcreatex.in.ea_list->num_eas, &io->ntcreatex.in.ea_list->eas); if (!NT_STATUS_IS_OK(status)) { return status; } } op->send_fn = nttrans_create_send; op->op_info = io; return ntvfs_open(req->ntvfs, io);}/* send NTTRANS_QUERY_SEC_DESC reply */static NTSTATUS nttrans_query_sec_desc_send(struct nttrans_op *op){ union smb_fileinfo *io = talloc_get_type(op->op_info, union smb_fileinfo); uint8_t *params; NTSTATUS status; enum ndr_err_code ndr_err; status = nttrans_setup_reply(op, op->trans, 4, 0, 0); NT_STATUS_NOT_OK_RETURN(status); params = op->trans->out.params.data; ndr_err = ndr_push_struct_blob(&op->trans->out.data, op, NULL, io->query_secdesc.out.sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); } SIVAL(params, 0, op->trans->out.data.length); return NT_STATUS_OK;}/* parse NTTRANS_QUERY_SEC_DESC request */static NTSTATUS nttrans_query_sec_desc(struct smbsrv_request *req, struct nttrans_op *op){ struct smb_nttrans *trans = op->trans; union smb_fileinfo *io; if (trans->in.params.length < 8) { return NT_STATUS_INVALID_PARAMETER; } /* parse the request */ io = talloc(op, union smb_fileinfo); NT_STATUS_HAVE_NO_MEMORY(io); io->query_secdesc.level = RAW_FILEINFO_SEC_DESC; io->query_secdesc.in.file.ntvfs = smbsrv_pull_fnum(req, trans->in.params.data, 0); io->query_secdesc.in.secinfo_flags = IVAL(trans->in.params.data, 4); op->op_info = io; op->send_fn = nttrans_query_sec_desc_send; SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(io->query_secdesc.in.file.ntvfs); return ntvfs_qfileinfo(req->ntvfs, io);}/* parse NTTRANS_SET_SEC_DESC request */static NTSTATUS nttrans_set_sec_desc(struct smbsrv_request *req, struct nttrans_op *op){ struct smb_nttrans *trans = op->trans; union smb_setfileinfo *io; enum ndr_err_code ndr_err; if (trans->in.params.length < 8) { return NT_STATUS_INVALID_PARAMETER; } /* parse the request */ io = talloc(req, union smb_setfileinfo); NT_STATUS_HAVE_NO_MEMORY(io); io->set_secdesc.level = RAW_SFILEINFO_SEC_DESC; io->set_secdesc.in.file.ntvfs = smbsrv_pull_fnum(req, trans->in.params.data, 0); io->set_secdesc.in.secinfo_flags = IVAL(trans->in.params.data, 4); io->set_secdesc.in.sd = talloc(io, struct security_descriptor); NT_STATUS_HAVE_NO_MEMORY(io->set_secdesc.in.sd); ndr_err = ndr_pull_struct_blob(&trans->in.data, req, NULL, io->set_secdesc.in.sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); } SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(io->set_secdesc.in.file.ntvfs); return ntvfs_setfileinfo(req->ntvfs, io);}/* parse NTTRANS_RENAME request */static NTSTATUS nttrans_rename(struct smbsrv_request *req, struct nttrans_op *op){ struct smb_nttrans *trans = op->trans; union smb_rename *io; if (trans->in.params.length < 5) { return NT_STATUS_INVALID_PARAMETER; } /* parse the request */ io = talloc(req, union smb_rename); NT_STATUS_HAVE_NO_MEMORY(io); io->nttrans.level = RAW_RENAME_NTTRANS; io->nttrans.in.file.ntvfs = smbsrv_pull_fnum(req, trans->in.params.data, 0); io->nttrans.in.flags = SVAL(trans->in.params.data, 2); smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 4, &io->nttrans.in.new_name, STR_TERMINATE); if (!io->nttrans.in.new_name) { return NT_STATUS_INVALID_PARAMETER; } SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(io->nttrans.in.file.ntvfs); return ntvfs_rename(req->ntvfs, io);}/* parse NTTRANS_IOCTL send */static NTSTATUS nttrans_ioctl_send(struct nttrans_op *op){ union smb_ioctl *info = talloc_get_type(op->op_info, union smb_ioctl); NTSTATUS status; /* * we pass 0 as data_count here, * because we reuse the DATA_BLOB from the smb_ioctl * struct */ status = nttrans_setup_reply(op, op->trans, 0, 0, 1); NT_STATUS_NOT_OK_RETURN(status); op->trans->out.setup[0] = 0; op->trans->out.data = info->ntioctl.out.blob; return NT_STATUS_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -