📄 rpc_message.c
字号:
buffers[3].pvBuffer = auth_value; if (dir == SECURE_PACKET_SEND) { if ((auth_hdr->auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(hdr)) { sec_status = EncryptMessage(&Connection->ctx, 0, &message, 0 /* FIXME */); if (sec_status != SEC_E_OK) { ERR("EncryptMessage failed with 0x%08x\n", sec_status); return RPC_S_SEC_PKG_ERROR; } } else if (auth_hdr->auth_level != RPC_C_AUTHN_LEVEL_NONE) { sec_status = MakeSignature(&Connection->ctx, 0, &message, 0 /* FIXME */); if (sec_status != SEC_E_OK) { ERR("MakeSignature failed with 0x%08x\n", sec_status); return RPC_S_SEC_PKG_ERROR; } } } else if (dir == SECURE_PACKET_RECEIVE) { if ((auth_hdr->auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(hdr)) { sec_status = DecryptMessage(&Connection->ctx, &message, 0 /* FIXME */, 0); if (sec_status != SEC_E_OK) { ERR("EncryptMessage failed with 0x%08x\n", sec_status); return RPC_S_SEC_PKG_ERROR; } } else if (auth_hdr->auth_level != RPC_C_AUTHN_LEVEL_NONE) { sec_status = VerifySignature(&Connection->ctx, &message, 0 /* FIXME */, NULL); if (sec_status != SEC_E_OK) { ERR("VerifySignature failed with 0x%08x\n", sec_status); return RPC_S_SEC_PKG_ERROR; } } } return RPC_S_OK;} /*********************************************************************** * RPCRT4_SendAuth (internal) * * Transmit a packet with authorization data over connection in acceptable fragments. */static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength, void *Auth, unsigned int AuthLength){ PUCHAR buffer_pos; DWORD hdr_size; LONG count; unsigned char *pkt; LONG alen; RPC_STATUS status; buffer_pos = Buffer; /* The packet building functions save the packet header size, so we can use it. */ hdr_size = Header->common.frag_len; if (AuthLength) Header->common.auth_len = AuthLength; else if (Connection->AuthInfo && packet_has_auth_verifier(Header)) { if ((Connection->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(Header)) Header->common.auth_len = Connection->encryption_auth_len; else Header->common.auth_len = Connection->signature_auth_len; } else Header->common.auth_len = 0; Header->common.flags |= RPC_FLG_FIRST; Header->common.flags &= ~RPC_FLG_LAST; alen = RPC_AUTH_VERIFIER_LEN(&Header->common); while (!(Header->common.flags & RPC_FLG_LAST)) { unsigned char auth_pad_len = Header->common.auth_len ? ROUND_UP_AMOUNT(BufferLength, AUTH_ALIGNMENT) : 0; unsigned int pkt_size = BufferLength + hdr_size + alen + auth_pad_len; /* decide if we need to split the packet into fragments */ if (pkt_size <= Connection->MaxTransmissionSize) { Header->common.flags |= RPC_FLG_LAST; Header->common.frag_len = pkt_size; } else { auth_pad_len = 0; /* make sure packet payload will be a multiple of 16 */ Header->common.frag_len = ((Connection->MaxTransmissionSize - hdr_size - alen) & ~(AUTH_ALIGNMENT-1)) + hdr_size + alen; } pkt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Header->common.frag_len); memcpy(pkt, Header, hdr_size); /* fragment consisted of header only and is the last one */ if (hdr_size == Header->common.frag_len) goto write; memcpy(pkt + hdr_size, buffer_pos, Header->common.frag_len - hdr_size - auth_pad_len - alen); /* add the authorization info */ if (Connection->AuthInfo && packet_has_auth_verifier(Header)) { RpcAuthVerifier *auth_hdr = (RpcAuthVerifier *)&pkt[Header->common.frag_len - alen]; auth_hdr->auth_type = Connection->AuthInfo->AuthnSvc; auth_hdr->auth_level = Connection->AuthInfo->AuthnLevel; auth_hdr->auth_pad_length = auth_pad_len; auth_hdr->auth_reserved = 0; /* a unique number... */ auth_hdr->auth_context_id = (unsigned long)Connection; if (AuthLength) memcpy(auth_hdr + 1, Auth, AuthLength); else { status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_SEND, (RpcPktHdr *)pkt, hdr_size, pkt + hdr_size, Header->common.frag_len - hdr_size - alen, auth_hdr, (unsigned char *)(auth_hdr + 1), Header->common.auth_len); if (status != RPC_S_OK) { HeapFree(GetProcessHeap(), 0, pkt); return status; } } }write: count = rpcrt4_conn_write(Connection, pkt, Header->common.frag_len); HeapFree(GetProcessHeap(), 0, pkt); if (count<0) { WARN("rpcrt4_conn_write failed (auth)\n"); return RPC_S_PROTOCOL_ERROR; } buffer_pos += Header->common.frag_len - hdr_size - alen - auth_pad_len; BufferLength -= Header->common.frag_len - hdr_size - alen - auth_pad_len; Header->common.flags &= ~RPC_FLG_FIRST; } return RPC_S_OK;}/*********************************************************************** * RPCRT4_ClientAuthorize (internal) * * Authorize a client connection. A NULL in param signifies a new connection. */static RPC_STATUS RPCRT4_ClientAuthorize(RpcConnection *conn, SecBuffer *in, SecBuffer *out){ SECURITY_STATUS r; SecBufferDesc out_desc; SecBufferDesc inp_desc; SecPkgContext_Sizes secctx_sizes; BOOL continue_needed; ULONG context_req = ISC_REQ_CONNECTION | ISC_REQ_USE_DCE_STYLE | ISC_REQ_MUTUAL_AUTH | ISC_REQ_DELEGATE; if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) context_req |= ISC_REQ_INTEGRITY; else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) context_req |= ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY; out->BufferType = SECBUFFER_TOKEN; out->cbBuffer = conn->AuthInfo->cbMaxToken; out->pvBuffer = HeapAlloc(GetProcessHeap(), 0, out->cbBuffer); if (!out->pvBuffer) return ERROR_OUTOFMEMORY; out_desc.ulVersion = 0; out_desc.cBuffers = 1; out_desc.pBuffers = out; inp_desc.cBuffers = 1; inp_desc.pBuffers = in; inp_desc.ulVersion = 0; r = InitializeSecurityContextA(&conn->AuthInfo->cred, in ? &conn->ctx : NULL, NULL, context_req, 0, SECURITY_NETWORK_DREP, in ? &inp_desc : NULL, 0, &conn->ctx, &out_desc, &conn->attr, &conn->exp); if (FAILED(r)) { WARN("InitializeSecurityContext failed with error 0x%08x\n", r); goto failed; } TRACE("r = 0x%08x, attr = 0x%08x\n", r, conn->attr); continue_needed = ((r == SEC_I_CONTINUE_NEEDED) || (r == SEC_I_COMPLETE_AND_CONTINUE)); if ((r == SEC_I_COMPLETE_NEEDED) || (r == SEC_I_COMPLETE_AND_CONTINUE)) { TRACE("complete needed\n"); r = CompleteAuthToken(&conn->ctx, &out_desc); if (FAILED(r)) { WARN("CompleteAuthToken failed with error 0x%08x\n", r); goto failed; } } TRACE("cbBuffer = %ld\n", out->cbBuffer); if (!continue_needed) { r = QueryContextAttributesA(&conn->ctx, SECPKG_ATTR_SIZES, &secctx_sizes); if (FAILED(r)) { WARN("QueryContextAttributes failed with error 0x%08x\n", r); goto failed; } conn->signature_auth_len = secctx_sizes.cbMaxSignature; conn->encryption_auth_len = secctx_sizes.cbSecurityTrailer; } return RPC_S_OK;failed: HeapFree(GetProcessHeap(), 0, out->pvBuffer); out->pvBuffer = NULL; return ERROR_ACCESS_DENIED; /* FIXME: is this correct? */}/*********************************************************************** * RPCRT4_AuthorizeBinding (internal) */static RPC_STATUS RPCRT_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, ULONG count){ SecBuffer inp, out; RpcPktHdr *resp_hdr; RPC_STATUS status; TRACE("challenge %s, %d bytes\n", challenge, count); inp.BufferType = SECBUFFER_TOKEN; inp.pvBuffer = challenge; inp.cbBuffer = count; status = RPCRT4_ClientAuthorize(conn, &inp, &out); if (status) return status; resp_hdr = RPCRT4_BuildAuthHeader(NDR_LOCAL_DATA_REPRESENTATION); if (!resp_hdr) return E_OUTOFMEMORY; status = RPCRT4_SendAuth(conn, resp_hdr, NULL, 0, out.pvBuffer, out.cbBuffer); HeapFree(GetProcessHeap(), 0, out.pvBuffer); RPCRT4_FreeHeader(resp_hdr); return status;}/*********************************************************************** * RPCRT4_Send (internal) * * Transmit a packet over connection in acceptable fragments. */RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength){ RPC_STATUS r; SecBuffer out; if (!Connection->AuthInfo || SecIsValidHandle(&Connection->ctx)) { return RPCRT4_SendAuth(Connection, Header, Buffer, BufferLength, NULL, 0); } /* tack on a negotiate packet */ RPCRT4_ClientAuthorize(Connection, NULL, &out); r = RPCRT4_SendAuth(Connection, Header, Buffer, BufferLength, out.pvBuffer, out.cbBuffer); HeapFree(GetProcessHeap(), 0, out.pvBuffer); return r;}/*********************************************************************** * RPCRT4_Receive (internal) * * Receive a packet from connection and merge the fragments. */RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg){ RPC_STATUS status; DWORD hdr_length; LONG dwRead; unsigned short first_flag; unsigned long data_length; unsigned long buffer_length; unsigned long auth_length; unsigned char *auth_data = NULL; RpcPktCommonHdr common_hdr; *Header = NULL; TRACE("(%p, %p, %p)\n", Connection, Header, pMsg); /* read packet common header */ dwRead = rpcrt4_conn_read(Connection, &common_hdr, sizeof(common_hdr)); if (dwRead != sizeof(common_hdr)) { WARN("Short read of header, %d bytes\n", dwRead); status = RPC_S_PROTOCOL_ERROR; goto fail; } /* verify if the header really makes sense */ if (common_hdr.rpc_ver != RPC_VER_MAJOR || common_hdr.rpc_ver_minor != RPC_VER_MINOR) { WARN("unhandled packet version\n"); status = RPC_S_PROTOCOL_ERROR; goto fail; } hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr); if (hdr_length == 0) { WARN("header length == 0\n"); status = RPC_S_PROTOCOL_ERROR; goto fail; } *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length); memcpy(*Header, &common_hdr, sizeof(common_hdr)); /* read the rest of packet header */ dwRead = rpcrt4_conn_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr)); if (dwRead != hdr_length - sizeof(common_hdr)) { WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length); status = RPC_S_PROTOCOL_ERROR; goto fail; } /* read packet body */ switch (common_hdr.ptype) { case PKT_RESPONSE: pMsg->BufferLength = (*Header)->response.alloc_hint; break; case PKT_REQUEST: pMsg->BufferLength = (*Header)->request.alloc_hint; break; default: pMsg->BufferLength = common_hdr.frag_len - hdr_length - RPC_AUTH_VERIFIER_LEN(&common_hdr); } TRACE("buffer length = %u\n", pMsg->BufferLength); status = I_RpcGetBuffer(pMsg); if (status != RPC_S_OK) goto fail; first_flag = RPC_FLG_FIRST; auth_length = common_hdr.auth_len; if (auth_length) { auth_data = HeapAlloc(GetProcessHeap(), 0, RPC_AUTH_VERIFIER_LEN(&common_hdr)); if (!auth_data) { status = RPC_S_PROTOCOL_ERROR; goto fail; } } buffer_length = 0; while (TRUE) { unsigned int header_auth_len = RPC_AUTH_VERIFIER_LEN(&(*Header)->common); /* verify header fields */ if (((*Header)->common.frag_len < hdr_length) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -