📄 rpc_message.c
字号:
/* * RPC messages * * Copyright 2001-2002 Ove K鍁en, TransGaming Technologies * Copyright 2004 Filip Navara * Copyright 2006 CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */#include <stdarg.h>#include <stdio.h>#include <string.h>#include "windef.h"#include "winbase.h"#include "winerror.h"#include "rpc.h"#include "rpcndr.h"#include "rpcdcep.h"#include "wine/debug.h"#include "rpc_binding.h"#include "rpc_defs.h"#include "rpc_message.h"#include "ncastatus.h"WINE_DEFAULT_DEBUG_CHANNEL(rpc);/* note: the DCE/RPC spec says the alignment amount should be 4, but * MS/RPC servers seem to always use 16 */#define AUTH_ALIGNMENT 16/* gets the amount needed to round a value up to the specified alignment */#define ROUND_UP_AMOUNT(value, alignment) \ (((alignment) - (((value) % (alignment)))) % (alignment))#define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1))enum secure_packet_direction{ SECURE_PACKET_SEND, SECURE_PACKET_RECEIVE};static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg);static DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header){ static const DWORD header_sizes[] = { sizeof(Header->request), 0, sizeof(Header->response), sizeof(Header->fault), 0, 0, 0, 0, 0, 0, 0, sizeof(Header->bind), sizeof(Header->bind_ack), sizeof(Header->bind_nack), 0, 0, 0, 0, 0 }; ULONG ret = 0; if (Header->common.ptype < sizeof(header_sizes) / sizeof(header_sizes[0])) { ret = header_sizes[Header->common.ptype]; if (ret == 0) FIXME("unhandled packet type\n"); if (Header->common.flags & RPC_FLG_OBJECT_UUID) ret += sizeof(UUID); } else { TRACE("invalid packet type\n"); } return ret;}static int packet_has_body(const RpcPktHdr *Header){ return (Header->common.ptype == PKT_FAULT) || (Header->common.ptype == PKT_REQUEST) || (Header->common.ptype == PKT_RESPONSE);}static int packet_has_auth_verifier(const RpcPktHdr *Header){ return !(Header->common.ptype == PKT_BIND_NACK) && !(Header->common.ptype == PKT_SHUTDOWN);}static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType, unsigned long DataRepresentation){ Header->common.rpc_ver = RPC_VER_MAJOR; Header->common.rpc_ver_minor = RPC_VER_MINOR; Header->common.ptype = PacketType; Header->common.drep[0] = LOBYTE(LOWORD(DataRepresentation)); Header->common.drep[1] = HIBYTE(LOWORD(DataRepresentation)); Header->common.drep[2] = LOBYTE(HIWORD(DataRepresentation)); Header->common.drep[3] = HIBYTE(HIWORD(DataRepresentation)); Header->common.auth_len = 0; Header->common.call_id = 1; Header->common.flags = 0; /* Flags and fragment length are computed in RPCRT4_Send. */} static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation, unsigned long BufferLength, unsigned short ProcNum, UUID *ObjectUuid){ RpcPktHdr *header; BOOL has_object; RPC_STATUS status; has_object = (ObjectUuid != NULL && !UuidIsNil(ObjectUuid, &status)); header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->request) + (has_object ? sizeof(UUID) : 0)); if (header == NULL) { return NULL; } RPCRT4_BuildCommonHeader(header, PKT_REQUEST, DataRepresentation); header->common.frag_len = sizeof(header->request); header->request.alloc_hint = BufferLength; header->request.context_id = 0; header->request.opnum = ProcNum; if (has_object) { header->common.flags |= RPC_FLG_OBJECT_UUID; header->common.frag_len += sizeof(UUID); memcpy(&header->request + 1, ObjectUuid, sizeof(UUID)); } return header;}RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, unsigned long BufferLength){ RpcPktHdr *header; header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->response)); if (header == NULL) { return NULL; } RPCRT4_BuildCommonHeader(header, PKT_RESPONSE, DataRepresentation); header->common.frag_len = sizeof(header->response); header->response.alloc_hint = BufferLength; return header;}RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, RPC_STATUS Status){ RpcPktHdr *header; header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->fault)); if (header == NULL) { return NULL; } RPCRT4_BuildCommonHeader(header, PKT_FAULT, DataRepresentation); header->common.frag_len = sizeof(header->fault); header->fault.status = Status; return header;}RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, unsigned long AssocGroupId, const RPC_SYNTAX_IDENTIFIER *AbstractId, const RPC_SYNTAX_IDENTIFIER *TransferId){ RpcPktHdr *header; header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind)); if (header == NULL) { return NULL; } RPCRT4_BuildCommonHeader(header, PKT_BIND, DataRepresentation); header->common.frag_len = sizeof(header->bind); header->bind.max_tsize = MaxTransmissionSize; header->bind.max_rsize = MaxReceiveSize; header->bind.assoc_gid = AssocGroupId; header->bind.num_elements = 1; header->bind.num_syntaxes = 1; memcpy(&header->bind.abstract, AbstractId, sizeof(RPC_SYNTAX_IDENTIFIER)); memcpy(&header->bind.transfer, TransferId, sizeof(RPC_SYNTAX_IDENTIFIER)); return header;}static RpcPktHdr *RPCRT4_BuildAuthHeader(unsigned long DataRepresentation){ RpcPktHdr *header; header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->common) + 12); if (header == NULL) return NULL; RPCRT4_BuildCommonHeader(header, PKT_AUTH3, DataRepresentation); header->common.frag_len = 0x14; header->common.auth_len = 0; return header;}RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor){ RpcPktHdr *header; header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind_nack)); if (header == NULL) { return NULL; } RPCRT4_BuildCommonHeader(header, PKT_BIND_NACK, DataRepresentation); header->common.frag_len = sizeof(header->bind_nack); header->bind_nack.protocols_count = 1; header->bind_nack.protocols[0].rpc_ver = RpcVersion; header->bind_nack.protocols[0].rpc_ver_minor = RpcVersionMinor; return header;}RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, LPCSTR ServerAddress, unsigned long Result, unsigned long Reason, const RPC_SYNTAX_IDENTIFIER *TransferId){ RpcPktHdr *header; unsigned long header_size; RpcAddressString *server_address; RpcResults *results; RPC_SYNTAX_IDENTIFIER *transfer_id; header_size = sizeof(header->bind_ack) + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[strlen(ServerAddress) + 1]), 4) + sizeof(RpcResults) + sizeof(RPC_SYNTAX_IDENTIFIER); header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, header_size); if (header == NULL) { return NULL; } RPCRT4_BuildCommonHeader(header, PKT_BIND_ACK, DataRepresentation); header->common.frag_len = header_size; header->bind_ack.max_tsize = MaxTransmissionSize; header->bind_ack.max_rsize = MaxReceiveSize; server_address = (RpcAddressString*)(&header->bind_ack + 1); server_address->length = strlen(ServerAddress) + 1; strcpy(server_address->string, ServerAddress); /* results is 4-byte aligned */ results = (RpcResults*)((ULONG_PTR)server_address + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); results->num_results = 1; results->results[0].result = Result; results->results[0].reason = Reason; transfer_id = (RPC_SYNTAX_IDENTIFIER*)(results + 1); memcpy(transfer_id, TransferId, sizeof(RPC_SYNTAX_IDENTIFIER)); return header;}VOID RPCRT4_FreeHeader(RpcPktHdr *Header){ HeapFree(GetProcessHeap(), 0, Header);}NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status){ switch (status) { case ERROR_INVALID_HANDLE: return NCA_S_FAULT_CONTEXT_MISMATCH; case ERROR_OUTOFMEMORY: return NCA_S_FAULT_REMOTE_NO_MEMORY; case RPC_S_NOT_LISTENING: return NCA_S_SERVER_TOO_BUSY; case RPC_S_UNKNOWN_IF: return NCA_S_UNK_IF; case RPC_S_SERVER_TOO_BUSY: return NCA_S_SERVER_TOO_BUSY; case RPC_S_CALL_FAILED: return NCA_S_FAULT_UNSPEC; case RPC_S_CALL_FAILED_DNE: return NCA_S_MANAGER_NOT_ENTERED; case RPC_S_PROTOCOL_ERROR: return NCA_S_PROTO_ERROR; case RPC_S_UNSUPPORTED_TYPE: return NCA_S_UNSUPPORTED_TYPE; case RPC_S_INVALID_TAG: return NCA_S_FAULT_INVALID_TAG; case RPC_S_INVALID_BOUND: return NCA_S_FAULT_INVALID_BOUND; case RPC_S_PROCNUM_OUT_OF_RANGE: return NCA_S_OP_RNG_ERROR; case RPC_X_SS_HANDLES_MISMATCH: return NCA_S_FAULT_CONTEXT_MISMATCH; case STATUS_FLOAT_DIVIDE_BY_ZERO: return NCA_S_FAULT_FP_DIV_ZERO; case STATUS_FLOAT_INVALID_OPERATION: return NCA_S_FAULT_FP_ERROR; case STATUS_FLOAT_OVERFLOW: return NCA_S_FAULT_FP_OVERFLOW; case STATUS_FLOAT_UNDERFLOW: return NCA_S_FAULT_FP_UNDERFLOW; case STATUS_INTEGER_DIVIDE_BY_ZERO: return NCA_S_FAULT_INT_DIV_BY_ZERO; case STATUS_INTEGER_OVERFLOW: return NCA_S_FAULT_INT_OVERFLOW; default: return status; }}RPC_STATUS NCA2RPC_STATUS(NCA_STATUS status){ switch (status) { case NCA_S_COMM_FAILURE: return RPC_S_COMM_FAILURE; case NCA_S_OP_RNG_ERROR: return RPC_S_PROCNUM_OUT_OF_RANGE; case NCA_S_UNK_IF: return RPC_S_UNKNOWN_IF; case NCA_S_YOU_CRASHED: return RPC_S_CALL_FAILED; case NCA_S_PROTO_ERROR: return RPC_S_PROTOCOL_ERROR; case NCA_S_OUT_ARGS_TOO_BIG: return ERROR_NOT_ENOUGH_SERVER_MEMORY; case NCA_S_SERVER_TOO_BUSY: return RPC_S_SERVER_TOO_BUSY; case NCA_S_UNSUPPORTED_TYPE: return RPC_S_UNSUPPORTED_TYPE; case NCA_S_FAULT_INT_DIV_BY_ZERO: return RPC_S_ZERO_DIVIDE; case NCA_S_FAULT_ADDR_ERROR: return RPC_S_ADDRESS_ERROR; case NCA_S_FAULT_FP_DIV_ZERO: return RPC_S_FP_DIV_ZERO; case NCA_S_FAULT_FP_UNDERFLOW: return RPC_S_FP_UNDERFLOW; case NCA_S_FAULT_FP_OVERFLOW: return RPC_S_FP_OVERFLOW; case NCA_S_FAULT_INVALID_TAG: return RPC_S_INVALID_TAG; case NCA_S_FAULT_INVALID_BOUND: return RPC_S_INVALID_BOUND; case NCA_S_RPC_VERSION_MISMATCH: return RPC_S_PROTOCOL_ERROR; case NCA_S_UNSPEC_REJECT: return RPC_S_CALL_FAILED_DNE; case NCA_S_BAD_ACTID: return RPC_S_CALL_FAILED_DNE; case NCA_S_WHO_ARE_YOU_FAILED: return RPC_S_CALL_FAILED; case NCA_S_MANAGER_NOT_ENTERED: return RPC_S_CALL_FAILED_DNE; case NCA_S_FAULT_CANCEL: return RPC_S_CALL_CANCELLED; case NCA_S_FAULT_ILL_INST: return RPC_S_ADDRESS_ERROR; case NCA_S_FAULT_FP_ERROR: return RPC_S_FP_OVERFLOW; case NCA_S_FAULT_INT_OVERFLOW: return RPC_S_ADDRESS_ERROR; case NCA_S_FAULT_UNSPEC: return RPC_S_CALL_FAILED; case NCA_S_FAULT_PIPE_EMPTY: return RPC_X_PIPE_EMPTY; case NCA_S_FAULT_PIPE_CLOSED: return RPC_X_PIPE_CLOSED; case NCA_S_FAULT_PIPE_ORDER: return RPC_X_WRONG_PIPE_ORDER; case NCA_S_FAULT_PIPE_DISCIPLINE: return RPC_X_PIPE_DISCIPLINE_ERROR; case NCA_S_FAULT_PIPE_COMM_ERROR: return RPC_S_COMM_FAILURE; case NCA_S_FAULT_PIPE_MEMORY: return ERROR_OUTOFMEMORY; case NCA_S_FAULT_CONTEXT_MISMATCH: return ERROR_INVALID_HANDLE; case NCA_S_FAULT_REMOTE_NO_MEMORY: return ERROR_NOT_ENOUGH_SERVER_MEMORY; default: return status; }}static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection, enum secure_packet_direction dir, RpcPktHdr *hdr, unsigned int hdr_size, unsigned char *stub_data, unsigned int stub_data_size, RpcAuthVerifier *auth_hdr, unsigned char *auth_value, unsigned int auth_value_size){ SecBufferDesc message; SecBuffer buffers[4]; SECURITY_STATUS sec_status; message.ulVersion = SECBUFFER_VERSION; message.cBuffers = sizeof(buffers)/sizeof(buffers[0]); message.pBuffers = buffers; buffers[0].cbBuffer = hdr_size; buffers[0].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; buffers[0].pvBuffer = hdr; buffers[1].cbBuffer = stub_data_size; buffers[1].BufferType = SECBUFFER_DATA; buffers[1].pvBuffer = stub_data; buffers[2].cbBuffer = sizeof(*auth_hdr); buffers[2].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; buffers[2].pvBuffer = auth_hdr; buffers[3].cbBuffer = auth_value_size; buffers[3].BufferType = SECBUFFER_TOKEN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -