diff options
-rw-r--r-- | librpc/rpc/dcerpc_util.c | 73 | ||||
-rw-r--r-- | librpc/rpc/rpc_common.h | 5 |
2 files changed, 78 insertions, 0 deletions
diff --git a/librpc/rpc/dcerpc_util.c b/librpc/rpc/dcerpc_util.c index 8f0ebd01cfe..2f81447964f 100644 --- a/librpc/rpc/dcerpc_util.c +++ b/librpc/rpc/dcerpc_util.c @@ -177,6 +177,79 @@ NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt, return NT_STATUS_OK; } +/** +* @brief Verify the fields in ncacn_packet header. +* +* @param pkt - The ncacn_packet strcuture +* @param ptype - The expected PDU type +* @param max_auth_info - The maximum size of a possible auth trailer +* @param required_flags - The required flags for the pdu. +* @param optional_flags - The possible optional flags for the pdu. +* +* @return - A NTSTATUS error code. +*/ +NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt, + enum dcerpc_pkt_type ptype, + size_t max_auth_info, + uint8_t required_flags, + uint8_t optional_flags) +{ + if (pkt->rpc_vers != 5) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + + if (pkt->rpc_vers_minor != 0) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + + if (pkt->auth_length > pkt->frag_length) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + + if (pkt->ptype != ptype) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + + if (max_auth_info > UINT16_MAX) { + return NT_STATUS_INTERNAL_ERROR; + } + + if (pkt->auth_length > 0) { + size_t max_auth_length; + + if (max_auth_info <= DCERPC_AUTH_TRAILER_LENGTH) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + max_auth_length = max_auth_info - DCERPC_AUTH_TRAILER_LENGTH; + + if (pkt->auth_length > max_auth_length) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + } + + if ((pkt->pfc_flags & required_flags) != required_flags) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + if (pkt->pfc_flags & ~(optional_flags|required_flags)) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + + if (pkt->drep[0] & ~DCERPC_DREP_LE) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + if (pkt->drep[1] != 0) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + if (pkt->drep[2] != 0) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + if (pkt->drep[3] != 0) { + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + + return NT_STATUS_OK; +} + struct dcerpc_read_ncacn_packet_state { #if 0 struct { diff --git a/librpc/rpc/rpc_common.h b/librpc/rpc/rpc_common.h index f6434e7613d..bd0985ad6a9 100644 --- a/librpc/rpc/rpc_common.h +++ b/librpc/rpc/rpc_common.h @@ -193,6 +193,11 @@ NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt, struct dcerpc_auth *auth, uint32_t *auth_length, bool auth_data_only); +NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt, + enum dcerpc_pkt_type ptype, + size_t max_auth_info, + uint8_t required_flags, + uint8_t optional_flags); struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct tstream_context *stream); |