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

📄 srv_pipe_hnd.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * This also sets the endian flag in rpc_in.	 */	if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) {		DEBUG(0,("unmarshall_rpc_header: failed to unmarshall RPC_HDR.\n"));		set_incoming_fault(p);		prs_mem_free(&rpc_in);		return -1;	}	/*	 * Validate the RPC header.	 */	if(p->hdr.major != 5 && p->hdr.minor != 0) {		DEBUG(0,("unmarshall_rpc_header: invalid major/minor numbers in RPC_HDR.\n"));		set_incoming_fault(p);		prs_mem_free(&rpc_in);		return -1;	}	/*	 * If there's not data in the incoming buffer this should be the start of a new RPC.	 */	if(prs_offset(&p->in_data.data) == 0) {		/*		 * AS/U doesn't set FIRST flag in a BIND packet it seems.		 */		if ((p->hdr.pkt_type == RPC_REQUEST) && !(p->hdr.flags & RPC_FLG_FIRST)) {			/*			 * Ensure that the FIRST flag is set. If not then we have			 * a stream missmatch.			 */			DEBUG(0,("unmarshall_rpc_header: FIRST flag not set in first PDU !\n"));			set_incoming_fault(p);			prs_mem_free(&rpc_in);			return -1;		}		/*		 * If this is the first PDU then set the endianness		 * flag in the pipe. We will need this when parsing all		 * data in this RPC.		 */		p->endian = rpc_in.bigendian_data;		DEBUG(5,("unmarshall_rpc_header: using %sendian RPC\n",				p->endian == RPC_LITTLE_ENDIAN ? "little-" : "big-" ));	} else {		/*		 * If this is *NOT* the first PDU then check the endianness		 * flag in the pipe is the same as that in the PDU.		 */		if (p->endian != rpc_in.bigendian_data) {			DEBUG(0,("unmarshall_rpc_header: FIRST endianness flag (%d) different in next PDU !\n", (int)p->endian));			set_incoming_fault(p);			prs_mem_free(&rpc_in);			return -1;		}	}	/*	 * Ensure that the pdu length is sane.	 */	if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > RPC_MAX_PDU_FRAG_LEN)) {		DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));		set_incoming_fault(p);		prs_mem_free(&rpc_in);		return -1;	}	DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,			(unsigned int)p->hdr.flags ));	p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;	prs_mem_free(&rpc_in);	return 0; /* No extra data processed. */}/**************************************************************************** Call this to free any talloc'ed memory. Do this before and after processing a complete PDU.****************************************************************************/static void free_pipe_context(pipes_struct *p){	if (p->mem_ctx) {		DEBUG(3,("free_pipe_context: destroying talloc pool of size "			 "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) ));		talloc_free_children(p->mem_ctx);	} else {		p->mem_ctx = talloc_init("pipe %s %p", p->name, p);		if (p->mem_ctx == NULL) {			p->fault_state = True;		}	}}/**************************************************************************** Processes a request pdu. This will do auth processing if needed, and appends the data into the complete stream if the LAST flag is not set.****************************************************************************/static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p){	uint32 ss_padding_len = 0;	size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -				(p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;	if(!p->pipe_bound) {		DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));		set_incoming_fault(p);		return False;	}	/*	 * Check if we need to do authentication processing.	 * This is only done on requests, not binds.	 */	/*	 * Read the RPC request header.	 */	if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {		DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));		set_incoming_fault(p);		return False;	}	switch(p->auth.auth_type) {		case PIPE_AUTH_TYPE_NONE:			break;		case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:		case PIPE_AUTH_TYPE_NTLMSSP:		{			NTSTATUS status;			if(!api_pipe_ntlmssp_auth_process(p, rpc_in_p, &ss_padding_len, &status)) {				DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));				DEBUG(0,("process_request_pdu: error was %s.\n", nt_errstr(status) ));				set_incoming_fault(p);				return False;			}			break;		}		case PIPE_AUTH_TYPE_SCHANNEL:			if (!api_pipe_schannel_process(p, rpc_in_p, &ss_padding_len)) {				DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));				set_incoming_fault(p);				return False;			}			break;		default:			DEBUG(0,("process_request_pdu: unknown auth type %u set.\n", (unsigned int)p->auth.auth_type ));			set_incoming_fault(p);			return False;	}	/* Now we've done the sign/seal we can remove any padding data. */	if (data_len > ss_padding_len) {		data_len -= ss_padding_len;	}	/*	 * Check the data length doesn't go over the 15Mb limit.	 * increased after observing a bug in the Windows NT 4.0 SP6a	 * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC	 * will not fit in the initial buffer of size 0x1068   --jerry 22/01/2002	 */		if(prs_offset(&p->in_data.data) + data_len > 15*1024*1024) {		DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",				(unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));		set_incoming_fault(p);		return False;	}	/*	 * Append the data portion into the buffer and return.	 */	if(!prs_append_some_prs_data(&p->in_data.data, rpc_in_p, prs_offset(rpc_in_p), data_len)) {		DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",				(unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));		set_incoming_fault(p);		return False;	}	if(p->hdr.flags & RPC_FLG_LAST) {		BOOL ret = False;		/*		 * Ok - we finally have a complete RPC stream.		 * Call the rpc command to process it.		 */		/*		 * Ensure the internal prs buffer size is *exactly* the same		 * size as the current offset.		 */ 		if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data))) {			DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));			set_incoming_fault(p);			return False;		}		/*		 * Set the parse offset to the start of the data and set the		 * prs_struct to UNMARSHALL.		 */		prs_set_offset(&p->in_data.data, 0);		prs_switch_type(&p->in_data.data, UNMARSHALL);		/*		 * Process the complete data stream here.		 */		free_pipe_context(p);		if(pipe_init_outgoing_data(p)) {			ret = api_pipe_request(p);		}		free_pipe_context(p);		/*		 * We have consumed the whole data stream. Set back to		 * marshalling and set the offset back to the start of		 * the buffer to re-use it (we could also do a prs_mem_free()		 * and then re_init on the next start of PDU. Not sure which		 * is best here.... JRA.		 */		prs_switch_type(&p->in_data.data, MARSHALL);		prs_set_offset(&p->in_data.data, 0);		return ret;	}	return True;}/**************************************************************************** Processes a finished PDU stored in current_in_pdu. The RPC_HEADER has already been parsed and stored in p->hdr.****************************************************************************/static void process_complete_pdu(pipes_struct *p){	prs_struct rpc_in;	size_t data_len = p->in_data.pdu_received_len - RPC_HEADER_LEN;	char *data_p = (char *)&p->in_data.current_in_pdu[RPC_HEADER_LEN];	BOOL reply = False;	if(p->fault_state) {		DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n",			p->name ));		set_incoming_fault(p);		setup_fault_pdu(p, NT_STATUS(0x1c010002));		return;	}	prs_init( &rpc_in, 0, p->mem_ctx, UNMARSHALL);	/*	 * Ensure we're using the corrent endianness for both the 	 * RPC header flags and the raw data we will be reading from.	 */	prs_set_endian_data( &rpc_in, p->endian);	prs_set_endian_data( &p->in_data.data, p->endian);	prs_give_memory( &rpc_in, data_p, (uint32)data_len, False);	DEBUG(10,("process_complete_pdu: processing packet type %u\n",			(unsigned int)p->hdr.pkt_type ));	switch (p->hdr.pkt_type) {		case RPC_REQUEST:			reply = process_request_pdu(p, &rpc_in);			break;		case RPC_PING: /* CL request - ignore... */			DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",				(unsigned int)p->hdr.pkt_type, p->name));			break;		case RPC_RESPONSE: /* No responses here. */			DEBUG(0,("process_complete_pdu: Error. RPC_RESPONSE received from client on pipe %s.\n",				p->name ));			break;		case RPC_FAULT:		case RPC_WORKING: /* CL request - reply to a ping when a call in process. */		case RPC_NOCALL: /* CL - server reply to a ping call. */		case RPC_REJECT:		case RPC_ACK:		case RPC_CL_CANCEL:		case RPC_FACK:		case RPC_CANCEL_ACK:			DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",				(unsigned int)p->hdr.pkt_type, p->name));			break;		case RPC_BIND:			/*			 * We assume that a pipe bind is only in one pdu.			 */			if(pipe_init_outgoing_data(p)) {				reply = api_pipe_bind_req(p, &rpc_in);			}			break;		case RPC_BINDACK:		case RPC_BINDNACK:			DEBUG(0,("process_complete_pdu: Error. RPC_BINDACK/RPC_BINDNACK packet type %u received on pipe %s.\n",				(unsigned int)p->hdr.pkt_type, p->name));			break;		case RPC_ALTCONT:			/*			 * We assume that a pipe bind is only in one pdu.			 */			if(pipe_init_outgoing_data(p)) {				reply = api_pipe_alter_context(p, &rpc_in);			}			break;		case RPC_ALTCONTRESP:			DEBUG(0,("process_complete_pdu: Error. RPC_ALTCONTRESP on pipe %s: Should only be server -> client.\n",				p->name));			break;		case RPC_AUTH3:			/*			 * The third packet in an NTLMSSP auth exchange.			 */			if(pipe_init_outgoing_data(p)) {				reply = api_pipe_bind_auth3(p, &rpc_in);			}			break;		case RPC_SHUTDOWN:			DEBUG(0,("process_complete_pdu: Error. RPC_SHUTDOWN on pipe %s: Should only be server -> client.\n",				p->name));			break;		case RPC_CO_CANCEL:			/* For now just free all client data and continue processing. */			DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n"));			/* As we never do asynchronous RPC serving, we can never cancel a			   call (as far as I know). If we ever did we'd have to send a cancel_ack			   reply. For now, just free all client data and continue processing. */			reply = True;			break;#if 0			/* Enable this if we're doing async rpc. */			/* We must check the call-id matches the outstanding callid. */			if(pipe_init_outgoing_data(p)) {				/* Send a cancel_ack PDU reply. */				/* We should probably check the auth-verifier here. */				reply = setup_cancel_ack_reply(p, &rpc_in);			}			break;#endif		case RPC_ORPHANED:			/* We should probably check the auth-verifier here.			   For now just free all client data and continue processing. */			DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n"));			reply = True;			break;		default:			DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type ));			break;	}	/* Reset to little endian. Probably don't need this but it won't hurt. */	prs_set_endian_data( &p->in_data.data, RPC_LITTLE_ENDIAN);	if (!reply) {		DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on pipe %s\n", p->pipe_srv_name));		set_incoming_fault(p);		setup_fault_pdu(p, NT_STATUS(0x1c010002));		prs_mem_free(&rpc_in);	} else {		/*		 * Reset the lengths. We're ready for a new pdu.		 */		p->in_data.pdu_needed_len = 0;		p->in_data.pdu_received_len = 0;	}	prs_mem_free(&rpc_in);}/**************************************************************************** Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.****************************************************************************/static ssize_t process_incoming_data(pipes_struct *p, char *data, size_t n){	size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len);	DEBUG(10,("process_incoming_data: Start: pdu_received_len = %u, pdu_needed_len = %u, incoming data = %u\n",		(unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len,		(unsigned int)n ));	if(data_to_copy == 0) {		/*

⌨️ 快捷键说明

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