diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2003-07-17 08:45:38 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2003-07-17 08:45:38 +0000 |
commit | 697c978c9589b5d256576781d6e84074e4e1abb9 (patch) | |
tree | fb219b77a0531e42456144388f0da69c5e8ccaa8 /usr.sbin | |
parent | 5eedaf7b34d80506fcb980c2acb3359f332b3eda (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/Makefile | 6 | ||||
-rw-r--r-- | usr.sbin/tcpdump/print-ipsec.c | 144 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump.8 | 71 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump.c | 19 |
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); } |