cli_pipe.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,128 行 · 第 1/5 页

C
2,128
字号
					(unsigned char *)prs_data_p(outgoing_pdu),					(size_t)prs_offset(outgoing_pdu),					&auth_blob);			if (!NT_STATUS_IS_OK(status)) {				data_blob_free(&auth_blob);				return status;			}			break;		case PIPE_AUTH_LEVEL_INTEGRITY:			/* Data is signed. */			status = ntlmssp_sign_packet(cli->auth.a_u.ntlmssp_state,					(unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,					data_and_pad_len,					(unsigned char *)prs_data_p(outgoing_pdu),					(size_t)prs_offset(outgoing_pdu),					&auth_blob);			if (!NT_STATUS_IS_OK(status)) {				data_blob_free(&auth_blob);				return status;			}			break;		default:			/* Can't happen. */			smb_panic("bad auth level");			/* Notreached. */			return NT_STATUS_INVALID_PARAMETER;	}	/* Finally marshall the blob. */	                                                                                               	if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {		DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",			(unsigned int)NTLMSSP_SIG_SIZE));		data_blob_free(&auth_blob);		return NT_STATUS_NO_MEMORY;	}                                                                                                                                	data_blob_free(&auth_blob);	return NT_STATUS_OK;}/******************************************************************* Create and add the schannel sign/seal auth header and data. ********************************************************************/static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,					RPC_HDR *phdr,					uint32 ss_padding_len,					prs_struct *outgoing_pdu){	RPC_HDR_AUTH auth_info;	RPC_AUTH_SCHANNEL_CHK verf;	struct schannel_auth_struct *sas = cli->auth.a_u.schannel_auth;	char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;	size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;	if (!sas) {		return NT_STATUS_INVALID_PARAMETER;	}	/* Init and marshall the auth header. */	init_rpc_hdr_auth(&auth_info,			map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),			cli->auth.auth_level,			ss_padding_len,			1 /* context id. */);	if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {		DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));		return NT_STATUS_NO_MEMORY;	}	switch (cli->auth.auth_level) {		case PIPE_AUTH_LEVEL_PRIVACY:		case PIPE_AUTH_LEVEL_INTEGRITY:			DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",				sas->seq_num));			schannel_encode(sas,					cli->auth.auth_level,					SENDER_IS_INITIATOR,					&verf,					data_p,					data_and_pad_len);			sas->seq_num++;			break;		default:			/* Can't happen. */			smb_panic("bad auth level");			/* Notreached. */			return NT_STATUS_INVALID_PARAMETER;	}	/* Finally marshall the blob. */	smb_io_rpc_auth_schannel_chk("",			RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,			&verf,			outgoing_pdu,			0);                                                                                               	return NT_STATUS_OK;}/******************************************************************* Calculate how much data we're going to send in this packet, also work out any sign/seal padding length. ********************************************************************/static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,					uint32 data_left,					uint16 *p_frag_len,					uint16 *p_auth_len,					uint32 *p_ss_padding){	uint32 data_space, data_len;	switch (cli->auth.auth_level) {		case PIPE_AUTH_LEVEL_NONE:		case PIPE_AUTH_LEVEL_CONNECT:			data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;			data_len = MIN(data_space, data_left);			*p_ss_padding = 0;			*p_auth_len = 0;			*p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;			return data_len;		case PIPE_AUTH_LEVEL_INTEGRITY:		case PIPE_AUTH_LEVEL_PRIVACY:			/* Treat the same for all authenticated rpc requests. */			switch(cli->auth.auth_type) {				case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:				case PIPE_AUTH_TYPE_NTLMSSP:					*p_auth_len = NTLMSSP_SIG_SIZE;					break;				case PIPE_AUTH_TYPE_SCHANNEL:					*p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;					break;				default:					smb_panic("bad auth type");					break;			}			data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -						RPC_HDR_AUTH_LEN - *p_auth_len;			data_len = MIN(data_space, data_left);			if (data_len % 8) {				*p_ss_padding = 8 - (data_len % 8);			}			*p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + 		/* Normal headers. */					data_len + *p_ss_padding + 		/* data plus padding. */					RPC_HDR_AUTH_LEN + *p_auth_len;		/* Auth header and auth data. */			return data_len;		default:			smb_panic("bad auth level");			/* Notreached. */			return 0;	}}/******************************************************************* External interface. Does an rpc request on a pipe. Incoming data is NDR encoded in in_data. Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's and deals with signing/sealing details. ********************************************************************/NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,			uint8 op_num,			prs_struct *in_data,			prs_struct *out_data){	NTSTATUS ret;	uint32 data_left = prs_offset(in_data);	uint32 alloc_hint = prs_offset(in_data);	uint32 data_sent_thistime = 0;	uint32 current_data_offset = 0;	uint32 call_id = get_rpc_call_id();	char pad[8];	prs_struct outgoing_pdu;	memset(pad, '\0', 8);	if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {		/* Server is screwed up ! */		return NT_STATUS_INVALID_PARAMETER;	}	prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL);	while (1) {		RPC_HDR hdr;		RPC_HDR_REQ hdr_req;		uint16 auth_len = 0;		uint16 frag_len = 0;		uint8 flags = 0;		uint32 ss_padding = 0;		data_sent_thistime = calculate_data_len_tosend(cli, data_left,						&frag_len, &auth_len, &ss_padding);		if (current_data_offset == 0) {			flags = RPC_FLG_FIRST;		}		if (data_sent_thistime == data_left) {			flags |= RPC_FLG_LAST;		}		/* Create and marshall the header and request header. */		init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);		if(!smb_io_rpc_hdr("hdr    ", &hdr, &outgoing_pdu, 0)) {			prs_mem_free(&outgoing_pdu);			return NT_STATUS_NO_MEMORY;		}		/* Create the rpc request RPC_HDR_REQ */		init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);		if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {			prs_mem_free(&outgoing_pdu);			return NT_STATUS_NO_MEMORY;		}		/* Copy in the data, plus any ss padding. */		if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {			prs_mem_free(&outgoing_pdu);			return NT_STATUS_NO_MEMORY;		}		/* Copy the sign/seal padding data. */		if (ss_padding) {			if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {				prs_mem_free(&outgoing_pdu);				return NT_STATUS_NO_MEMORY;			}		}		/* Generate any auth sign/seal and add the auth footer. */		if (auth_len) {			switch (cli->auth.auth_type) {				case PIPE_AUTH_TYPE_NONE:					break;				case PIPE_AUTH_TYPE_NTLMSSP:				case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:					ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);					if (!NT_STATUS_IS_OK(ret)) {						prs_mem_free(&outgoing_pdu);						return ret;					}					break;				case PIPE_AUTH_TYPE_SCHANNEL:					ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);					if (!NT_STATUS_IS_OK(ret)) {						prs_mem_free(&outgoing_pdu);						return ret;					}					break;				default:					smb_panic("bad auth type");					break; /* notreached */			}		}		/* Actually send the packet. */		if (flags & RPC_FLG_LAST) {			/* Last packet - send the data, get the reply and return. */			ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);			prs_mem_free(&outgoing_pdu);						if (DEBUGLEVEL >= 50) {				pstring dump_name;				/* Also capture received data */				slprintf(dump_name, sizeof(dump_name) - 1, "%s/reply_%s_%d",					dyn_LOGFILEBASE, cli->pipe_name, op_num);				prs_dump(dump_name, op_num, out_data);			}			return ret;		} else {			/* More packets to come - write and continue. */			ssize_t num_written = cli_write(cli->cli, cli->fnum, 8, /* 8 means message mode. */							prs_data_p(&outgoing_pdu),							(off_t)0,							(size_t)hdr.frag_len);			if (num_written != hdr.frag_len) {				prs_mem_free(&outgoing_pdu);				return cli_get_nt_error(cli->cli);			}		}		current_data_offset += data_sent_thistime;		data_left -= data_sent_thistime;		/* Reset the marshalling position back to zero. */		if (!prs_set_offset(&outgoing_pdu, 0)) {			prs_mem_free(&outgoing_pdu);			return NT_STATUS_NO_MEMORY;		}	}}#if 0/**************************************************************************** Set the handle state.****************************************************************************/static BOOL rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,				   const char *pipe_name, uint16 device_state){	BOOL state_set = False;	char param[2];	uint16 setup[2]; /* only need 2 uint16 setup parameters */	char *rparam = NULL;	char *rdata = NULL;	uint32 rparam_len, rdata_len;	if (pipe_name == NULL)		return False;	DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",		 cli->fnum, pipe_name, device_state));	/* create parameters: device state */	SSVAL(param, 0, device_state);	/* create setup parameters. */	setup[0] = 0x0001; 	setup[1] = cli->fnum; /* pipe file handle.  got this from an SMBOpenX. */	/* send the data on \PIPE\ */	if (cli_api_pipe(cli->cli, "\\PIPE\\",	            setup, 2, 0,                /* setup, length, max */	            param, 2, 0,                /* param, length, max */	            NULL, 0, 1024,              /* data, length, max */	            &rparam, &rparam_len,        /* return param, length */	            &rdata, &rdata_len))         /* return data, length */	{		DEBUG(5, ("Set Handle state: return OK\n"));		state_set = True;	}	SAFE_FREE(rparam);	SAFE_FREE(rdata);	return state_set;}#endif/**************************************************************************** Check the rpc bind acknowledge response.****************************************************************************/static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *transfer){	if ( pipe_idx >= PI_MAX_PIPES ) {		DEBUG(0,("valid_pipe_name: Programmer error!  Invalid pipe index [%d]\n",			pipe_idx));		return False;	}	DEBUG(5,("Bind Abstract Syntax: "));		dump_data(5, (char*)&pipe_names[pipe_idx].abstr_syntax, 	          sizeof(pipe_names[pipe_idx].abstr_syntax));	DEBUG(5,("Bind Transfer Syntax: "));	dump_data(5, (char*)&pipe_names[pipe_idx].trans_syntax,	          sizeof(pipe_names[pipe_idx].trans_syntax));	/* copy the required syntaxes out so we can do the right bind */		*transfer = pipe_names[pipe_idx].trans_syntax;	*abstract = pipe_names[pipe_idx].abstr_syntax;	return True;}/**************************************************************************** Check the rpc bind acknowledge response.****************************************************************************/static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFACE *transfer){	if ( hdr_ba->addr.len == 0) {		DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));	}# if 0	/* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */	if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) &&	     !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) )	{		DEBUG(4,("bind_rpc_pipe: pipe_name %s != expected pipe %s.  oh well!\n",		         pipe_names[i].server_pipe ,hdr_ba->addr.str));		return False;	}		DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n", pipe_names[i].server_pipe ));	if (pipe_names[pipe_idx].server_pipe == NULL) {		DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));		return False;	}#endif 	/* JERRY */	/* check the transfer syntax */	if ((hdr_ba->transfer.version != transfer->version) ||	     (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {		DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));		return False;	}	if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {		DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",		          hdr_ba->res.num_results, hdr_ba->res.reason));	}	DEBUG(5,("check_bind_response: accepted!\n"));	return True;}

⌨️ 快捷键说明

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