summaryrefslogtreecommitdiff
path: root/librpc/rpc
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2015-06-26 08:10:46 +0200
committerStefan Metzmacher <metze@samba.org>2016-04-12 19:25:29 +0200
commit0fa8378fc51a030efc9a6bf566681b1a398d8acc (patch)
tree21bad21cadc6c156fddb0abec1b07e0e6eac90c1 /librpc/rpc
parentcdba091867061a9ed805f02a170938fa7de85e7e (diff)
downloadsamba-0fa8378fc51a030efc9a6bf566681b1a398d8acc.tar.gz
CVE-2015-5370: librpc/rpc: add a dcerpc_verify_ncacn_packet_header() helper function
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11344 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Günther Deschner <gd@samba.org>
Diffstat (limited to 'librpc/rpc')
-rw-r--r--librpc/rpc/dcerpc_util.c73
-rw-r--r--librpc/rpc/rpc_common.h5
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);