CVE-2015-5370: librpc/rpc: add a dcerpc_verify_ncacn_packet_header() helper function
authorStefan Metzmacher <metze@samba.org>
Fri, 26 Jun 2015 06:10:46 +0000 (08:10 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 30 Mar 2016 02:39:39 +0000 (04:39 +0200)
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>
librpc/rpc/dcerpc_util.c
librpc/rpc/rpc_common.h

index 8f0ebd01cfe97ce983d5b39d293e37d95eee8c0f..2f81447964fbc2b5462745c5bc1e80956775f885 100644 (file)
@@ -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 {
index f6434e7613d6a037e544bea462f154ad2fb88152..bd0985ad6a9b3a6e05892f978e68f70802484ff6 100644 (file)
@@ -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);