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

📄 srv_pipe_hnd.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  *  Unix SMB/CIFS implementation. *  RPC Pipe client / server routines *  Copyright (C) Andrew Tridgell              1992-1998, *  Largely re-written : 2005 *  Copyright (C) Jeremy Allison		1998 - 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"#undef DBGC_CLASS#define DBGC_CLASS DBGC_RPC_SRV#define	PIPE		"\\PIPE\\"#define	PIPELEN		strlen(PIPE)static smb_np_struct *chain_p;static int pipes_open;/* * Sometimes I can't decide if I hate Windows printer driver * writers more than I hate the Windows spooler service driver * writers. This gets around a combination of bugs in the spooler * and the HP 8500 PCL driver that causes a spooler spin. JRA. * * bumped up from 20 -> 64 after viewing traffic from WordPerfect * 2002 running on NT 4.- SP6 * bumped up from 64 -> 256 after viewing traffic from con2prt * for lots of printers on a WinNT 4.x SP6 box. */ #ifndef MAX_OPEN_SPOOLSS_PIPES#define MAX_OPEN_SPOOLSS_PIPES 256#endifstatic int current_spoolss_pipes_open;static smb_np_struct *Pipes;static pipes_struct *InternalPipes;static struct bitmap *bmap;/* TODO * the following prototypes are declared here to avoid * code being moved about too much for a patch to be * disrupted / less obvious. * * these functions, and associated functions that they * call, should be moved behind a .so module-loading * system _anyway_.  so that's the next step... */static ssize_t read_from_internal_pipe(void *np_conn, char *data, size_t n,		BOOL *is_data_outstanding);static ssize_t write_to_internal_pipe(void *np_conn, char *data, size_t n);static BOOL close_internal_rpc_pipe_hnd(void *np_conn);static void *make_internal_rpc_pipe_p(char *pipe_name, 			      connection_struct *conn, uint16 vuid);/**************************************************************************** Pipe iterator functions.****************************************************************************/smb_np_struct *get_first_pipe(void){	return Pipes;}smb_np_struct *get_next_pipe(smb_np_struct *p){	return p->next;}/**************************************************************************** Internal Pipe iterator functions.****************************************************************************/pipes_struct *get_first_internal_pipe(void){	return InternalPipes;}pipes_struct *get_next_internal_pipe(pipes_struct *p){	return p->next;}/* this must be larger than the sum of the open files and directories */static int pipe_handle_offset;/**************************************************************************** Set the pipe_handle_offset. Called from smbd/files.c****************************************************************************/void set_pipe_handle_offset(int max_open_files){	if(max_open_files < 0x7000) {		pipe_handle_offset = 0x7000;	} else {		pipe_handle_offset = max_open_files + 10; /* For safety. :-) */	}}/**************************************************************************** Reset pipe chain handle number.****************************************************************************/void reset_chain_p(void){	chain_p = NULL;}/**************************************************************************** Initialise pipe handle states.****************************************************************************/void init_rpc_pipe_hnd(void){	bmap = bitmap_allocate(MAX_OPEN_PIPES);	if (!bmap) {		exit_server("out of memory in init_rpc_pipe_hnd");	}}/**************************************************************************** Initialise an outgoing packet.****************************************************************************/static BOOL pipe_init_outgoing_data(pipes_struct *p){	output_data *o_data = &p->out_data;	/* Reset the offset counters. */	o_data->data_sent_length = 0;	o_data->current_pdu_len = 0;	o_data->current_pdu_sent = 0;	memset(o_data->current_pdu, '\0', sizeof(o_data->current_pdu));	/* Free any memory in the current return data buffer. */	prs_mem_free(&o_data->rdata);	/*	 * Initialize the outgoing RPC data buffer.	 * we will use this as the raw data area for replying to rpc requests.	 */		if(!prs_init(&o_data->rdata, RPC_MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) {		DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n"));		return False;	}	return True;}/**************************************************************************** Find first available pipe slot.****************************************************************************/smb_np_struct *open_rpc_pipe_p(char *pipe_name, 			      connection_struct *conn, uint16 vuid){	int i;	smb_np_struct *p, *p_it;	static int next_pipe;	BOOL is_spoolss_pipe = False;	DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",		 pipe_name, pipes_open));	if (strstr(pipe_name, "spoolss")) {		is_spoolss_pipe = True;	} 	if (is_spoolss_pipe && current_spoolss_pipes_open >= MAX_OPEN_SPOOLSS_PIPES) {		DEBUG(10,("open_rpc_pipe_p: spooler bug workaround. Denying open on pipe %s\n",			pipe_name ));		return NULL;	}	/* not repeating pipe numbers makes it easier to track things in 	   log files and prevents client bugs where pipe numbers are reused	   over connection restarts */	if (next_pipe == 0) {		next_pipe = (sys_getpid() ^ time(NULL)) % MAX_OPEN_PIPES;	}	i = bitmap_find(bmap, next_pipe);	if (i == -1) {		DEBUG(0,("ERROR! Out of pipe structures\n"));		return NULL;	}	next_pipe = (i+1) % MAX_OPEN_PIPES;	for (p = Pipes; p; p = p->next) {		DEBUG(5,("open_rpc_pipe_p: name %s pnum=%x\n", p->name, p->pnum));  	}	p = SMB_MALLOC_P(smb_np_struct);	if (!p) {		DEBUG(0,("ERROR! no memory for pipes_struct!\n"));		return NULL;	}	ZERO_STRUCTP(p);	/* add a dso mechanism instead of this, here */	p->namedpipe_create = make_internal_rpc_pipe_p;	p->namedpipe_read = read_from_internal_pipe;	p->namedpipe_write = write_to_internal_pipe;	p->namedpipe_close = close_internal_rpc_pipe_hnd;	p->np_state = p->namedpipe_create(pipe_name, conn, vuid);	if (p->np_state == NULL) {		DEBUG(0,("open_rpc_pipe_p: make_internal_rpc_pipe_p failed.\n"));		SAFE_FREE(p);		return NULL;	}	DLIST_ADD(Pipes, p);	/*	 * Initialize the incoming RPC data buffer with one PDU worth of memory.	 * We cheat here and say we're marshalling, as we intend to add incoming	 * data directly into the prs_struct and we want it to auto grow. We will	 * change the type to UNMARSALLING before processing the stream.	 */	bitmap_set(bmap, i);	i += pipe_handle_offset;	pipes_open++;	p->pnum = i;	p->open = True;	p->device_state = 0;	p->priority = 0;	p->conn = conn;	p->vuid  = vuid;	p->max_trans_reply = 0;		fstrcpy(p->name, pipe_name);		DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",		 pipe_name, i, pipes_open));		chain_p = p;		/* Iterate over p_it as a temp variable, to display all open pipes */ 	for (p_it = Pipes; p_it; p_it = p_it->next) {		DEBUG(5,("open pipes: name %s pnum=%x\n", p_it->name, p_it->pnum));  	}	return chain_p;}/**************************************************************************** Make an internal namedpipes structure****************************************************************************/static void *make_internal_rpc_pipe_p(char *pipe_name, 			      connection_struct *conn, uint16 vuid){	pipes_struct *p;	user_struct *vuser = get_valid_user_struct(vuid);	DEBUG(4,("Create pipe requested %s\n", pipe_name));	if (!vuser && vuid != UID_FIELD_INVALID) {		DEBUG(0,("ERROR! vuid %d did not map to a valid vuser struct!\n", vuid));		return NULL;	}	p = SMB_MALLOC_P(pipes_struct);	if (!p) {		DEBUG(0,("ERROR! no memory for pipes_struct!\n"));		return NULL;	}	ZERO_STRUCTP(p);	if ((p->mem_ctx = talloc_init("pipe %s %p", pipe_name, p)) == NULL) {		DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));		SAFE_FREE(p);		return NULL;	}	if ((p->pipe_state_mem_ctx = talloc_init("pipe_state %s %p", pipe_name, p)) == NULL) {		DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));		talloc_destroy(p->mem_ctx);		SAFE_FREE(p);		return NULL;	}	if (!init_pipe_handle_list(p, pipe_name)) {		DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n"));		talloc_destroy(p->mem_ctx);		talloc_destroy(p->pipe_state_mem_ctx);		SAFE_FREE(p);		return NULL;	}	/*	 * Initialize the incoming RPC data buffer with one PDU worth of memory.	 * We cheat here and say we're marshalling, as we intend to add incoming	 * data directly into the prs_struct and we want it to auto grow. We will	 * change the type to UNMARSALLING before processing the stream.	 */	if(!prs_init(&p->in_data.data, RPC_MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) {		DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n"));		talloc_destroy(p->mem_ctx);		talloc_destroy(p->pipe_state_mem_ctx);		return NULL;	}	DLIST_ADD(InternalPipes, p);	p->conn = conn;	p->vuid  = vuid;	p->endian = RPC_LITTLE_ENDIAN;	ZERO_STRUCT(p->pipe_user);	p->pipe_user.uid = (uid_t)-1;	p->pipe_user.gid = (gid_t)-1;		/* Store the session key and NT_TOKEN */	if (vuser) {		p->session_key = data_blob(vuser->session_key.data, vuser->session_key.length);		p->pipe_user.nt_user_token = dup_nt_token(vuser->nt_user_token);	}	/*	 * Initialize the outgoing RPC data buffer with no memory.	 */		prs_init(&p->out_data.rdata, 0, p->mem_ctx, MARSHALL);		fstrcpy(p->name, pipe_name);		DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n",		 pipe_name, pipes_open));	return (void*)p;}/**************************************************************************** Sets the fault state on incoming packets.****************************************************************************/static void set_incoming_fault(pipes_struct *p){	prs_mem_free(&p->in_data.data);	p->in_data.pdu_needed_len = 0;	p->in_data.pdu_received_len = 0;	p->fault_state = True;	DEBUG(10,("set_incoming_fault: Setting fault state on pipe %s : vuid = 0x%x\n",		p->name, p->vuid ));}/**************************************************************************** Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.****************************************************************************/static ssize_t fill_rpc_header(pipes_struct *p, char *data, size_t data_to_copy){	size_t len_needed_to_complete_hdr = MIN(data_to_copy, RPC_HEADER_LEN - p->in_data.pdu_received_len);	DEBUG(10,("fill_rpc_header: data_to_copy = %u, len_needed_to_complete_hdr = %u, receive_len = %u\n",			(unsigned int)data_to_copy, (unsigned int)len_needed_to_complete_hdr,			(unsigned int)p->in_data.pdu_received_len ));	memcpy((char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, len_needed_to_complete_hdr);	p->in_data.pdu_received_len += len_needed_to_complete_hdr;	return (ssize_t)len_needed_to_complete_hdr;}/**************************************************************************** Unmarshalls a new PDU header. Assumes the raw header data is in current_in_pdu.****************************************************************************/static ssize_t unmarshall_rpc_header(pipes_struct *p){	/*	 * Unmarshall the header to determine the needed length.	 */	prs_struct rpc_in;	if(p->in_data.pdu_received_len != RPC_HEADER_LEN) {		DEBUG(0,("unmarshall_rpc_header: assert on rpc header length failed.\n"));		set_incoming_fault(p);		return -1;	}	prs_init( &rpc_in, 0, p->mem_ctx, UNMARSHALL);	prs_set_endian_data( &rpc_in, p->endian);	prs_give_memory( &rpc_in, (char *)&p->in_data.current_in_pdu[0],					p->in_data.pdu_received_len, False);	/*	 * Unmarshall the header as this will tell us how much	 * data we need to read to get the complete pdu.

⌨️ 快捷键说明

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