📄 reply.c
字号:
/* Unix SMB/CIFS implementation. Main SMB reply routines Copyright (C) Andrew Tridgell 1992-2003 Copyright (C) James J Myers 2003 <myersjj@samba.org> Copyright (C) Stefan Metzmacher 2006 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 most of the reply_ calls that the server makes to handle specific SMB commands*/#include "includes.h"#include "smb_server/smb_server.h"#include "ntvfs/ntvfs.h"#include "librpc/gen_ndr/ndr_nbt.h"/**************************************************************************** Reply to a simple request (async send)****************************************************************************/static void reply_simple_send(struct ntvfs_request *ntvfs){ struct smbsrv_request *req; SMBSRV_CHECK_ASYNC_STATUS_SIMPLE; smbsrv_setup_reply(req, 0, 0); smbsrv_send_reply(req);}/**************************************************************************** Reply to a tcon.****************************************************************************/void smbsrv_reply_tcon(struct smbsrv_request *req){ union smb_tcon con; NTSTATUS status; uint8_t *p; /* parse request */ SMBSRV_CHECK_WCT(req, 0); con.tcon.level = RAW_TCON_TCON; p = req->in.data; p += req_pull_ascii4(&req->in.bufinfo, &con.tcon.in.service, p, STR_TERMINATE); p += req_pull_ascii4(&req->in.bufinfo, &con.tcon.in.password, p, STR_TERMINATE); p += req_pull_ascii4(&req->in.bufinfo, &con.tcon.in.dev, p, STR_TERMINATE); if (!con.tcon.in.service || !con.tcon.in.password || !con.tcon.in.dev) { smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER); return; } /* call backend */ status = smbsrv_tcon_backend(req, &con); if (!NT_STATUS_IS_OK(status)) { smbsrv_send_error(req, status); return; } /* construct reply */ smbsrv_setup_reply(req, 2, 0); SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit); SSVAL(req->out.vwv, VWV(1), con.tcon.out.tid); SSVAL(req->out.hdr, HDR_TID, req->tcon->tid); smbsrv_send_reply(req);}/**************************************************************************** Reply to a tcon and X.****************************************************************************/void smbsrv_reply_tcon_and_X(struct smbsrv_request *req){ NTSTATUS status; union smb_tcon con; uint8_t *p; uint16_t passlen; con.tconx.level = RAW_TCON_TCONX; /* parse request */ SMBSRV_CHECK_WCT(req, 4); con.tconx.in.flags = SVAL(req->in.vwv, VWV(2)); passlen = SVAL(req->in.vwv, VWV(3)); p = req->in.data; if (!req_pull_blob(&req->in.bufinfo, p, passlen, &con.tconx.in.password)) { smbsrv_send_error(req, NT_STATUS_ILL_FORMED_PASSWORD); return; } p += passlen; p += req_pull_string(&req->in.bufinfo, &con.tconx.in.path, p, -1, STR_TERMINATE); p += req_pull_string(&req->in.bufinfo, &con.tconx.in.device, p, -1, STR_ASCII); if (!con.tconx.in.path || !con.tconx.in.device) { smbsrv_send_error(req, NT_STATUS_BAD_DEVICE_TYPE); return; } /* call backend */ status = smbsrv_tcon_backend(req, &con); if (!NT_STATUS_IS_OK(status)) { smbsrv_send_error(req, status); return; } /* construct reply - two variants */ if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) { smbsrv_setup_reply(req, 2, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII); } else { smbsrv_setup_reply(req, 3, 0); SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); SSVAL(req->out.vwv, VWV(2), con.tconx.out.options); req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII); req_push_str(req, NULL, con.tconx.out.fs_type, -1, STR_TERMINATE); } /* set the incoming and outgoing tid to the just created one */ SSVAL(req->in.hdr, HDR_TID, con.tconx.out.tid); SSVAL(req->out.hdr,HDR_TID, con.tconx.out.tid); smbsrv_chain_reply(req);}/**************************************************************************** Reply to an unknown request****************************************************************************/void smbsrv_reply_unknown(struct smbsrv_request *req){ int type; type = CVAL(req->in.hdr, HDR_COM); DEBUG(0,("unknown command type %d (0x%X)\n", type, type)); smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRunknownsmb));}/**************************************************************************** Reply to an ioctl (async reply)****************************************************************************/static void reply_ioctl_send(struct ntvfs_request *ntvfs){ struct smbsrv_request *req; union smb_ioctl *io; SMBSRV_CHECK_ASYNC_STATUS(io, union smb_ioctl); /* the +1 is for nicer alignment */ smbsrv_setup_reply(req, 8, io->ioctl.out.blob.length+1); SSVAL(req->out.vwv, VWV(1), io->ioctl.out.blob.length); SSVAL(req->out.vwv, VWV(5), io->ioctl.out.blob.length); SSVAL(req->out.vwv, VWV(6), PTR_DIFF(req->out.data, req->out.hdr) + 1); memcpy(req->out.data+1, io->ioctl.out.blob.data, io->ioctl.out.blob.length); smbsrv_send_reply(req);}/**************************************************************************** Reply to an ioctl.****************************************************************************/void smbsrv_reply_ioctl(struct smbsrv_request *req){ union smb_ioctl *io; /* parse request */ SMBSRV_CHECK_WCT(req, 3); SMBSRV_TALLOC_IO_PTR(io, union smb_ioctl); SMBSRV_SETUP_NTVFS_REQUEST(reply_ioctl_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->ioctl.level = RAW_IOCTL_IOCTL; io->ioctl.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0)); io->ioctl.in.request = IVAL(req->in.vwv, VWV(1)); SMBSRV_CHECK_FILE_HANDLE_ERROR(io->ioctl.in.file.ntvfs, NT_STATUS_DOS(ERRSRV, ERRerror)); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req->ntvfs, io));}/**************************************************************************** Reply to a chkpth.****************************************************************************/void smbsrv_reply_chkpth(struct smbsrv_request *req){ union smb_chkpath *io; SMBSRV_TALLOC_IO_PTR(io, union smb_chkpath); SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); req_pull_ascii4(&req->in.bufinfo, &io->chkpath.in.path, req->in.data, STR_TERMINATE); SMBSRV_CALL_NTVFS_BACKEND(ntvfs_chkpath(req->ntvfs, io));}/**************************************************************************** Reply to a getatr (async reply)****************************************************************************/static void reply_getatr_send(struct ntvfs_request *ntvfs){ struct smbsrv_request *req; union smb_fileinfo *st; SMBSRV_CHECK_ASYNC_STATUS(st, union smb_fileinfo); /* construct reply */ smbsrv_setup_reply(req, 10, 0); SSVAL(req->out.vwv, VWV(0), st->getattr.out.attrib); srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(1), st->getattr.out.write_time); SIVAL(req->out.vwv, VWV(3), st->getattr.out.size); SMBSRV_VWV_RESERVED(5, 5); smbsrv_send_reply(req);}/**************************************************************************** Reply to a getatr.****************************************************************************/void smbsrv_reply_getatr(struct smbsrv_request *req){ union smb_fileinfo *st; SMBSRV_TALLOC_IO_PTR(st, union smb_fileinfo); SMBSRV_SETUP_NTVFS_REQUEST(reply_getatr_send, NTVFS_ASYNC_STATE_MAY_ASYNC); st->getattr.level = RAW_FILEINFO_GETATTR; /* parse request */ req_pull_ascii4(&req->in.bufinfo, &st->getattr.in.file.path, req->in.data, STR_TERMINATE); if (!st->getattr.in.file.path) { smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND); return; } SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qpathinfo(req->ntvfs, st));}/**************************************************************************** Reply to a setatr.****************************************************************************/void smbsrv_reply_setatr(struct smbsrv_request *req){ union smb_setfileinfo *st; /* parse request */ SMBSRV_CHECK_WCT(req, 8); SMBSRV_TALLOC_IO_PTR(st, union smb_setfileinfo); SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC); st->setattr.level = RAW_SFILEINFO_SETATTR; st->setattr.in.attrib = SVAL(req->in.vwv, VWV(0)); st->setattr.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1)); req_pull_ascii4(&req->in.bufinfo, &st->setattr.in.file.path, req->in.data, STR_TERMINATE); if (!st->setattr.in.file.path) { smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND); return; } SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setpathinfo(req->ntvfs, st));}/**************************************************************************** Reply to a dskattr (async reply)****************************************************************************/static void reply_dskattr_send(struct ntvfs_request *ntvfs){ struct smbsrv_request *req; union smb_fsinfo *fs; SMBSRV_CHECK_ASYNC_STATUS(fs, union smb_fsinfo); /* construct reply */ smbsrv_setup_reply(req, 5, 0); SSVAL(req->out.vwv, VWV(0), fs->dskattr.out.units_total); SSVAL(req->out.vwv, VWV(1), fs->dskattr.out.blocks_per_unit); SSVAL(req->out.vwv, VWV(2), fs->dskattr.out.block_size); SSVAL(req->out.vwv, VWV(3), fs->dskattr.out.units_free); SMBSRV_VWV_RESERVED(4, 1); smbsrv_send_reply(req);}/**************************************************************************** Reply to a dskattr.****************************************************************************/void smbsrv_reply_dskattr(struct smbsrv_request *req){ union smb_fsinfo *fs; SMBSRV_TALLOC_IO_PTR(fs, union smb_fsinfo); SMBSRV_SETUP_NTVFS_REQUEST(reply_dskattr_send, NTVFS_ASYNC_STATE_MAY_ASYNC); fs->dskattr.level = RAW_QFS_DSKATTR; SMBSRV_CALL_NTVFS_BACKEND(ntvfs_fsinfo(req->ntvfs, fs));}/**************************************************************************** Reply to an open (async reply)****************************************************************************/static void reply_open_send(struct ntvfs_request *ntvfs){ struct smbsrv_request *req; union smb_open *oi; SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open); /* construct reply */ smbsrv_setup_reply(req, 7, 0); smbsrv_push_fnum(req->out.vwv, VWV(0), oi->openold.out.file.ntvfs); SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib); srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time); SIVAL(req->out.vwv, VWV(4), oi->openold.out.size); SSVAL(req->out.vwv, VWV(6), oi->openold.out.rmode); smbsrv_send_reply(req);}/**************************************************************************** Reply to an open.****************************************************************************/void smbsrv_reply_open(struct smbsrv_request *req){ union smb_open *oi; /* parse request */ SMBSRV_CHECK_WCT(req, 2); SMBSRV_TALLOC_IO_PTR(oi, union smb_open); SMBSRV_SETUP_NTVFS_REQUEST(reply_open_send, NTVFS_ASYNC_STATE_MAY_ASYNC); oi->openold.level = RAW_OPEN_OPEN; oi->openold.in.open_mode = SVAL(req->in.vwv, VWV(0)); oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1)); req_pull_ascii4(&req->in.bufinfo, &oi->openold.in.fname, req->in.data, STR_TERMINATE); if (!oi->openold.in.fname) { smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND); return; } SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));}/**************************************************************************** Reply to an open and X (async reply)****************************************************************************/static void reply_open_and_X_send(struct ntvfs_request *ntvfs){ struct smbsrv_request *req; union smb_open *oi; SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open); /* build the reply */ if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) { smbsrv_setup_reply(req, 19, 0); } else { smbsrv_setup_reply(req, 15, 0); } SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); SSVAL(req->out.vwv, VWV(1), 0); smbsrv_push_fnum(req->out.vwv, VWV(2), oi->openx.out.file.ntvfs); SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib); srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time); SIVAL(req->out.vwv, VWV(6), oi->openx.out.size); SSVAL(req->out.vwv, VWV(8), oi->openx.out.access); SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -