]> The Tcpdump Group git mirrors - tcpdump/blobdiff - signature.c
Handle very large -f files by rejecting them.
[tcpdump] / signature.c
index b2a7084a899073378f68f96ef4c921c968032382..204e3456e2d47fa36b089f08f845ecffd8385765 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that: (1) source code
  * distributions retain the above copyright notice and this paragraph
  * FOR A PARTICULAR PURPOSE.
  *
  * Functions for signature and digest verification.
- * 
- * Original code by Hannes Gredler (hannes@juniper.net)
+ *
+ * Original code by Hannes Gredler (hannes@gredler.at)
  */
 
-#ifndef lint
-static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/signature.c,v 1.2 2008-09-22 20:22:10 guy Exp $ (LBL)";
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include <tcpdump-stdinc.h>
+#include <netdissect-stdinc.h>
 
 #include <string.h>
+#include <stdlib.h>
 
-#include "interface.h"
+#include "netdissect.h"
 #include "signature.h"
 
 #ifdef HAVE_LIBCRYPTO
@@ -38,6 +34,7 @@ static const char rcsid[] _U_ =
 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 }
 };
@@ -50,8 +47,8 @@ const struct tok signature_check_values[] = {
  */
 USES_APPLE_DEPRECATED_API
 static void
-signature_compute_hmac_md5(const u_int8_t *text, int text_len, unsigned char *key,
-                           unsigned int key_len, u_int8_t *digest)
+signature_compute_hmac_md5(const uint8_t *text, int text_len, unsigned char *key,
+                           unsigned int key_len, uint8_t *digest)
 {
     MD5_CTX context;
     unsigned char k_ipad[65];    /* inner padding - key XORd with ipad */
@@ -112,45 +109,101 @@ signature_compute_hmac_md5(const u_int8_t *text, int text_len, unsigned char *ke
     MD5_Final(digest, &context);          /* finish up 2nd pass */
 }
 USES_APPLE_RST
-#endif
 
-#ifdef HAVE_LIBCRYPTO
 /*
  * Verify a cryptographic signature of the packet.
  * Currently only MD5 is supported.
  */
 int
-signature_verify (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)
 {
-    u_int8_t rcvsig[16];
-    u_int8_t sig[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 (!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 *)sigsecret,
-                               strlen(sigsecret), sig);
+    /*
+     * 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);
+    }
 
-    if (memcmp(rcvsig, sig, sizeof(sig)) == 0) {
-        return (SIGNATURE_VALID);
+    memcpy(packet_copy, pptr, plen);
 
-    } else {
+    /*
+     * 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 uint8_t *)clear_arg - pptr)));
 
+    /*
+     * Compute the signature.
+     */
+    signature_compute_hmac_md5(packet_copy, plen,
+                               (unsigned char *)ndo->ndo_sigsecret,
+                               strlen(ndo->ndo_sigsecret), sig);
+
+    /*
+     * 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) {
-            (void)printf("%02x", sig[i]);
+            ND_PRINT((ndo, "%02x", sig[i]));
         }
 
         return (SIGNATURE_INVALID);
     }
 }
+#else
+int
+signature_verify(netdissect_options *ndo _U_, const u_char *pptr _U_,
+                 u_int plen _U_, const u_char *sig_ptr _U_,
+                 void (*clear_rtn)(void *) _U_, const void *clear_arg _U_)
+{
+    return (CANT_CHECK_SIGNATURE);
+}
 #endif
 
 /*