]> The Tcpdump Group git mirrors - tcpdump/commitdiff
From Bruce M. Simpson: add a "-M" flag to specify a shared secret for
authorguy <guy>
Tue, 23 Mar 2004 07:15:36 +0000 (07:15 +0000)
committerguy <guy>
Tue, 23 Mar 2004 07:15:36 +0000 (07:15 +0000)
TCP-MD5 (RFC 2385) digest verification if we have libcrypto.

interface.h
print-tcp.c
tcp.h
tcpdump.1
tcpdump.c

index 99079453792d2dde99c3dc9ee8212d079c6d47aa..e91c593b8f2ebf6bf61c51d6f09e51427247e38d 100644 (file)
@@ -18,7 +18,7 @@
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.224 2004-03-17 19:40:41 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.225 2004-03-23 07:15:36 guy Exp $ (LBL)
  */
 
 #ifndef tcpdump_interface_h
@@ -83,6 +83,7 @@ extern int xflag;             /* print packet in hex */
 extern int Xflag;              /* print packet in hex/ascii */
 extern int Aflag;              /* print packet only in ascii observing TAB, LF, CR and SPACE as graphical chars */
 extern char *espsecret;
+extern char *tcpmd5secret;
 
 extern int packettype;         /* as specified by -T */
 #define PT_VAT         1       /* Visual Audio Tool */
index ccf8770665affe7520289a26ad1d64813398e359..6cce9e21e746779067dd925d119e82c3ed64af42 100644 (file)
@@ -21,7 +21,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.110 2003-11-19 00:17:32 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.111 2004-03-23 07:15:36 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -50,6 +50,13 @@ static const char rcsid[] _U_ =
 
 #include "nameser.h"
 
+#ifdef HAVE_LIBCRYPTO
+#include <openssl/md5.h>
+
+static int tcp_verify_signature(const struct ip *ip, struct tcphdr *tp,
+    const u_char *data, int length, const u_char *rcvsig);
+#endif
+
 static void print_tcp_rst_data(register const u_char *sp, u_int length);
 
 #define MAX_RST_DATA_LEN       30
@@ -561,6 +568,26 @@ tcp_print(register const u_char *bp, register u_int length,
                                (void)printf(" %u", EXTRACT_32BITS(cp));
                                break;
 
+                       case TCPOPT_SIGNATURE:
+                               (void)printf("md5:");
+                               if (IP_V(ip) != 4) {
+                                       (void)printf("!ipv4");
+                                       break;
+                               }
+                               datalen = TCP_SIGLEN;
+                               LENCHECK(datalen);
+#ifdef HAVE_LIBCRYPTO
+                               if (tcp_verify_signature(ip, tp,
+                                   bp + TH_OFF(tp) * 4, length, cp) == 0)
+                                       (void)printf("valid");
+                               else
+                                       (void)printf("invalid");
+#else
+                               for (i = 0; i < TCP_SIGLEN; ++i)
+                                       (void)printf("%02x", cp[i]);
+#endif
+                               break;
+
                        default:
                                (void)printf("opt-%u:", opt);
                                datalen = len - 2;
@@ -673,3 +700,50 @@ print_tcp_rst_data(register const u_char *sp, u_int length)
        }
        putchar(']');
 }
+
+#ifdef HAVE_LIBCRYPTO
+static int
+tcp_verify_signature(const struct ip *ip, struct tcphdr *tp,
+    const u_char *data, int length, const u_char *rcvsig)
+{
+       char sig[TCP_SIGLEN];
+       char zero_proto = 0;
+       MD5_CTX ctx;
+       u_short savecsum, tlen;
+
+       if (tcpmd5secret == NULL)
+               return (-1);
+
+       MD5_Init(&ctx);
+       /*
+        * Step 1: Update MD5 hash with IP pseudo-header.
+        */
+       MD5_Update(&ctx, (char *)&ip->ip_src, sizeof(ip->ip_src));
+       MD5_Update(&ctx, (char *)&ip->ip_dst, sizeof(ip->ip_dst));
+       MD5_Update(&ctx, (char *)&zero_proto, sizeof(zero_proto));
+       MD5_Update(&ctx, (char *)&ip->ip_p, sizeof(ip->ip_p));
+       tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4;
+       tlen = htons(tlen);
+       MD5_Update(&ctx, (char *)&tlen, sizeof(tlen));
+       /*
+        * Step 2: Update MD5 hash with TCP header, excluding options.
+        * The TCP checksum must be set to zero.
+        */
+       savecsum = tp->th_sum;
+       tp->th_sum = 0;
+       MD5_Update(&ctx, (char *)tp, sizeof(struct tcphdr));
+       tp->th_sum = savecsum;
+       /*
+        * Step 3: Update MD5 hash with TCP segment data, if present.
+        */
+       if (length > 0)
+               MD5_Update(&ctx, data, length);
+       /*
+        * Step 4: Update MD5 hash with shared secret.
+        */
+       MD5_Update(&ctx, tcpmd5secret, strlen(tcpmd5secret));
+       MD5_Final(sig, &ctx);
+
+       return (memcmp(rcvsig, sig, 16));
+}
+#endif /* HAVE_LIBCRYPTO */
diff --git a/tcp.h b/tcp.h
index 43587ec443f00dc969e9f85ff69746d49c3f94c1..f7e7d6eac95e7c0054de4cf9a1973dd6456ae8a5 100644 (file)
--- a/tcp.h
+++ b/tcp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/tcp.h,v 1.10 2002-12-11 07:14:11 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/tcp.h,v 1.11 2004-03-23 07:15:37 guy Exp $ (LBL) */
 /*
  * Copyright (c) 1982, 1986, 1993
  *     The Regents of the University of California.  All rights reserved.
@@ -75,6 +75,10 @@ struct tcphdr {
 #define TCPOPT_CC              11      /* T/TCP CC options (rfc1644) */
 #define TCPOPT_CCNEW           12      /* T/TCP CC options (rfc1644) */
 #define TCPOPT_CCECHO          13      /* T/TCP CC options (rfc1644) */
+#define TCPOPT_SIGNATURE       19      /* Keyed MD5 (rfc2385) */
+#define    TCPOLEN_SIGNATURE           18
+
+#define TCP_SIGLEN 16                  /* length of an option 19 digest */
 
 #define TCPOPT_TSTAMP_HDR      \
     (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
index 3ef53a89b4181266182239acd5e99efbe47235b8..dc1fca9c0e10fecac20ee8fd9dbdec22aaaee20c 100644 (file)
--- a/tcpdump.1
+++ b/tcpdump.1
@@ -1,4 +1,4 @@
-.\" @(#) $Header: /tcpdump/master/tcpdump/Attic/tcpdump.1,v 1.160 2004-01-26 02:05:18 guy Exp $ (LBL)
+.\" @(#) $Header: /tcpdump/master/tcpdump/Attic/tcpdump.1,v 1.161 2004-03-23 07:15:37 guy Exp $ (LBL)
 .\"
 .\"    $NetBSD: tcpdump.8,v 1.9 2003/03/31 00:18:17 perry Exp $
 .\"
@@ -22,7 +22,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH TCPDUMP 1  "25 January 2004"
+.TH TCPDUMP 1  "22 March 2004"
 .SH NAME
 tcpdump \- dump traffic on a network
 .SH SYNOPSIS
@@ -54,6 +54,10 @@ tcpdump \- dump traffic on a network
 .I module
 ]
 [
+.B \-M
+.I secret
+]
+[
 .B \-r
 .I file
 ]
@@ -385,6 +389,10 @@ Load SMI MIB module definitions from file \fImodule\fR.
 This option
 can be used several times to load several MIB modules into \fItcpdump\fP.
 .TP
+.B \-M
+Use \fIsecret\fP as a shared secret for validating the digests found in
+TCP segments with the TCP-MD5 option (RFC 2385), if present.
+.TP
 .B \-n
 Don't convert addresses (i.e., host addresses, port numbers, etc.) to names.
 .TP
index 142731a377ff2273471a19c0772b238f7899342e..a6b998c8780c542599800a23b2052e8e7d607cf3 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -30,7 +30,7 @@ static const char copyright[] _U_ =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
 The Regents of the University of California.  All rights reserved.\n";
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.236 2004-03-19 21:36:35 risso Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.237 2004-03-23 07:15:38 guy Exp $ (LBL)";
 #endif
 
 /*
@@ -113,6 +113,7 @@ static int WflagChars = 0;
 const char *dlt_name = NULL;
 
 char *espsecret = NULL;                /* ESP secret key */
+char *tcpmd5secret = NULL;     /* TCP-MD5 secret key */
 
 int packettype;
 
@@ -437,7 +438,7 @@ main(int argc, char **argv)
 
        opterr = 0;
        while (
-           (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:i:lLm:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:YZ:")) != -1)
+           (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:i:lLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:YZ:")) != -1)
                switch (op) {
 
                case 'a':
@@ -590,6 +591,14 @@ main(int argc, char **argv)
 #endif
                        break;
 
+               case 'M':
+                       /* TCP-MD5 shared secret */
+#ifndef HAVE_LIBCRYPTO
+                       warning("crypto code not compiled in");
+#endif
+                       tcpmd5secret = optarg;
+                       break;
+
                case 'O':
                        Oflag = 0;
                        break;
@@ -1281,9 +1290,9 @@ usage(void)
        (void)fprintf(stderr,
 "Usage: %s [-aAd" D_FLAG "eflLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name);
        (void)fprintf(stderr,
-"\t\t[ -E algo:secret ] [ -F file ] [ -i interface ] [ -r file ]\n");
+"\t\t[ -E algo:secret ] [ -F file ] [ -i interface ] [ -M secret ]\n");
        (void)fprintf(stderr,
-"\t\t[ -s snaplen ] [ -T type ] [ -w file ] [ -W filecount ]\n");
+"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -w file ] [ -W filecount ]\n");
        (void)fprintf(stderr,
 "\t\t[ -y datalinktype ] [ -Z user ]\n");
        (void)fprintf(stderr,