X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/95be1abb3574f6fc9bdd5c90ff7073295ee07de7..ad6df73f5a6c46a409c7629f5588b1b81dff6357:/print-esp.c diff --git a/print-esp.c b/print-esp.c index 06fc7f90..95724508 100644 --- a/print-esp.c +++ b/print-esp.c @@ -23,7 +23,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.5 1999-12-15 08:10:18 fenner Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.24 2002-04-07 02:16:03 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -35,91 +35,187 @@ static const char rcsid[] = #include #include #include - -#include -#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CRYPTO -#include -#include -#ifdef HAVE_RC5_H -#include + +#ifdef HAVE_LIBCRYPTO +#include +#include +#ifdef HAVE_OPENSSL_RC5_H +#include #endif -#ifdef HAVE_CAST_H -#include +#ifdef HAVE_OPENSSL_CAST_H +#include #endif #endif #include +#include "ip.h" +#include "esp.h" #ifdef INET6 -#include +#include "ip6.h" #endif -/* there's no standard definition so we are on our own */ -struct esp { - u_int32_t esp_spi; /* ESP */ - /*variable size, 32bit bound*/ /* Initialization Vector */ - /*variable size*/ /* Payload data */ - /*variable size*/ /* padding */ - /*8bit*/ /* pad size */ - /*8bit*/ /* next header */ - /*8bit*/ /* next header */ - /*variable size, 32bit bound*/ /* Authentication data (new IPsec) */ +#define AVOID_CHURN 1 +#include "interface.h" +#include "addrtoname.h" + +static struct esp_algorithm *espsecret_xform=NULL; /* cache of decoded alg. */ +static char *espsecret_key=NULL; + + +enum cipher { NONE, + DESCBC, + BLOWFISH, + RC5, + CAST128, + DES3CBC}; + + + +struct esp_algorithm { + char *name; + enum cipher algo; + int ivlen; + int authlen; + int replaysize; }; -struct newesp { - u_int32_t esp_spi; /* ESP */ - u_int32_t esp_seq; /* Sequence number */ - /*variable size*/ /* (IV and) Payload data */ - /*variable size*/ /* padding */ - /*8bit*/ /* pad size */ - /*8bit*/ /* next header */ - /*8bit*/ /* next header */ - /*variable size, 32bit bound*/ /* Authentication data */ +struct esp_algorithm esp_xforms[]={ + {"none", NONE, 0, 0, 0}, + {"des-cbc", DESCBC, 8, 0, 0}, + {"des-cbc-hmac96", DESCBC, 8, 12, 4}, + {"blowfish-cbc", BLOWFISH,8, 0, 0}, + {"blowfish-cbc-hmac96", BLOWFISH,8, 12, 4}, + {"rc5-cbc", RC5, 8, 0, 0}, + {"rc5-cbc-hmac96", RC5, 8, 12, 4}, + {"cast128-cbc", CAST128, 8, 0, 0}, + {"cast128-cbc-hmac96", CAST128, 8, 12, 4}, + {"3des-cbc-hmac96", DES3CBC, 8, 12, 4}, }; -#include "interface.h" -#include "addrtoname.h" +static int hexdigit(char hex) +{ + if(hex >= '0' && hex <= '9') { + return (hex - '0'); + } else if(hex >= 'A' && hex <= 'F') { + return (hex - 'A' + 10); + } else if(hex >= 'a' && hex <= 'f') { + return (hex - 'a' + 10); + } else { + printf("invalid hex digit %c in espsecret\n", hex); + return 0; + } +} + +static int hex2byte(char *hexstring) +{ + int byte; + + byte = (hexdigit(hexstring[0]) << 4) + + hexdigit(hexstring[1]); + return byte; +} + + +static void esp_print_decodesecret(void) +{ + char *colon; + int len, i; + struct esp_algorithm *xf; + + if(espsecret == NULL) { + /* set to NONE transform */ + espsecret_xform = esp_xforms; + return; + } + + if(espsecret_key != NULL) { + return; + } + + colon = strchr(espsecret, ':'); + if(colon == NULL) { + printf("failed to decode espsecret: %s\n", + espsecret); + /* set to NONE transform */ + espsecret_xform = esp_xforms; + } + + len = colon - espsecret; + xf = esp_xforms; + while(xf->name && strncasecmp(espsecret, xf->name, len)!=0) { + xf++; + } + if(xf->name == NULL) { + printf("failed to find cipher algo %s\n", + espsecret); + espsecret_xform = esp_xforms; + return; + } + espsecret_xform = xf; + + colon++; + if(colon[0]=='0' && colon[1]=='x') { + /* decode some hex! */ + colon+=2; + len = strlen(colon) / 2; + espsecret_key = (char *)malloc(len); + if(espsecret_key == NULL) { + fprintf(stderr, "%s: ran out of memory (%d) to allocate secret key\n", + program_name, len); + exit(2); + } + i = 0; + while(colon[0] != '\0' && colon[1]!='\0') { + espsecret_key[i]=hex2byte(colon); + colon+=2; + i++; + } + } else { + espsecret_key = colon; + } +} int -esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr) +esp_print(register const u_char *bp, register const u_char *bp2, + int *nhdr, int *padlen) { register const struct esp *esp; register const u_char *ep; u_int32_t spi; - enum { NONE, DESCBC, BLOWFISH, RC5, CAST128, DES3CBC } algo = NONE; struct ip *ip = NULL; #ifdef INET6 struct ip6_hdr *ip6 = NULL; #endif int advance; int len; - char *secret = NULL; + char *secret; int ivlen = 0; u_char *ivoff; - +#ifdef HAVE_LIBCRYPTO + u_char *p; +#endif + esp = (struct esp *)bp; spi = (u_int32_t)ntohl(esp->esp_spi); + secret = NULL; + +#if 0 + /* keep secret out of a register */ + p = (u_char *)&secret; +#endif - /* 'ep' points to the end of avaible data. */ + /* 'ep' points to the end of available data. */ ep = snapend; if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) { fputs("[|ESP]", stdout); goto fail; } - printf("ESP(spi=%u", spi); + printf("ESP(spi=0x%08x", spi); printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1))); printf(")"); @@ -127,44 +223,15 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr) if (!espsecret) goto fail; - if (strncmp(espsecret, "des-cbc:", 8) == 0 - && strlen(espsecret + 8) == 8) { - algo = DESCBC; - ivlen = 8; - secret = espsecret + 8; - } else if (strncmp(espsecret, "blowfish-cbc:", 13) == 0) { - algo = BLOWFISH; - ivlen = 8; - secret = espsecret + 13; - } else if (strncmp(espsecret, "rc5-cbc:", 8) == 0) { - algo = RC5; - ivlen = 8; - secret = espsecret + 8; - } else if (strncmp(espsecret, "cast128-cbc:", 12) == 0) { - algo = CAST128; - ivlen = 8; - secret = espsecret + 12; - } else if (strncmp(espsecret, "3des-cbc:", 9) == 0 - && strlen(espsecret + 9) == 24) { - algo = DES3CBC; - ivlen = 8; - secret = espsecret + 9; - } else if (strncmp(espsecret, "none:", 5) == 0) { - algo = NONE; - ivlen = 0; - secret = espsecret + 5; - } else if (strlen(espsecret) == 8) { - algo = DESCBC; - ivlen = 8; - secret = espsecret; - } else { - algo = NONE; - ivlen = 0; - secret = espsecret; + if(!espsecret_xform) { + esp_print_decodesecret(); + } + if(espsecret_xform->algo == NONE) { + goto fail; } ip = (struct ip *)bp2; - switch (ip->ip_v) { + switch (IP_V(ip)) { #ifdef INET6 case 6: ip6 = (struct ip6_hdr *)bp2; @@ -177,6 +244,9 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr) break; #endif /*INET6*/ case 4: + /* nexthdr & padding are in the last fragment */ + if (ntohs(ip->ip_off) & IP_MF) + goto fail; #ifdef INET6 ip6 = NULL; #endif @@ -190,18 +260,16 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr) if (ep - bp2 < len) goto fail; - if (Rflag) - ivoff = (u_char *)(esp + 1) + sizeof(u_int32_t); - else - ivoff = (u_char *)(esp + 1); + ivoff = (u_char *)(esp + 1) + espsecret_xform->replaysize; + ivlen = espsecret_xform->ivlen; + secret = espsecret_key; - switch (algo) { + switch (espsecret_xform->algo) { case DESCBC: -#ifdef CRYPTO +#ifdef HAVE_LIBCRYPTO { u_char iv[8]; des_key_schedule schedule; - u_char *p; switch (ivlen) { case 4: @@ -232,13 +300,12 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr) } #else goto fail; -#endif /*CRYPTO*/ +#endif /*HAVE_LIBCRYPTO*/ case BLOWFISH: -#ifdef CRYPTO +#ifdef HAVE_LIBCRYPTO { BF_KEY schedule; - u_char *p; BF_set_key(&schedule, strlen(secret), secret); @@ -250,13 +317,12 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr) } #else goto fail; -#endif /*CRYPTO*/ +#endif /*HAVE_LIBCRYPTO*/ case RC5: -#if defined(CRYPTO) && defined(HAVE_RC5_H) +#if defined(HAVE_LIBCRYPTO) && defined(HAVE_RC5_H) { RC5_32_KEY schedule; - u_char *p; RC5_32_set_key(&schedule, strlen(secret), secret, RC5_16_ROUNDS); @@ -269,13 +335,12 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr) } #else goto fail; -#endif /*CRYPTO*/ +#endif /*HAVE_LIBCRYPTO*/ case CAST128: -#if defined(CRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128) +#if defined(HAVE_LIBCRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128) { CAST_KEY schedule; - u_char *p; CAST_set_key(&schedule, strlen(secret), secret); @@ -287,42 +352,53 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr) } #else goto fail; -#endif /*CRYPTO*/ +#endif /*HAVE_LIBCRYPTO*/ case DES3CBC: -#if defined(CRYPTO) +#if defined(HAVE_LIBCRYPTO) { des_key_schedule s1, s2, s3; - u_char *p; - des_check_key = 0; - des_set_key((void *)secret, s1); - des_set_key((void *)(secret + 8), s2); - des_set_key((void *)(secret + 16), s3); + des_check_key = 1; + des_set_odd_parity((void *)secret); + des_set_odd_parity((void *)(secret + 8)); + des_set_odd_parity((void *)(secret + 16)); + if(des_set_key((void *)secret, s1) != 0) { + printf("failed to schedule key 1\n"); + } + if(des_set_key((void *)(secret + 8), s2)!=0) { + printf("failed to schedule key 2\n"); + } + if(des_set_key((void *)(secret + 16), s3)!=0) { + printf("failed to schedule key 3\n"); + } p = ivoff + ivlen; des_ede3_cbc_encrypt((void *)p, (void *)p, - (long)(ep - p), s1, s2, s3, (void *)ivoff, DES_DECRYPT); + (long)(ep - p), + s1, s2, s3, + (void *)ivoff, DES_DECRYPT); advance = ivoff - (u_char *)esp + ivlen; break; } #else goto fail; -#endif /*CRYPTO*/ +#endif /*HAVE_LIBCRYPTO*/ case NONE: default: - if (Rflag) - advance = sizeof(struct esp) + sizeof(u_int32_t); - else - advance = sizeof(struct esp); + advance = sizeof(struct esp) + espsecret_xform->replaysize; break; } + ep = ep - espsecret_xform->authlen; /* sanity check for pad length */ if (ep - bp < *(ep - 2)) goto fail; + if (padlen) + *padlen = *(ep - 2) + 2; + if (nhdr) *nhdr = *(ep - 1);