]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-esp.c
Get rid of unneeded includes of <netinet/in_systm.h> and <netinet/ip.h>.
[tcpdump] / print-esp.c
index 97ab366e2a80ba73e39a86f0595623685a3076ca..957245084473fc7abab1a748b125a9060701ec71 100644 (file)
  */
 
 #ifndef lint
-static char rcsid[] =
-    "@(#) Header: print-ah.c,v 1.37 94/06/10 17:01:42 mccanne Exp (LBL)";
+static const char rcsid[] =
+    "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.24 2002-04-07 02:16:03 guy Exp $ (LBL)";
 #endif
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <stdlib.h>
 
 #include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
-#include <netinet/udp.h>
-#include <netinet/udp_var.h>
-
-#undef NOERROR                                 /* Solaris sucks */
-#include <arpa/nameser.h>
-#include <arpa/tftp.h>
-
-#ifdef SOLARIS
-#include <tiuser.h>
+
+#ifdef HAVE_LIBCRYPTO
+#include <openssl/des.h>
+#include <openssl/blowfish.h>
+#ifdef HAVE_OPENSSL_RC5_H
+#include <openssl/rc5.h>
+#endif
+#ifdef HAVE_OPENSSL_CAST_H
+#include <openssl/cast.h>
+#endif
 #endif
-#include <rpc/rpc.h>
 
-#include <errno.h>
 #include <stdio.h>
 
+#include "ip.h"
+#include "esp.h"
+#ifdef INET6
+#include "ip6.h"
+#endif
+
+#define AVOID_CHURN 1
 #include "interface.h"
 #include "addrtoname.h"
-#include "appletalk.h"
 
-#include "nfs.h"
-#include "bootp.h"
+static struct esp_algorithm *espsecret_xform=NULL;  /* cache of decoded alg. */
+static char                 *espsecret_key=NULL;
 
-extern int packettype;
 
+enum cipher { NONE,
+             DESCBC,
+             BLOWFISH,
+             RC5,
+             CAST128,
+             DES3CBC};
+
+
+
+struct esp_algorithm {
+       char        *name;
+       enum  cipher algo;
+       int          ivlen;
+       int          authlen;
+       int          replaysize;
+};
+
+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},
+};
+
+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;
+       }
+}
 
-void
-esp_print(register const u_char *bp, int length, register const u_char *bp2)
+int
+esp_print(register const u_char *bp, register const u_char *bp2,
+         int *nhdr, int *padlen)
 {
-  register const struct ip *ip;
-  register const u_char *cp, *nh;
-  u_short ahlen, authlen;
-  u_long  spi, seqno;
+       register const struct esp *esp;
+       register const u_char *ep;
+       u_int32_t spi;
+       struct ip *ip = NULL;
+#ifdef INET6
+       struct ip6_hdr *ip6 = NULL;
+#endif
+       int advance;
+       int len;
+       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 available data. */
+       ep = snapend;
+
+       if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) {
+               fputs("[|ESP]", stdout);
+               goto fail;
+       }
+       printf("ESP(spi=0x%08x", spi);
+       printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1)));
+       printf(")");
+
+       /* if we don't have decryption key, we can't decrypt this packet. */
+       if (!espsecret)
+               goto fail;
+
+       if(!espsecret_xform) {
+               esp_print_decodesecret();
+       }
+       if(espsecret_xform->algo == NONE) {
+               goto fail;
+       }
+
+       ip = (struct ip *)bp2;
+       switch (IP_V(ip)) {
+#ifdef INET6
+       case 6:
+               ip6 = (struct ip6_hdr *)bp2;
+               ip = NULL;
+               /* we do not attempt to decrypt jumbograms */
+               if (!ntohs(ip6->ip6_plen))
+                       goto fail;
+               /* if we can't get nexthdr, we do not need to decrypt it */
+               len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
+               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
+               len = ntohs(ip->ip_len);
+               break;
+       default:
+               goto fail;
+       }
+
+       /* if we can't get nexthdr, we do not need to decrypt it */
+       if (ep - bp2 < len)
+               goto fail;
+
+       ivoff = (u_char *)(esp + 1) + espsecret_xform->replaysize;
+       ivlen = espsecret_xform->ivlen;
+       secret = espsecret_key;
+
+       switch (espsecret_xform->algo) {
+       case DESCBC:
+#ifdef HAVE_LIBCRYPTO
+           {
+               u_char iv[8];
+               des_key_schedule schedule;
+
+               switch (ivlen) {
+               case 4:
+                       memcpy(iv, ivoff, 4);
+                       memcpy(&iv[4], ivoff, 4);
+                       p = &iv[4];
+                       *p++ ^= 0xff;
+                       *p++ ^= 0xff;
+                       *p++ ^= 0xff;
+                       *p++ ^= 0xff;
+                       break;
+               case 8:
+                       memcpy(iv, ivoff, 8);
+                       break;
+               default:
+                       goto fail;
+               }
+
+               des_check_key = 0;
+               des_set_key((void *)secret, schedule);
+
+               p = ivoff + ivlen;
+               des_cbc_encrypt((void *)p, (void *)p,
+                       (long)(ep - p), schedule, (void *)iv,
+                       DES_DECRYPT);
+               advance = ivoff - (u_char *)esp + ivlen;
+               break;
+           }
+#else
+               goto fail;
+#endif /*HAVE_LIBCRYPTO*/
+
+       case BLOWFISH:
+#ifdef HAVE_LIBCRYPTO
+           {
+               BF_KEY schedule;
+
+               BF_set_key(&schedule, strlen(secret), secret);
+
+               p = ivoff + ivlen;
+               BF_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
+                       BF_DECRYPT);
+               advance = ivoff - (u_char *)esp + ivlen;
+               break;
+           }
+#else
+               goto fail;
+#endif /*HAVE_LIBCRYPTO*/
+
+       case RC5:
+#if defined(HAVE_LIBCRYPTO) && defined(HAVE_RC5_H)
+           {
+               RC5_32_KEY schedule;
+
+               RC5_32_set_key(&schedule, strlen(secret), secret,
+                       RC5_16_ROUNDS);
+
+               p = ivoff + ivlen;
+               RC5_32_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
+                       RC5_DECRYPT);
+               advance = ivoff - (u_char *)esp + ivlen;
+               break;
+           }
+#else
+               goto fail;
+#endif /*HAVE_LIBCRYPTO*/
+
+       case CAST128:
+#if defined(HAVE_LIBCRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128)
+           {
+               CAST_KEY schedule;
+
+               CAST_set_key(&schedule, strlen(secret), secret);
+
+               p = ivoff + ivlen;
+               CAST_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
+                       CAST_DECRYPT);
+               advance = ivoff - (u_char *)esp + ivlen;
+               break;
+           }
+#else
+               goto fail;
+#endif /*HAVE_LIBCRYPTO*/
+
+       case DES3CBC:
+#if defined(HAVE_LIBCRYPTO)
+           {
+               des_key_schedule s1, s2, 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");
+               }
 
-  ip = (struct ip *)bp2;
+               p = ivoff + ivlen;
+               des_ede3_cbc_encrypt((void *)p, (void *)p,
+                                    (long)(ep - p),
+                                    s1, s2, s3,
+                                    (void *)ivoff, DES_DECRYPT);
+               advance = ivoff - (u_char *)esp + ivlen;
+               break;
+           }
+#else
+               goto fail;
+#endif /*HAVE_LIBCRYPTO*/
 
-  (void)printf("ESP %s > %s\n\t\t",
-              ipaddr_string(&ip->ip_src), 
-              ipaddr_string(&ip->ip_dst));
+       case NONE:
+       default:
+               advance = sizeof(struct esp) + espsecret_xform->replaysize;
+               break;
+       }
 
-  if (length < 8) {
-    (void)printf(" [|esp] truncated-esp %d", length);
-    return;
-  }
+       ep = ep - espsecret_xform->authlen;
+       /* sanity check for pad length */
+       if (ep - bp < *(ep - 2))
+               goto fail;
 
-  spi        = ntohl(*((u_long *)(bp)));
-  seqno      = ntohl(*((u_long *)(bp+4)));
+       if (padlen)
+               *padlen = *(ep - 2) + 2;
 
-  nh         = bp+ahlen;
+       if (nhdr)
+               *nhdr = *(ep - 1);
 
-  (void)printf("spi:%08x seqno:%d ciphertext: ", spi, seqno);
-  (void)default_print_unaligned(bp+8, length-8);
+       printf(": ");
+       return advance;
 
-  /* XXX it would be nice to decrypt! */
+fail:
+       if (nhdr)
+               *nhdr = -1;
+       return 65536;
 }