librpc/rpc: let dcerpc_pull_auth_trailer() check that auth_pad_length fits within...
authorStefan Metzmacher <metze@samba.org>
Mon, 20 Jun 2016 14:25:12 +0000 (16:25 +0200)
committerKarolin Seeger <kseeger@samba.org>
Thu, 4 Aug 2016 08:59:19 +0000 (10:59 +0200)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11982

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 3f7e3ed8a276f16aaed87c1f3cd5b9781aa7e1af)

librpc/rpc/dcerpc_util.c

index 4d82e9a53a975c9af42b13734b4c9d4d113cd638..ee7b30779c467ae519077a9a7f27f1a9033460a2 100644 (file)
@@ -95,6 +95,7 @@ NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
        uint16_t data_and_pad;
        uint16_t auth_length;
        uint32_t tmp_length;
+       uint32_t max_pad_len = 0;
 
        ZERO_STRUCTP(auth);
        if (_auth_length != NULL) {
@@ -157,6 +158,42 @@ NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
                return ndr_map_error2ntstatus(ndr_err);
        }
 
+       /*
+        * Make sure the padding would not exceed
+        * the frag_length.
+        *
+        * Here we assume at least 24 bytes for the
+        * payload specific header the value of
+        * DCERPC_{REQUEST,RESPONSE}_LENGTH.
+        *
+        * We use this also for BIND_*, ALTER_* and AUTH3 pdus.
+        *
+        * We need this check before we ignore possible
+        * invalid values. See also bug #11982.
+        *
+        * This check is mainly used to generate the correct
+        * error for BIND_*, ALTER_* and AUTH3 pdus.
+        *
+        * We always have the 'if (data_and_pad < auth->auth_pad_length)'
+        * protection for REQUEST and RESPONSE pdus, where the
+        * auth_pad_length field is actually used by the caller.
+        */
+       tmp_length = DCERPC_REQUEST_LENGTH;
+       tmp_length += DCERPC_AUTH_TRAILER_LENGTH;
+       tmp_length += pkt->auth_length;
+       if (tmp_length < pkt->frag_length) {
+               max_pad_len = pkt->frag_length - tmp_length;
+       }
+       if (max_pad_len < auth->auth_pad_length) {
+               DEBUG(1, (__location__ ": ERROR: pad length to large. "
+                         "max %u got %u\n",
+                         (unsigned)max_pad_len,
+                         (unsigned)auth->auth_pad_length));
+               talloc_free(ndr);
+               ZERO_STRUCTP(auth);
+               return NT_STATUS_RPC_PROTOCOL_ERROR;
+       }
+
        if (data_and_pad < auth->auth_pad_length) {
                DEBUG(1, (__location__ ": ERROR: pad length mismatch. "
                          "Calculated %u  got %u\n",