]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Have signature_verify() do the copying and clearing.
authorGuy Harris <[email protected]>
Mon, 28 Dec 2015 01:59:56 +0000 (17:59 -0800)
committerGuy Harris <[email protected]>
Mon, 28 Dec 2015 01:59:56 +0000 (17:59 -0800)
Just pass it a pointer to a routine to do the clearing and a pointer to
the data that needs to be cleared; signature_verify() will relocate all
pointers to stuff that needs to be cleared to point into the copy, clear
the signature itself, and call the routine to clear anything else.

print-isoclns.c
print-rsvp.c
signature.c
signature.h

index e34e1dc6b0622fb0bfd0246a107a49a9f0444f6e..5e4d58a20aab537b15aef5e3d2c77dc12bc85173 100644 (file)
@@ -2051,6 +2051,20 @@ isis_print_extd_ip_reach(netdissect_options *ndo,
     return (processed);
 }
 
+/*
+ * Clear checksum and lifetime prior to signature verification.
+ */
+static void
+isis_clear_checksum_lifetime(void *header)
+{
+    struct isis_lsp_header *header_lsp = (struct isis_lsp_header *) header;
+
+    header_lsp->checksum[0] = 0;
+    header_lsp->checksum[1] = 0;
+    header_lsp->remaining_lifetime[0] = 0;
+    header_lsp->remaining_lifetime[1] = 0;
+}
+
 /*
  * isis_print
  * Decode IS-IS packets.  Return 0 on error.
@@ -2079,9 +2093,6 @@ isis_print(netdissect_options *ndo,
     u_short packet_len,pdu_len, key_id;
     u_int i,vendor_id;
     int sigcheck;
-#ifdef HAVE_LIBCRYPTO
-    uint8_t *packet_copy;
-#endif
 
     packet_len=length;
     optr = p; /* initialize the _o_riginal pointer to the packet start -
@@ -2658,35 +2669,9 @@ isis_print(netdissect_options *ndo,
                     ND_PRINT((ndo, ", (invalid subTLV) "));
 
 #ifdef HAVE_LIBCRYPTO
-                /*
-                 * Make a copy of the packet, so we don't overwrite the
-                 * original.
-                 */
-                ND_TCHECK2(*optr, packet_len);
-                packet_copy = malloc(packet_len);
-                if (packet_copy == NULL)
-                    sigcheck = CANT_ALLOCATE_COPY;
-                else {
-                    struct isis_lsp_header *header_lsp_copy;
-                    u_int8_t *tptr_copy;
-
-                    memcpy(packet_copy, optr, packet_len);
-
-                    /*
-                     * Clear checksum and lifetime in the copy prior to
-                     * signature verification.
-                     */
-                    header_lsp_copy = (struct isis_lsp_header *)(packet_copy + ISIS_COMMON_HEADER_SIZE);
-                    header_lsp_copy->checksum[0] = 0;
-                    header_lsp_copy->checksum[1] = 0;
-                    header_lsp_copy->remaining_lifetime[0] = 0;
-                    header_lsp_copy->remaining_lifetime[1] = 0;
-
-                    tptr_copy = packet_copy + (tptr - optr);
-                    sigcheck = signature_verify(ndo, packet_copy, length,
-                                                tptr_copy + 1);
-                    free(packet_copy);
-                }
+                sigcheck = signature_verify(ndo, optr, length, tptr + 1,
+                                            isis_clear_checksum_lifetime,
+                                            header_lsp);
 #else
                 sigcheck = CANT_CHECK_SIGNATURE;
 #endif
index 71a04cd92d1140890e293bc611dc19b072ef0a88..1726337736d347f59f7608c839c37d51f0e7f949 100644 (file)
@@ -640,6 +640,18 @@ trunc:
     return 0;
 }
 
+/*
+ * Clear checksum prior to signature verification.
+ */
+static void
+rsvp_clear_checksum(void *header)
+{
+    struct rsvp_common_header *rsvp_com_header = (struct rsvp_common_header *) header;
+
+    rsvp_com_header->checksum[0] = 0;
+    rsvp_com_header->checksum[1] = 0;
+}
+
 static int
 rsvp_obj_print(netdissect_options *ndo,
                const u_char *pptr
@@ -651,7 +663,12 @@ _U_
 _U_
 #endif
 , const u_char *tptr,
-                const char *ident, u_int tlen)
+                const char *ident, u_int tlen,
+                const struct rsvp_common_header *rsvp_com_header
+#ifndef HAVE_LIBCRYPTO
+_U_
+#endif
+)
 {
     const struct rsvp_object_header *rsvp_obj_header;
     const u_char *obj_tptr;
@@ -1666,8 +1683,10 @@ _U_
                        EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest + 12)));
 
 #ifdef HAVE_LIBCRYPTO
-                sigcheck = signature_verify(ndo, pptr, plen, (unsigned char *)obj_ptr.\
-                                             rsvp_obj_integrity->digest);
+                sigcheck = signature_verify(ndo, pptr, plen,
+                                            obj_ptr.rsvp_obj_integrity->digest,
+                                            rsvp_clear_checksum,
+                                            rsvp_com_header);
 #else
                 sigcheck = CANT_CHECK_SIGNATURE;
 #endif
@@ -1800,13 +1819,13 @@ void
 rsvp_print(netdissect_options *ndo,
            register const u_char *pptr, register u_int len)
 {
-    struct rsvp_common_header *rsvp_com_header;
+    const struct rsvp_common_header *rsvp_com_header;
     const u_char *tptr,*subtptr;
     u_short plen, tlen, subtlen;
 
     tptr=pptr;
 
-    rsvp_com_header = (struct rsvp_common_header *)pptr;
+    rsvp_com_header = (const struct rsvp_common_header *)pptr;
     ND_TCHECK(*rsvp_com_header);
 
     /*
@@ -1840,12 +1859,6 @@ rsvp_print(netdissect_options *ndo,
            rsvp_com_header->ttl,
            EXTRACT_16BITS(rsvp_com_header->checksum)));
 
-    /*
-     * Clear checksum prior to signature verification.
-     */
-    rsvp_com_header->checksum[0] = 0;
-    rsvp_com_header->checksum[1] = 0;
-
     if (tlen < sizeof(const struct rsvp_common_header)) {
         ND_PRINT((ndo, "ERROR: common header too short %u < %lu", tlen,
                (unsigned long)sizeof(const struct rsvp_common_header)));
@@ -1860,7 +1873,7 @@ rsvp_print(netdissect_options *ndo,
     case RSVP_MSGTYPE_AGGREGATE:
         while(tlen > 0) {
             subtptr=tptr;
-            rsvp_com_header = (struct rsvp_common_header *)subtptr;
+            rsvp_com_header = (const struct rsvp_common_header *)subtptr;
             ND_TCHECK(*rsvp_com_header);
 
             /*
@@ -1882,12 +1895,6 @@ rsvp_print(netdissect_options *ndo,
                    rsvp_com_header->ttl,
                    EXTRACT_16BITS(rsvp_com_header->checksum)));
 
-            /*
-             * Clear checksum prior to signature verification.
-             */
-            rsvp_com_header->checksum[0] = 0;
-            rsvp_com_header->checksum[1] = 0;
-
             if (subtlen < sizeof(const struct rsvp_common_header)) {
                 ND_PRINT((ndo, "ERROR: common header too short %u < %lu", subtlen,
                        (unsigned long)sizeof(const struct rsvp_common_header)));
@@ -1903,7 +1910,7 @@ rsvp_print(netdissect_options *ndo,
             subtptr+=sizeof(const struct rsvp_common_header);
             subtlen-=sizeof(const struct rsvp_common_header);
 
-            if (rsvp_obj_print(ndo, pptr, plen, subtptr, "\n\t    ", subtlen) == -1)
+            if (rsvp_obj_print(ndo, pptr, plen, subtptr, "\n\t    ", subtlen, rsvp_com_header) == -1)
                 return;
 
             tptr+=subtlen+sizeof(const struct rsvp_common_header);
@@ -1923,7 +1930,7 @@ rsvp_print(netdissect_options *ndo,
     case RSVP_MSGTYPE_HELLO:
     case RSVP_MSGTYPE_ACK:
     case RSVP_MSGTYPE_SREFRESH:
-        if (rsvp_obj_print(ndo, pptr, plen, tptr, "\n\t  ", tlen) == -1)
+        if (rsvp_obj_print(ndo, pptr, plen, tptr, "\n\t  ", tlen, rsvp_com_header) == -1)
             return;
         break;
 
index b989baff19305cb09f031ec65a49ba809747fc9b..77ec493b7db6baffac40632b9dec8a51693afefe 100644 (file)
@@ -22,6 +22,7 @@
 #include <netdissect-stdinc.h>
 
 #include <string.h>
+#include <stdlib.h>
 
 #include "netdissect.h"
 #include "signature.h"
@@ -116,31 +117,80 @@ USES_APPLE_RST
  * Currently only MD5 is supported.
  */
 int
-signature_verify(netdissect_options *ndo,
-                 const u_char *pptr, u_int plen, u_char *sig_ptr)
+signature_verify(netdissect_options *ndo, const u_char *pptr, u_int plen,
+                 const u_char *sig_ptr, void (*clear_rtn)(void *),
+                 const void *clear_arg)
 {
-    uint8_t rcvsig[16];
+    uint8_t *packet_copy, *sig_copy;
     uint8_t sig[16];
     unsigned int i;
 
+    if (!ndo->ndo_sigsecret) {
+        return (CANT_CHECK_SIGNATURE);
+    }
+
     /*
-     * Save the signature before clearing it.
+     * Do we have all the packet data to be checked?
      */
-    memcpy(rcvsig, sig_ptr, sizeof(rcvsig));
-    memset(sig_ptr, 0, sizeof(rcvsig));
+    if (!ND_TTEST2(pptr, plen)) {
+        /* No. */
+        return (CANT_CHECK_SIGNATURE);
+    }
 
-    if (!ndo->ndo_sigsecret) {
+    /*
+     * Do we have the entire signature to check?
+     */
+    if (!ND_TTEST2(sig_ptr, sizeof(sig))) {
+        /* No. */
+        return (CANT_CHECK_SIGNATURE);
+    }
+    if ((sig_ptr + sizeof(sig) - pptr) > plen) {
+        /* No. */
         return (CANT_CHECK_SIGNATURE);
     }
 
-    signature_compute_hmac_md5(pptr, plen, (unsigned char *)ndo->ndo_sigsecret,
+    /*
+     * Make a copy of the packet, so we don't overwrite the original.
+     */
+    packet_copy = malloc(plen);
+    if (packet_copy == NULL) {
+        return (CANT_ALLOCATE_COPY);
+    }
+
+    memcpy(packet_copy, pptr, plen);
+
+    /*
+     * Clear the signature in the copy.
+     */
+    sig_copy = packet_copy + (sig_ptr - pptr);
+    memset(sig_copy, 0, sizeof(sig));
+
+    /*
+     * Clear anything else that needs to be cleared in the copy.
+     * Our caller is assumed to have vetted the clear_arg pointer.
+     */
+    (*clear_rtn)((void *)(packet_copy + ((const u_int8_t *)clear_arg - pptr)));
+
+    /*
+     * Compute the signature.
+     */
+    signature_compute_hmac_md5(packet_copy, plen,
+                               (unsigned char *)ndo->ndo_sigsecret,
                                strlen(ndo->ndo_sigsecret), sig);
 
-    if (memcmp(rcvsig, sig, sizeof(sig)) == 0) {
-        return (SIGNATURE_VALID);
+    /*
+     * Free the copy.
+     */
+    free(packet_copy);
 
+    /*
+     * Does the computed signature match the signature in the packet?
+     */
+    if (memcmp(sig_ptr, sig, sizeof(sig)) == 0) {
+        /* Yes. */
+        return (SIGNATURE_VALID);
     } else {
-
+        /* No - print the computed signature. */
         for (i = 0; i < sizeof(sig); ++i) {
             ND_PRINT((ndo, "%02x", sig[i]));
         }
index 6df7227d7c9fdbd4b7cd0ec9de83521ff9a00e7c..239ee3e8db0b076faa640b4e5e02c90f3f38dfe2 100644 (file)
@@ -25,4 +25,5 @@
 #define CANT_CHECK_SIGNATURE   3
 
 extern const struct tok signature_check_values[];
-extern int signature_verify(netdissect_options *, const u_char *, u_int, u_char *);
+extern int signature_verify(netdissect_options *, const u_char *, u_int,
+                            const u_char *, void (*)(void *), const void *);