From: Guy Harris Date: Mon, 28 Dec 2015 01:59:56 +0000 (-0800) Subject: Have signature_verify() do the copying and clearing. X-Git-Tag: tcpdump-4.8.0~51 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/59caec8a010375386ba91fb8a581f882912f2733 Have signature_verify() do the copying and clearing. 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. --- diff --git a/print-isoclns.c b/print-isoclns.c index e34e1dc6..5e4d58a2 100644 --- a/print-isoclns.c +++ b/print-isoclns.c @@ -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 diff --git a/print-rsvp.c b/print-rsvp.c index 71a04cd9..17263377 100644 --- a/print-rsvp.c +++ b/print-rsvp.c @@ -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; diff --git a/signature.c b/signature.c index b989baff..77ec493b 100644 --- a/signature.c +++ b/signature.c @@ -22,6 +22,7 @@ #include #include +#include #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])); } diff --git a/signature.h b/signature.h index 6df7227d..239ee3e8 100644 --- a/signature.h +++ b/signature.h @@ -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 *);