cli_pipe.c

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

C
2,128
字号
					"PDU data format is big-endian.\n",					cli->cli->desthost,					cli->pipe_name,					(unsigned int)cli->fnum));				prs_set_endian_data(rbuf, RPC_BIG_ENDIAN);			} else {				/* Check endianness on subsequent packets. */				if (current_pdu.bigendian_data != rbuf->bigendian_data) {					DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",						rbuf->bigendian_data ? "big" : "little",						current_pdu.bigendian_data ? "big" : "little" ));					ret = NT_STATUS_INVALID_PARAMETER;					goto err;				}			}		}		/* Now copy the data portion out of the pdu into rbuf. */		if (!prs_force_grow(rbuf, ret_data_len)) {                        ret = NT_STATUS_NO_MEMORY;                        goto err;                }		memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len);		current_rbuf_offset += ret_data_len;		/* See if we've finished with all the data in current_pdu yet ? */		ret = cli_pipe_reset_current_pdu(cli, &rhdr, &current_pdu);		if (!NT_STATUS_IS_OK(ret)) {			goto err;		}		if (rhdr.flags & RPC_FLG_LAST) {			break; /* We're done. */		}	}	DEBUG(10,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x returned %u bytes.\n",		cli->cli->desthost,		cli->pipe_name,		(unsigned int)cli->fnum,		(unsigned int)prs_data_size(rbuf) ));	prs_mem_free(&current_pdu);	return NT_STATUS_OK;  err:	prs_mem_free(&current_pdu);	prs_mem_free(rbuf);	return ret;}/******************************************************************* Creates krb5 auth bind. ********************************************************************/static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,						enum pipe_auth_level auth_level,						RPC_HDR_AUTH *pauth_out,						prs_struct *auth_data){#ifdef HAVE_KRB5	int ret;	struct kerberos_auth_struct *a = cli->auth.a_u.kerberos_auth;	DATA_BLOB tkt = data_blob(NULL, 0);	DATA_BLOB tkt_wrapped = data_blob(NULL, 0);	/* We may change the pad length before marshalling. */	init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);	DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",		a->service_principal ));	/* Create the ticket for the service principal and return it in a gss-api wrapped blob. */	ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,			&a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED);	if (ret) {		DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "			"failed with %s\n",			a->service_principal,			error_message(ret) ));		data_blob_free(&tkt);		prs_mem_free(auth_data);		return NT_STATUS_INVALID_PARAMETER;	}	/* wrap that up in a nice GSS-API wrapping */	tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);	data_blob_free(&tkt);	/* Auth len in the rpc header doesn't include auth_header. */	if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {		data_blob_free(&tkt_wrapped);		prs_mem_free(auth_data);		return NT_STATUS_NO_MEMORY;	}	DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));	dump_data(5, (const char *)tkt_wrapped.data, tkt_wrapped.length);	data_blob_free(&tkt_wrapped);	return NT_STATUS_OK;#else	return NT_STATUS_INVALID_PARAMETER;#endif}/******************************************************************* Creates SPNEGO NTLMSSP auth bind. ********************************************************************/static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,						enum pipe_auth_level auth_level,						RPC_HDR_AUTH *pauth_out,						prs_struct *auth_data){	NTSTATUS nt_status;	DATA_BLOB null_blob = data_blob(NULL, 0);	DATA_BLOB request = data_blob(NULL, 0);	DATA_BLOB spnego_msg = data_blob(NULL, 0);	/* We may change the pad length before marshalling. */	init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);	DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));	nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,					null_blob,					&request);	if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {		data_blob_free(&request);		prs_mem_free(auth_data);		return nt_status;	}	/* Wrap this in SPNEGO. */	spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);	data_blob_free(&request);	/* Auth len in the rpc header doesn't include auth_header. */	if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {		data_blob_free(&spnego_msg);		prs_mem_free(auth_data);		return NT_STATUS_NO_MEMORY;	}	DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));	dump_data(5, (const char *)spnego_msg.data, spnego_msg.length);	data_blob_free(&spnego_msg);	return NT_STATUS_OK;}/******************************************************************* Creates NTLMSSP auth bind. ********************************************************************/static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,						enum pipe_auth_level auth_level,						RPC_HDR_AUTH *pauth_out,						prs_struct *auth_data){	NTSTATUS nt_status;	DATA_BLOB null_blob = data_blob(NULL, 0);	DATA_BLOB request = data_blob(NULL, 0);	/* We may change the pad length before marshalling. */	init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);	DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));	nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,					null_blob,					&request);	if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {		data_blob_free(&request);		prs_mem_free(auth_data);		return nt_status;	}	/* Auth len in the rpc header doesn't include auth_header. */	if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {		data_blob_free(&request);		prs_mem_free(auth_data);		return NT_STATUS_NO_MEMORY;	}	DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));	dump_data(5, (const char *)request.data, request.length);	data_blob_free(&request);	return NT_STATUS_OK;}/******************************************************************* Creates schannel auth bind. ********************************************************************/static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,						enum pipe_auth_level auth_level,						RPC_HDR_AUTH *pauth_out,						prs_struct *auth_data){	RPC_AUTH_SCHANNEL_NEG schannel_neg;	/* We may change the pad length before marshalling. */	init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);	/* Use lp_workgroup() if domain not specified */	if (!cli->domain || !cli->domain[0]) {		cli->domain = lp_workgroup();	}	init_rpc_auth_schannel_neg(&schannel_neg, cli->domain, global_myname());	/*	 * Now marshall the data into the auth parse_struct.	 */	if(!smb_io_rpc_auth_schannel_neg("schannel_neg",				       &schannel_neg, auth_data, 0)) {		DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));		prs_mem_free(auth_data);		return NT_STATUS_NO_MEMORY;	}	return NT_STATUS_OK;}/******************************************************************* Creates the internals of a DCE/RPC bind request or alter context PDU. ********************************************************************/static NTSTATUS create_bind_or_alt_ctx_internal(uint8 pkt_type,						prs_struct *rpc_out, 						uint32 rpc_call_id,						RPC_IFACE *abstract,						RPC_IFACE *transfer,						RPC_HDR_AUTH *phdr_auth,						prs_struct *pauth_info){	RPC_HDR hdr;	RPC_HDR_RB hdr_rb;	RPC_CONTEXT rpc_ctx;	uint16 auth_len = prs_offset(pauth_info);	uint8 ss_padding_len = 0;	uint16 frag_len = 0;	/* create the RPC context. */	init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);	/* create the bind request RPC_HDR_RB */	init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);	/* Start building the frag length. */	frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);	/* Do we need to pad ? */	if (auth_len) {		uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);		if (data_len % 8) {			ss_padding_len = 8 - (data_len % 8);			phdr_auth->auth_pad_len = ss_padding_len;		}		frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;	}	/* Create the request RPC_HDR */	init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);	/* Marshall the RPC header */	if(!smb_io_rpc_hdr("hdr"   , &hdr, rpc_out, 0)) {		DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));		return NT_STATUS_NO_MEMORY;	}	/* Marshall the bind request data */	if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {		DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));		return NT_STATUS_NO_MEMORY;	}	/*	 * Grow the outgoing buffer to store any auth info.	 */	if(auth_len != 0) {		if (ss_padding_len) {			char pad[8];			memset(pad, '\0', 8);			if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {				DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));				return NT_STATUS_NO_MEMORY;			}		}		if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {			DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));			return NT_STATUS_NO_MEMORY;		}		if(!prs_append_prs_data( rpc_out, pauth_info)) {			DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));			return NT_STATUS_NO_MEMORY;		}	}	return NT_STATUS_OK;}/******************************************************************* Creates a DCE/RPC bind request. ********************************************************************/static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,				prs_struct *rpc_out, 				uint32 rpc_call_id,				RPC_IFACE *abstract, RPC_IFACE *transfer,				enum pipe_auth_type auth_type,				enum pipe_auth_level auth_level){	RPC_HDR_AUTH hdr_auth;	prs_struct auth_info;	NTSTATUS ret = NT_STATUS_OK;	ZERO_STRUCT(hdr_auth);	prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);	switch (auth_type) {		case PIPE_AUTH_TYPE_SCHANNEL:			ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);			if (!NT_STATUS_IS_OK(ret)) {				prs_mem_free(&auth_info);				return ret;			}			break;		case PIPE_AUTH_TYPE_NTLMSSP:			ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);			if (!NT_STATUS_IS_OK(ret)) {				prs_mem_free(&auth_info);				return ret;			}			break;		case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:			ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);			if (!NT_STATUS_IS_OK(ret)) {				prs_mem_free(&auth_info);				return ret;			}			break;		case PIPE_AUTH_TYPE_KRB5:			ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);			if (!NT_STATUS_IS_OK(ret)) {				prs_mem_free(&auth_info);				return ret;			}			break;		case PIPE_AUTH_TYPE_NONE:			break;		default:			/* "Can't" happen. */			return NT_STATUS_INVALID_INFO_CLASS;	}	ret = create_bind_or_alt_ctx_internal(RPC_BIND,						rpc_out, 						rpc_call_id,						abstract,						transfer,						&hdr_auth,						&auth_info);	prs_mem_free(&auth_info);	return ret;}/******************************************************************* Create and add the NTLMSSP sign/seal auth header and data. ********************************************************************/static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,					RPC_HDR *phdr,					uint32 ss_padding_len,					prs_struct *outgoing_pdu){	RPC_HDR_AUTH auth_info;	NTSTATUS status;	DATA_BLOB auth_blob = data_blob(NULL, 0);	uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;	if (!cli->auth.a_u.ntlmssp_state) {		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_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));		data_blob_free(&auth_blob);		return NT_STATUS_NO_MEMORY;	}	switch (cli->auth.auth_level) {		case PIPE_AUTH_LEVEL_PRIVACY:			/* Data portion is encrypted. */			status = ntlmssp_seal_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,

⌨️ 快捷键说明

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