]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-isoclns.c
CVE-2017-13045/VQP: add some bounds checks
[tcpdump] / print-isoclns.c
index 2690d1b894775d686af157959c8ce9be1c6d8dbf..6285502845247c95ac3bb999bb934ccf99a84d2b 100644 (file)
@@ -20,7 +20,7 @@
  *
  * Original code by Matt Thomas, Digital Equipment Corporation
  *
- * Extensively modified by Hannes Gredler (hannes@juniper.net) for more
+ * Extensively modified by Hannes Gredler (hannes@gredler.at) for more
  * complete IS-IS & CLNP support.
  */
 
@@ -670,10 +670,9 @@ struct isis_tlv_lsp {
 #define ISIS_PSNP_HEADER_SIZE (sizeof(struct isis_psnp_header))
 
 void
-isoclns_print(netdissect_options *ndo,
-              const uint8_t *p, u_int length, u_int caplen)
+isoclns_print(netdissect_options *ndo, const uint8_t *p, u_int length)
 {
-       if (caplen <= 1) { /* enough bytes on the wire ? */
+       if (!ND_TTEST(*p)) { /* enough bytes on the wire ? */
                ND_PRINT((ndo, "|OSI"));
                return;
        }
@@ -685,7 +684,7 @@ isoclns_print(netdissect_options *ndo,
 
        case NLPID_CLNP:
                if (!clnp_print(ndo, p, length))
-                       print_unknown_data(ndo, p, "\n\t", caplen);
+                       print_unknown_data(ndo, p, "\n\t", length);
                break;
 
        case NLPID_ESIS:
@@ -694,7 +693,7 @@ isoclns_print(netdissect_options *ndo,
 
        case NLPID_ISIS:
                if (!isis_print(ndo, p, length))
-                       print_unknown_data(ndo, p, "\n\t", caplen);
+                       print_unknown_data(ndo, p, "\n\t", length);
                break;
 
        case NLPID_NULLNS:
@@ -721,8 +720,8 @@ isoclns_print(netdissect_options *ndo,
                if (!ndo->ndo_eflag)
                        ND_PRINT((ndo, "OSI NLPID 0x%02x unknown", *p));
                ND_PRINT((ndo, "%slength: %u", ndo->ndo_eflag ? "" : ", ", length));
-               if (caplen > 1)
-                       print_unknown_data(ndo, p, "\n\t", caplen);
+               if (length > 1)
+                       print_unknown_data(ndo, p, "\n\t", length);
                break;
        }
 }
@@ -1218,10 +1217,18 @@ esis_print(netdissect_options *ndo,
                pptr += netal;
                 li -= netal;
 
-               if (netal == 0)
-                       ND_PRINT((ndo, "\n\t  %s", etheraddr_string(ndo, snpa)));
+               if (snpal == 6)
+                       ND_PRINT((ndo, "\n\t  SNPA (length: %u): %s",
+                              snpal,
+                              etheraddr_string(ndo, snpa)));
                else
-                       ND_PRINT((ndo, "\n\t  %s", isonsap_string(ndo, neta, netal)));
+                       ND_PRINT((ndo, "\n\t  SNPA (length: %u): %s",
+                              snpal,
+                              linkaddr_string(ndo, snpa, LINKADDR_OTHER, snpal)));
+               if (netal != 0)
+                       ND_PRINT((ndo, "\n\t  NET (length: %u) %s",
+                              netal,
+                              isonsap_string(ndo, neta, netal)));
                break;
        }
 
@@ -1396,6 +1403,7 @@ isis_print_mt_port_cap_subtlv(netdissect_options *ndo,
 
   while (len > 2)
   {
+    ND_TCHECK2(*tptr, 2);
     stlv_type = *(tptr++);
     stlv_len  = *(tptr++);
 
@@ -1408,11 +1416,18 @@ isis_print_mt_port_cap_subtlv(netdissect_options *ndo,
     /*len -= TLV_TYPE_LEN_OFFSET;*/
     len = len -2;
 
+    /* Make sure the subTLV fits within the space left */
+    if (len < stlv_len)
+      goto trunc;
+    /* Make sure the entire subTLV is in the captured data */
+    ND_TCHECK2(*(tptr), stlv_len);
+
     switch (stlv_type)
     {
       case ISIS_SUBTLV_SPB_MCID:
       {
-        ND_TCHECK2(*(tptr), ISIS_SUBTLV_SPB_MCID_MIN_LEN);
+       if (stlv_len < ISIS_SUBTLV_SPB_MCID_MIN_LEN)
+         goto trunc;
 
         subtlv_spb_mcid = (const struct isis_subtlv_spb_mcid *)tptr;
 
@@ -1427,15 +1442,17 @@ isis_print_mt_port_cap_subtlv(netdissect_options *ndo,
 
           /*tptr += SPB_MCID_MIN_LEN;
             len -= SPB_MCID_MIN_LEN; */
-        tptr = tptr + sizeof(struct isis_subtlv_spb_mcid);
-        len = len - sizeof(struct isis_subtlv_spb_mcid);
+        tptr = tptr + ISIS_SUBTLV_SPB_MCID_MIN_LEN;
+        len = len - ISIS_SUBTLV_SPB_MCID_MIN_LEN;
+        stlv_len = stlv_len - ISIS_SUBTLV_SPB_MCID_MIN_LEN;
 
         break;
       }
 
       case ISIS_SUBTLV_SPB_DIGEST:
       {
-        ND_TCHECK2(*(tptr), ISIS_SUBTLV_SPB_DIGEST_MIN_LEN);
+        if (stlv_len < ISIS_SUBTLV_SPB_DIGEST_MIN_LEN)
+          goto trunc;
 
         ND_PRINT((ndo, "\n\t        RES: %d V: %d A: %d D: %d",
                         (*(tptr) >> 5), (((*tptr)>> 4) & 0x01),
@@ -1454,18 +1471,15 @@ isis_print_mt_port_cap_subtlv(netdissect_options *ndo,
         }
 
         len = len - ISIS_SUBTLV_SPB_DIGEST_MIN_LEN;
+        stlv_len = stlv_len - ISIS_SUBTLV_SPB_DIGEST_MIN_LEN;
 
         break;
       }
 
       case ISIS_SUBTLV_SPB_BVID:
       {
-        ND_TCHECK2(*(tptr), stlv_len);
-
-        while (len >= ISIS_SUBTLV_SPB_BVID_MIN_LEN)
+        while (stlv_len >= ISIS_SUBTLV_SPB_BVID_MIN_LEN)
         {
-          ND_TCHECK2(*(tptr), ISIS_SUBTLV_SPB_BVID_MIN_LEN);
-
           ND_PRINT((ndo, "\n\t           ECT: %08x",
                       EXTRACT_32BITS(tptr)));
 
@@ -1478,14 +1492,17 @@ isis_print_mt_port_cap_subtlv(netdissect_options *ndo,
 
           tptr = tptr + 2;
           len = len - ISIS_SUBTLV_SPB_BVID_MIN_LEN;
+          stlv_len = stlv_len - ISIS_SUBTLV_SPB_BVID_MIN_LEN;
         }
 
         break;
       }
 
       default:
-          break;
+        break;
     }
+    tptr += stlv_len;
+    len -= stlv_len;
   }
 
   return 0;
@@ -1504,6 +1521,7 @@ isis_print_mt_capability_subtlv(netdissect_options *ndo,
 
   while (len > 2)
   {
+    ND_TCHECK2(*tptr, 2);
     stlv_type = *(tptr++);
     stlv_len  = *(tptr++);
 
@@ -1515,11 +1533,17 @@ isis_print_mt_capability_subtlv(netdissect_options *ndo,
 
     len = len - 2;
 
+    /* Make sure the subTLV fits within the space left */
+    if (len < stlv_len)
+      goto trunc;
+    /* Make sure the entire subTLV is in the captured data */
+    ND_TCHECK2(*(tptr), stlv_len);
+
     switch (stlv_type)
     {
       case ISIS_SUBTLV_SPB_INSTANCE:
-
-          ND_TCHECK2(*tptr, ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN);
+          if (stlv_len < ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN)
+            goto trunc;
 
           ND_PRINT((ndo, "\n\t        CIST Root-ID: %08x", EXTRACT_32BITS(tptr)));
           tptr = tptr+4;
@@ -1541,10 +1565,12 @@ isis_print_mt_capability_subtlv(netdissect_options *ndo,
           tmp = *(tptr++);
 
           len = len - ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN;
+          stlv_len = stlv_len - ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN;
 
           while (tmp)
           {
-            ND_TCHECK2(*tptr, ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN);
+            if (stlv_len < ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN)
+              goto trunc;
 
             ND_PRINT((ndo, "\n\t         U:%d, M:%d, A:%d, RES:%d",
                       *(tptr) >> 7, (*(tptr) >> 6) & 0x01,
@@ -1562,14 +1588,15 @@ isis_print_mt_capability_subtlv(netdissect_options *ndo,
 
             tptr = tptr + 3;
             len = len - ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN;
+            stlv_len = stlv_len - ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN;
             tmp--;
           }
 
           break;
 
       case ISIS_SUBTLV_SPBM_SI:
-
-          ND_TCHECK2(*tptr, 8);
+          if (stlv_len < 8)
+            goto trunc;
 
           ND_PRINT((ndo, "\n\t        BMAC: %08x", EXTRACT_32BITS(tptr)));
           tptr = tptr+4;
@@ -1601,6 +1628,8 @@ isis_print_mt_capability_subtlv(netdissect_options *ndo,
       default:
         break;
     }
+    tptr += stlv_len;
+    len -= stlv_len;
   }
   return 0;
 
@@ -1617,8 +1646,12 @@ isis_print_id(const uint8_t *cp, int id_len)
     int i;
     static char id[sizeof("xxxx.xxxx.xxxx.yy-zz")];
     char *pos = id;
+    int sysid_len;
 
-    for (i = 1; i <= SYSTEM_ID_LEN; i++) {
+    sysid_len = SYSTEM_ID_LEN;
+    if (sysid_len > id_len)
+        sysid_len = id_len;
+    for (i = 1; i <= sysid_len; i++) {
         snprintf(pos, sizeof(id) - (pos - id), "%02x", *cp++);
        pos += strlen(pos);
        if (i == 2 || i == 4)
@@ -2039,7 +2072,7 @@ isis_print_extd_ip_reach(netdissect_options *ndo,
         }
         processed++;
     } else if (afi == AF_INET6) {
-        if (!ND_TTEST2(*tptr, 1)) /* fetch status & prefix_len byte */
+        if (!ND_TTEST2(*tptr, 2)) /* fetch status & prefix_len byte */
             return (0);
         status_byte=*(tptr++);
         bit_length=*(tptr++);
@@ -2200,7 +2233,7 @@ isis_print(netdissect_options *ndo,
     }
 
     if (isis_header->fixed_len < ISIS_COMMON_HEADER_SIZE) {
-       ND_PRINT((ndo, "fixed header length %u < minimum header size %u", isis_header->fixed_len, ISIS_COMMON_HEADER_SIZE));
+       ND_PRINT((ndo, "fixed header length %u < minimum header size %u", isis_header->fixed_len, (u_int)ISIS_COMMON_HEADER_SIZE));
        return (0);
     }
 
@@ -2533,6 +2566,7 @@ isis_print(netdissect_options *ndo,
            ND_TCHECK2(*tptr, 1);
            alen = *tptr++;
            while (tmp && alen < tmp) {
+               ND_TCHECK2(*tptr, alen);
                ND_PRINT((ndo, "\n\t      Area address (length: %u): %s",
                        alen,
                        isonsap_string(ndo, tptr, alen)));