summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2003-07-17 08:45:38 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2003-07-17 08:45:38 +0000
commit697c978c9589b5d256576781d6e84074e4e1abb9 (patch)
treefb219b77a0531e42456144388f0da69c5e8ccaa8 /usr.sbin
parent5eedaf7b34d80506fcb980c2acb3359f332b3eda (diff)
add support for ESP decryption; ok deraadt@; feedback mickey@;
many manpage fixes from jmc@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/tcpdump/Makefile6
-rw-r--r--usr.sbin/tcpdump/print-ipsec.c144
-rw-r--r--usr.sbin/tcpdump/tcpdump.871
-rw-r--r--usr.sbin/tcpdump/tcpdump.c19
4 files changed, 211 insertions, 29 deletions
diff --git a/usr.sbin/tcpdump/Makefile b/usr.sbin/tcpdump/Makefile
index d852531c605..9eb84ccf8db 100644
--- a/usr.sbin/tcpdump/Makefile
+++ b/usr.sbin/tcpdump/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.40 2003/06/11 20:58:45 markus Exp $
+# $OpenBSD: Makefile,v 1.41 2003/07/17 08:45:37 markus Exp $
#
# Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
# The Regents of the University of California. All rights reserved.
@@ -32,8 +32,8 @@ CFLAGS+=-DCSLIP -DPPP -DHAVE_FDDI -DETHER_SERVICE -DRETSIGTYPE=void -DHAVE_NET_S
CFLAGS+=-DLBL_ALIGN
.endif
-LDADD+= -lpcap -ll
-DPADD+= ${LIBL} ${LIBPCAP}
+LDADD+= -lpcap -ll -lcrypto
+DPADD+= ${LIBL} ${LIBPCAP} ${LIBCRYPTO}
SRCS= tcpdump.c addrtoname.c \
print-ether.c print-ip.c print-arp.c print-tcp.c print-udp.c \
diff --git a/usr.sbin/tcpdump/print-ipsec.c b/usr.sbin/tcpdump/print-ipsec.c
index b1a3f8d797c..fb223e21abd 100644
--- a/usr.sbin/tcpdump/print-ipsec.c
+++ b/usr.sbin/tcpdump/print-ipsec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: print-ipsec.c,v 1.7 2003/02/20 23:39:20 jason Exp $ */
+/* $OpenBSD: print-ipsec.c,v 1.8 2003/07/17 08:45:37 markus Exp $ */
/*
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
@@ -28,7 +28,7 @@
#ifndef lint
static const char rcsid[] =
- "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-ipsec.c,v 1.7 2003/02/20 23:39:20 jason Exp $ (XXX)";
+ "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-ipsec.c,v 1.8 2003/07/17 08:45:37 markus Exp $ (XXX)";
#endif
#include <sys/param.h>
@@ -53,6 +53,9 @@ static const char rcsid[] =
#include "interface.h"
#include "extract.h" /* must come after interface.h */
+#include <openssl/evp.h>
+#include <ctype.h>
+
/*
* IPsec/ESP header
*/
@@ -61,6 +64,138 @@ struct esp_hdr {
u_int esp_seq;
};
+static int espinit = 0;
+static int espauthlen = 12;
+static EVP_CIPHER_CTX ctx;
+
+int
+esp_init (char *espspec)
+{
+ const EVP_CIPHER *evp;
+ char *p, *espkey, s[3], name[1024];
+ u_char *key;
+ int i, klen, len;
+
+ evp = EVP_aes_128_cbc(); /* default */
+ espkey = espspec;
+ if ((p = strchr(espspec, ':')) != NULL) {
+ len = p - espspec;
+ if (len >= sizeof(name))
+ error("espalg too long");
+ memcpy(name, espspec, len);
+ name[len] = '\0';
+ espkey = p + 1;
+
+ /* strip auth alg */
+ espauthlen = 0;
+ if ((p = strstr(name, "-hmac96")) != NULL) {
+ espauthlen = 12;
+ *p = '\0';
+ }
+ OpenSSL_add_all_algorithms();
+ if ((evp = EVP_get_cipherbyname(name)) == NULL)
+ error("espalg `%s' not supported", name);
+ }
+ klen = EVP_CIPHER_key_length(evp);
+ if (strlen(espkey) != klen * 2)
+ error("espkey size mismatch, %d bytes needed", klen);
+ if ((key = malloc(klen)) == NULL)
+ error("malloc failed");
+ for (i = 0; i < klen; i++) {
+ s[0] = espkey[2*i];
+ s[1] = espkey[2*i + 1];
+ s[2] = 0;
+ if (!isxdigit(s[0]) || !isxdigit(s[1]))
+ error("espkey must be specified in hex");
+ key[i] = strtoul(s, NULL, 16);
+ }
+ EVP_CIPHER_CTX_init(&ctx);
+ if (EVP_CipherInit(&ctx, evp, key, NULL, 0) < 0) {
+ free(key);
+ error("espkey init failed");
+ }
+ free(key);
+ espinit = 1;
+ return (0);
+}
+
+void
+esp_decrypt (const u_char *bp, u_int len, const u_char *bp2)
+{
+ const struct ip *ip;
+ u_char *data, pad, nh;
+ int blocksz;
+
+ ip = (const struct ip *)bp2;
+
+ blocksz = EVP_CIPHER_CTX_block_size(&ctx);
+
+ /* Skip fragments and short packets */
+ if (ntohs(ip->ip_off) & 0x3fff)
+ return;
+ if (snapend - bp < len) {
+ printf(" [|esp]");
+ return;
+ }
+ /*
+ * Skip ESP header and ignore authentication trailer.
+ * For decryption we need at least 2 blocks: IV and
+ * one cipher block.
+ */
+ if (len < sizeof(struct esp_hdr) + espauthlen + 2 * blocksz) {
+ printf(" [|esp]");
+ return;
+ }
+
+ data = (char *)bp;
+ data += sizeof(struct esp_hdr);
+ len -= sizeof(struct esp_hdr);
+ len -= espauthlen;
+
+ /* the first block contains the IV */
+ EVP_CipherInit(&ctx, NULL, NULL, data, 0);
+ len -= blocksz;
+ data += blocksz;
+
+ /* decrypt remaining payload */
+ EVP_Cipher(&ctx, data, data, len);
+
+ nh = data[len - 1];
+ pad = data[len - 2];
+
+ /* verify padding */
+ if (pad + 2 > len)
+ return;
+ if (data[len - 3] != pad)
+ return;
+ if (vflag > 1)
+ printf(" pad %d", pad);
+ len -= (pad + 2);
+ printf(": ");
+ switch (nh) {
+ case IPPROTO_TCP:
+ tcp_print(data, len, bp2);
+ break;
+ case IPPROTO_UDP:
+ udp_print(data, len, bp2);
+ break;
+ case IPPROTO_IPV6:
+ ip6_print(data, len);
+ break;
+ case IPPROTO_IPV4:
+ ip_print(data, len);
+ break;
+ case IPPROTO_ICMP:
+ icmp_print(data, bp2);
+ break;
+ default:
+ printf("ip-proto-%d %d", nh, len);
+ break;
+ }
+ if (vflag)
+ printf(" (esp)");
+}
+
void
esp_print (register const u_char *bp, register u_int len,
register const u_char *bp2)
@@ -82,6 +217,9 @@ esp_print (register const u_char *bp, register u_int len,
printf(" spi 0x%08X seq %d len %d",
ntohl(esp->esp_spi), ntohl(esp->esp_seq), len);
+
+ if (espinit)
+ esp_decrypt(bp, len, bp2);
}
/*
@@ -109,7 +247,7 @@ ah_print (register const u_char *bp, register u_int len,
ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst));
if (pl_len < sizeof(struct ah_hdr)) {
- printf("[|esp]");
+ printf("[|ah]");
return;
}
ah = (const struct ah_hdr *)bp;
diff --git a/usr.sbin/tcpdump/tcpdump.8 b/usr.sbin/tcpdump/tcpdump.8
index 52194b21fe1..f42801bf4a0 100644
--- a/usr.sbin/tcpdump/tcpdump.8
+++ b/usr.sbin/tcpdump/tcpdump.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tcpdump.8,v 1.36 2003/07/14 13:46:14 jmc Exp $
+.\" $OpenBSD: tcpdump.8,v 1.37 2003/07/17 08:45:37 markus Exp $
.\"
.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996
.\" The Regents of the University of California. All rights reserved.
@@ -35,6 +35,7 @@
.Op Fl s Ar snaplen
.Op Fl T Ar type
.Op Fl w Ar file
+.Op Fl E Oo Ar espalg: Oc Ar espkey
.Op Ar expression
.Sh DESCRIPTION
.Nm
@@ -193,6 +194,34 @@ No Selective Acknowledgements
and
.Cm wb
.Pq distributed White Board .
+.It Xo
+.Fl E Oo Ar espalg: Oc Ar espkey
+.Xc
+Try to decrypt
+.Tn RFC 2406
+.Cm ESP
+traffic using the specified hex key
+.Ar espkey .
+Supported algorithms for
+.Ar espalg
+are:
+.Cm aes128 ,
+.Cm aes128-hmac96 ,
+.Cm blowfish ,
+.Cm blowfish-hmac96 ,
+.Cm cast ,
+.Cm cast-hmac96 ,
+.Cm des3 ,
+.Cm des3-hmac96 ,
+.Cm des
+and
+.Cm des-hmac96 .
+The algorithm defaults to
+.Cm aes128-hmac96 .
+This option should be used for debugging only, since
+the key will show up in
+.Xr ps 1
+output.
.It Fl S
Print absolute, rather than relative,
.Tn TCP
@@ -412,9 +441,8 @@ expressions can be prepended with the keywords,
or
.Cm rarp
as in:
-.Bd -literal -offset indent
-.Cm ip host Ar host
-.Ed
+.Pp
+.D1 Cm ip host Ar host
.Pp
which is equivalent to:
.Bd -ragged -offset indent
@@ -529,9 +557,8 @@ Any of the above port expressions can be prepended with the keywords
or
.Cm udp ,
as in:
-.Bd -literal -offset indent
-.Cm tcp src port Ar port
-.Ed
+.Pp
+.D1 Cm tcp src port Ar port
.Pp
which matches only
.Tn TCP
@@ -541,17 +568,15 @@ packets whose source port is
True if the packet has a length less than or equal to
.Ar length .
This is equivalent to:
-.Bd -literal -offset indent
-.Cm len \*(<= Ar length .
-.Ed
+.Pp
+.D1 Cm len \*(Le Ar length .
.Pp
.It Cm greater Ar length
True if the packet has a length greater than or equal to
.Ar length .
This is equivalent to:
-.Bd -literal -offset indent
-.Cm len \*(>= Ar length .
-.Ed
+.Pp
+.D1 Cm len \*(Ge Ar length .
.Pp
.It Cm ip proto Ar proto
True if the packet is an
@@ -716,9 +741,8 @@ and
.Cm mopdl
.Xc
Abbreviations for:
-.Bd -literal -offset indent
-.Cm ether proto Ar p
-.Ed
+.Pp
+.D1 Cm ether proto Ar p
.Pp
where
.Ar p
@@ -992,6 +1016,19 @@ packets that are not echo requests/replies (i.e., not ping packets):
.Cm and icmp Ns [0] !\&= 0
\&'
.Ed
+.Pp
+To print and decrypt all
+.Tn ESP
+packets with
+.Tn SPI
+0x00001234:
+.Bd -ragged -offset indent
+.Nm
+-E des3-hmac96:ab...def
+\&'
+.Cm ip Ns [20:4] = 0x00001234
+\&'
+.Ed
.El
.Sh OUTPUT FORMAT
The output of
@@ -1664,7 +1701,7 @@ The file
.Pa /etc/atalk.names
is used to translate AppleTalk net and node numbers to names.
Lines in this file have the form
-.Bd -literal -offset indent
+.Bd -unfilled -offset indent
.Ar number name
1.254 ether
diff --git a/usr.sbin/tcpdump/tcpdump.c b/usr.sbin/tcpdump/tcpdump.c
index 00825330d76..6e0935b47b9 100644
--- a/usr.sbin/tcpdump/tcpdump.c
+++ b/usr.sbin/tcpdump/tcpdump.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcpdump.c,v 1.31 2003/05/14 08:50:37 canacar Exp $ */
+/* $OpenBSD: tcpdump.c,v 1.32 2003/07/17 08:45:37 markus Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -26,7 +26,7 @@ static const char copyright[] =
"@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997\n\
The Regents of the University of California. All rights reserved.\n";
static const char rcsid[] =
- "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/tcpdump.c,v 1.31 2003/05/14 08:50:37 canacar Exp $ (LBL)";
+ "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/tcpdump.c,v 1.32 2003/07/17 08:45:37 markus Exp $ (LBL)";
#endif
/*
@@ -80,6 +80,7 @@ int32_t thiszone; /* seconds offset from gmt to local time */
/* Externs */
extern void bpf_dump(struct bpf_program *, int);
+extern int esp_init(char *);
/* Forwards */
RETSIGTYPE cleanup(int);
@@ -161,7 +162,7 @@ main(int argc, char **argv)
error("%s", ebuf);
opterr = 0;
- while ((op = getopt(argc, argv, "ac:defF:i:lnNOpqr:s:StT:vw:xXY")) != -1)
+ while ((op = getopt(argc, argv, "ac:deE:fF:i:lnNOpqr:s:StT:vw:xXY")) != -1)
switch (op) {
case 'a':
@@ -284,6 +285,11 @@ main(int argc, char **argv)
if (xflag == 0) ++xflag;
break;
+ case 'E':
+ if (esp_init(optarg) < 0)
+ error("bad esp specification `%s'", optarg);
+ break;
+
default:
usage();
/* NOTREACHED */
@@ -531,10 +537,11 @@ usage(void)
(void)fprintf(stderr, "%s version %s\n", program_name, version);
(void)fprintf(stderr, "libpcap version %s\n", pcap_version);
(void)fprintf(stderr,
-"Usage: %s [-adeflnNOpqStvxX] [-c count] [ -F file ]\n", program_name);
+"Usage: %s [-adeflnNOpqStvxX] [-c count] [-F file] [-i interface] [-r file]\n",
+ program_name);
(void)fprintf(stderr,
-"\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n");
+"\t\t[-s snaplen] [-T type] [-w file] [-E [espalg:]espkey]\n");
(void)fprintf(stderr,
-"\t\t[ -T type ] [ -w file ] [ expression ]\n");
+"\t\t[expression]\n");
exit(1);
}