From: Guy Harris Date: Mon, 28 Dec 2015 00:58:52 +0000 (-0800) Subject: Don't overwrite packet data when checking the signature. X-Git-Tag: tcpdump-4.8.0~52 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/20f164f5e4825a605d97906b9ac6bf4222b9eef4 Don't overwrite packet data when checking the signature. Instead, make a copy, and overwrite that. --- diff --git a/print-isoclns.c b/print-isoclns.c index 08be550d..e34e1dc6 100644 --- a/print-isoclns.c +++ b/print-isoclns.c @@ -31,6 +31,7 @@ #include #include +#include #include "netdissect.h" #include "addrtoname.h" @@ -2063,7 +2064,7 @@ isis_print(netdissect_options *ndo, const struct isis_iih_lan_header *header_iih_lan; const struct isis_iih_ptp_header *header_iih_ptp; - struct isis_lsp_header *header_lsp; + const struct isis_lsp_header *header_lsp; const struct isis_csnp_header *header_csnp; const struct isis_psnp_header *header_psnp; @@ -2078,6 +2079,9 @@ 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 - @@ -2088,7 +2092,7 @@ isis_print(netdissect_options *ndo, pptr = p+(ISIS_COMMON_HEADER_SIZE); header_iih_lan = (const struct isis_iih_lan_header *)pptr; header_iih_ptp = (const struct isis_iih_ptp_header *)pptr; - header_lsp = (struct isis_lsp_header *)pptr; + header_lsp = (const struct isis_lsp_header *)pptr; header_csnp = (const struct isis_csnp_header *)pptr; header_psnp = (const struct isis_psnp_header *)pptr; @@ -2315,19 +2319,11 @@ isis_print(netdissect_options *ndo, EXTRACT_16BITS(header_lsp->remaining_lifetime), EXTRACT_16BITS(header_lsp->checksum))); - if (osi_print_cksum(ndo, (uint8_t *)header_lsp->lsp_id, + if (osi_print_cksum(ndo, (const uint8_t *)header_lsp->lsp_id, EXTRACT_16BITS(header_lsp->checksum), 12, length-12) == 0) goto trunc; - /* - * Clear checksum and lifetime prior to signature verification. - */ - header_lsp->checksum[0] = 0; - header_lsp->checksum[1] = 0; - header_lsp->remaining_lifetime[0] = 0; - header_lsp->remaining_lifetime[1] = 0; - ND_PRINT((ndo, ", PDU length: %u, Flags: [ %s", pdu_len, ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : "")); @@ -2662,8 +2658,35 @@ isis_print(netdissect_options *ndo, ND_PRINT((ndo, ", (invalid subTLV) ")); #ifdef HAVE_LIBCRYPTO - sigcheck = signature_verify(ndo, optr, length, - (unsigned char *)tptr + 1); + /* + * 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); + } #else sigcheck = CANT_CHECK_SIGNATURE; #endif diff --git a/signature.c b/signature.c index 18449fc2..b989baff 100644 --- a/signature.c +++ b/signature.c @@ -33,6 +33,7 @@ const struct tok signature_check_values[] = { { SIGNATURE_VALID, "valid"}, { SIGNATURE_INVALID, "invalid"}, + { CANT_ALLOCATE_COPY, "can't allocate memory"}, { CANT_CHECK_SIGNATURE, "unchecked"}, { 0, NULL } }; diff --git a/signature.h b/signature.h index a052df86..6df7227d 100644 --- a/signature.h +++ b/signature.h @@ -21,7 +21,8 @@ /* signature checking result codes */ #define SIGNATURE_VALID 0 #define SIGNATURE_INVALID 1 -#define CANT_CHECK_SIGNATURE 2 +#define CANT_ALLOCATE_COPY 2 +#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 *);