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

📄 request.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.      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 implements functions for manipulating the 'struct smbsrv_request' structure in smbd*/#include "includes.h"#include "smb_server/smb_server.h"#include "smb_server/service_smb_proto.h"#include "smbd/service_stream.h"#include "lib/stream/packet.h"#include "ntvfs/ntvfs.h"#include "param/param.h"/* we over allocate the data buffer to prevent too many realloc calls */#define REQ_OVER_ALLOCATION 0/* setup the bufinfo used for strings and range checking */void smbsrv_setup_bufinfo(struct smbsrv_request *req){	req->in.bufinfo.mem_ctx    = req;	req->in.bufinfo.flags      = 0;	if (req->flags2 & FLAGS2_UNICODE_STRINGS) {		req->in.bufinfo.flags |= BUFINFO_FLAG_UNICODE;	}	req->in.bufinfo.align_base = req->in.buffer;	req->in.bufinfo.data       = req->in.data;	req->in.bufinfo.data_size  = req->in.data_size;}static int smbsrv_request_destructor(struct smbsrv_request *req){	DLIST_REMOVE(req->smb_conn->requests, req);	return 0;}/****************************************************************************construct a basic request packet, mostly used to construct async packetssuch as change notify and oplock break requests****************************************************************************/struct smbsrv_request *smbsrv_init_request(struct smbsrv_connection *smb_conn){	struct smbsrv_request *req;	req = talloc_zero(smb_conn, struct smbsrv_request);	if (!req) {		return NULL;	}	/* setup the request context */	req->smb_conn = smb_conn;	talloc_set_destructor(req, smbsrv_request_destructor);	return req;}/*  setup a chained reply in req->out with the given word count and initial data buffer size. */static void req_setup_chain_reply(struct smbsrv_request *req, uint_t wct, uint_t buflen){	uint32_t chain_base_size = req->out.size;	/* we need room for the wct value, the words, the buffer length and the buffer */	req->out.size += 1 + VWV(wct) + 2 + buflen;	/* over allocate by a small amount */	req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 	req->out.buffer = talloc_realloc(req, req->out.buffer, 					 uint8_t, req->out.allocated);	if (!req->out.buffer) {		smbsrv_terminate_connection(req->smb_conn, "allocation failed");		return;	}	req->out.hdr = req->out.buffer + NBT_HDR_SIZE;	req->out.vwv = req->out.buffer + chain_base_size + 1;	req->out.wct = wct;	req->out.data = req->out.vwv + VWV(wct) + 2;	req->out.data_size = buflen;	req->out.ptr = req->out.data;	SCVAL(req->out.buffer, chain_base_size, wct);	SSVAL(req->out.vwv, VWV(wct), buflen);}/*  setup a reply in req->out with the given word count and initial data buffer size.   the caller will then fill in the command words and data before calling req_send_reply() to   send the reply on its way*/void smbsrv_setup_reply(struct smbsrv_request *req, uint_t wct, size_t buflen){	uint16_t flags2;	if (req->chain_count != 0) {		req_setup_chain_reply(req, wct, buflen);		return;	}	req->out.size = NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct) + buflen;	/* over allocate by a small amount */	req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 	req->out.buffer = talloc_size(req, req->out.allocated);	if (!req->out.buffer) {		smbsrv_terminate_connection(req->smb_conn, "allocation failed");		return;	}	flags2 = FLAGS2_LONG_PATH_COMPONENTS | 		FLAGS2_EXTENDED_ATTRIBUTES | 		FLAGS2_IS_LONG_NAME;	flags2 |= (req->flags2 & (FLAGS2_UNICODE_STRINGS|FLAGS2_EXTENDED_SECURITY));	if (req->smb_conn->negotiate.client_caps & CAP_STATUS32) {		flags2 |= FLAGS2_32_BIT_ERROR_CODES;	}	req->out.hdr = req->out.buffer + NBT_HDR_SIZE;	req->out.vwv = req->out.hdr + HDR_VWV;	req->out.wct = wct;	req->out.data = req->out.vwv + VWV(wct) + 2;	req->out.data_size = buflen;	req->out.ptr = req->out.data;	SIVAL(req->out.hdr, HDR_RCLS, 0);	SCVAL(req->out.hdr, HDR_WCT, wct);	SSVAL(req->out.vwv, VWV(wct), buflen);	memcpy(req->out.hdr, "\377SMB", 4);	SCVAL(req->out.hdr,HDR_FLG, FLAG_REPLY | FLAG_CASELESS_PATHNAMES); 	SSVAL(req->out.hdr,HDR_FLG2, flags2);	SSVAL(req->out.hdr,HDR_PIDHIGH,0);	memset(req->out.hdr + HDR_SS_FIELD, 0, 10);	if (req->in.hdr) {		/* copy the cmd, tid, pid, uid and mid from the request */		SCVAL(req->out.hdr,HDR_COM,CVAL(req->in.hdr,HDR_COM));			SSVAL(req->out.hdr,HDR_TID,SVAL(req->in.hdr,HDR_TID));		SSVAL(req->out.hdr,HDR_PID,SVAL(req->in.hdr,HDR_PID));		SSVAL(req->out.hdr,HDR_UID,SVAL(req->in.hdr,HDR_UID));		SSVAL(req->out.hdr,HDR_MID,SVAL(req->in.hdr,HDR_MID));	} else {		SCVAL(req->out.hdr,HDR_COM,0);		SSVAL(req->out.hdr,HDR_TID,0);		SSVAL(req->out.hdr,HDR_PID,0);		SSVAL(req->out.hdr,HDR_UID,0);		SSVAL(req->out.hdr,HDR_MID,0);	}}/*  setup a copy of a request, used when the server needs to send  more than one reply for a single request packet*/struct smbsrv_request *smbsrv_setup_secondary_request(struct smbsrv_request *old_req){	struct smbsrv_request *req;	ptrdiff_t diff;	req = talloc_memdup(old_req, old_req, sizeof(struct smbsrv_request));	if (req == NULL) {		return NULL;	}	req->out.buffer = talloc_memdup(req, req->out.buffer, req->out.allocated);	if (req->out.buffer == NULL) {		talloc_free(req);		return NULL;	}	diff = req->out.buffer - old_req->out.buffer;	req->out.hdr  += diff;	req->out.vwv  += diff;	req->out.data += diff;	req->out.ptr  += diff;	return req;}/*  work out the maximum data size we will allow for this reply, given  the negotiated max_xmit. The basic reply packet must be setup before  this call  note that this is deliberately a signed integer reply*/int req_max_data(struct smbsrv_request *req){	int ret;	ret = req->smb_conn->negotiate.max_send;	ret -= PTR_DIFF(req->out.data, req->out.hdr);	if (ret < 0) ret = 0;	return ret;}/*  grow the allocation of the data buffer portion of a reply  packet. Note that as this can reallocate the packet buffer this  invalidates any local pointers into the packet.  To cope with this req->out.ptr is supplied. This will be updated to  point at the same offset into the packet as before this call*/static void req_grow_allocation(struct smbsrv_request *req, uint_t new_size){	int delta;	uint8_t *buf2;	delta = new_size - req->out.data_size;	if (delta + req->out.size <= req->out.allocated) {		/* it fits in the preallocation */		return;	}	/* we need to realloc */	req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;	buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);	if (buf2 == NULL) {		smb_panic("out of memory in req_grow_allocation");	}	if (buf2 == req->out.buffer) {		/* the malloc library gave us the same pointer */		return;	}		/* update the pointers into the packet */	req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);	req->out.ptr  = buf2 + PTR_DIFF(req->out.ptr,  req->out.buffer);	req->out.vwv  = buf2 + PTR_DIFF(req->out.vwv,  req->out.buffer);	req->out.hdr  = buf2 + PTR_DIFF(req->out.hdr,  req->out.buffer);	req->out.buffer = buf2;}/*  grow the data buffer portion of a reply packet. Note that as this  can reallocate the packet buffer this invalidates any local pointers  into the packet.   To cope with this req->out.ptr is supplied. This will be updated to  point at the same offset into the packet as before this call*/void req_grow_data(struct smbsrv_request *req, size_t new_size){	int delta;	if (!(req->control_flags & SMBSRV_REQ_CONTROL_LARGE) && new_size > req_max_data(req)) {		smb_panic("reply buffer too large!");	}	req_grow_allocation(req, new_size);	delta = new_size - req->out.data_size;	req->out.size += delta;	req->out.data_size += delta;	/* set the BCC to the new data size */	SSVAL(req->out.vwv, VWV(req->out.wct), new_size);}/*  send a reply and destroy the request buffer  note that this only looks at req->out.buffer and req->out.size, allowing manually   constructed packets to be sent*/void smbsrv_send_reply_nosign(struct smbsrv_request *req){	DATA_BLOB blob;	NTSTATUS status;	if (req->smb_conn->connection->event.fde == NULL) {		/* we are in the process of shutting down this connection */		talloc_free(req);		return;	}	if (req->out.size > NBT_HDR_SIZE) {		_smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);	}	blob = data_blob_const(req->out.buffer, req->out.size);	status = packet_send(req->smb_conn->packet, blob);	if (!NT_STATUS_IS_OK(status)) {		smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));	}	talloc_free(req);}/*  possibly sign a message then send a reply and destroy the request buffer  note that this only looks at req->out.buffer and req->out.size, allowing manually   constructed packets to be sent*/void smbsrv_send_reply(struct smbsrv_request *req){	if (req->smb_conn->connection->event.fde == NULL) {		/* we are in the process of shutting down this connection */		talloc_free(req);		return;	}	smbsrv_sign_packet(req);	smbsrv_send_reply_nosign(req);}/*    setup the header of a reply to include an NTSTATUS code*/void smbsrv_setup_error(struct smbsrv_request *req, NTSTATUS status){	if (!req->smb_conn->config.nt_status_support || !(req->smb_conn->negotiate.client_caps & CAP_STATUS32)) {		/* convert to DOS error codes */		uint8_t eclass;		uint32_t ecode;		ntstatus_to_dos(status, &eclass, &ecode);		SCVAL(req->out.hdr, HDR_RCLS, eclass);		SSVAL(req->out.hdr, HDR_ERR, ecode);		SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);		return;	}	if (NT_STATUS_IS_DOS(status)) {		/* its a encoded DOS error, using the reserved range */		SSVAL(req->out.hdr, HDR_RCLS, NT_STATUS_DOS_CLASS(status));		SSVAL(req->out.hdr, HDR_ERR,  NT_STATUS_DOS_CODE(status));		SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);	} else {		SIVAL(req->out.hdr, HDR_RCLS, NT_STATUS_V(status));		SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) | FLAGS2_32_BIT_ERROR_CODES);	}}/*    construct and send an error packet, then destroy the request    auto-converts to DOS error format when appropriate*/void smbsrv_send_error(struct smbsrv_request *req, NTSTATUS status){	if (req->smb_conn->connection->event.fde == NULL) {		/* the socket has been destroyed - no point trying to send an error! */		talloc_free(req);		return;	}	smbsrv_setup_reply(req, 0, 0);	/* error returns never have any data */	req_grow_data(req, 0);	smbsrv_setup_error(req, status);	smbsrv_send_reply(req);}/*

⌨️ 快捷键说明

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