#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "interface.h"
#include "addrtoname.h"
#define MAX_ALGS (256)
int skipflag = 0;
const int skip_max_algs = MAX_ALGS;
char *old_skip_crypt_algs[MAX_ALGS] = {
"none",
"des_cbc",
"rc2_cbc",
"rc4(40bit)",
"rc4(128bit)",
"des_ede-2",
"des_ede-3",
"idea",
"",
"",
"simplecrypt"
};
char *
skip_alg_to_name(char *table[], int alg)
{
if (alg > skip_max_algs) {
return ("<invalid>");
}
if (alg < 0) {
return ("<invalid>");
}
if (table[alg] == NULL) {
return ("<unknown>");
}
if (strlen(table[alg]) == 0) {
return ("<unknown>");
}
return (table[alg]);
}
unsigned char old_skip_ekp_sizes[MAX_ALGS] = {
8,
8,
8,
8,
16,
16,
24,
16,
0,
0,
8,
};
unsigned char old_skip_mid_sizes[MAX_ALGS] = {
8,
8,
8,
8,
8,
8,
8,
8,
0,
0,
8,
};
void skip_print_old(register const u_char *bp, register int length,
const u_char *bp2)
{
struct ip *ip;
const u_char *end;
u_char *p;
unsigned char kij_alg, kp_alg, *c;
unsigned short i;
unsigned short len;
int boxid;
int node;
ip=(struct ip *)bp2;
p=(u_char *)bp;
end=bp+length;
printf("SKIP: *** OLD SKIP ***\n");
printf("OSKIP: %s>%s:%d",ipaddr_string(&ip->ip_src),
ipaddr_string(&ip->ip_dst),length);
if (!skipflag)
return;
printf("\nOSKIP: SAID byte 1= 0x%02x\n",*p);
printf("OSKIP: xxxx .... = version %d\n", (int) (*p & 0xf0) >> 4);
if (*p & 0x08) {
printf("OSKIP: .... 1... = encrypted\n");
} else {
printf("OSKIP: .... 0... = not encrypted\n");
}
if (*p & 0x04) {
printf("OSKIP: .... .1.. = authenticated\n");
} else {
printf("OSKIP: .... .0.. = not authenticated\n");
}
if (*p & 0x02) {
printf("OSKIP: .... ..1. = compressed\n");
} else {
printf("OSKIP: .... ..0. = not compressed\n");
}
if (*p & 0x01) {
printf("OSKIP: .... ...1 = sequenced\n");
} else {
printf("OSKIP: .... ...0 = not sequenced\n");
}
p++;
printf("OSKIP: SAID byte 2 = 0x%02x\n", *p);
if (*p & 0x80) {
node=1;
printf("OSKIP: 1... .... = Node ID present\n");
} else {
node=0;
printf("OSKIP: 0... .... = no Node ID present\n");
}
if (*p & 0x40) {
printf("OSKIP: .1.. .... = <reserved should be zero>\n");
} else {
printf("OSKIP: .0.. .... = <reserved should be zero>\n");
}
if (*p & 0x20) {
printf("OSKIP: ..1. .... = <reserved should be zero>\n");
} else {
printf("OSKIP: ..0. .... = <reserved should be zero>\n");
}
if (*p & 0x10) {
printf("OSKIP: ...1 .... = <reserved should be zero>\n");
} else {
printf("OSKIP: ...0 .... = <reserved should be zero>\n");
}
p++;
printf("OSKIP: SAID byte 3 = 0x%02x\n", *p);
p++;
printf("OSKIP: SAID byte 4 = 0x%02x\n", *p);
p++;
kij_alg = *p;
printf("OSKIP: Kij alg (key encryption algorithm) = 0x%02x (%s)\n",
kij_alg, skip_alg_to_name(old_skip_crypt_algs,kij_alg));
p++;
kp_alg = *p;
printf("OSKIP: Kp alg (traffic encryption algorithm) = 0x%02x (%s)\n",
kp_alg, skip_alg_to_name(old_skip_crypt_algs,kp_alg));
p++;
printf("OSKIP: reserved byte 1 = 0x%02x\n", *p++);
printf("OSKIP: reserved byte 2 = 0x%02x\n", *p++);
if (node) {
if ((end - p) < sizeof(boxid)) {
return;
}
c = (unsigned char *) &boxid;
*c++ = *p++;
*c++ = *p++;
*c++ = *p++;
*c++ = *p++;
printf("OSKIP: Node ID = 0x%08x\n", ntohl(boxid));
}
len = old_skip_ekp_sizes[kp_alg];
if ((unsigned short) (end - p) < len) {
return;
}
printf("OSKIP: encrypted Kp: ");
for (i = 0; i < len; i++) {
printf("%02x ", (unsigned char) *p++);
}
printf("\n");
len = old_skip_mid_sizes[kp_alg];
if ((unsigned short) (end - p) < len) {
return;
}
printf("OSKIP: message indicator field: ");
for (i = 0; i < len; i++) {
printf("%02x ", (unsigned char) *p++);
}
printf("\n");
}
unsigned char skip_nsid_sizes[MAX_ALGS] = {
0,
4,
4,
16,
16,
16,
16,
6,
16,
16,
16,
16,
};
unsigned char skip_ekp_sizes[MAX_ALGS] = {
0,
8,
24,
0,
0,
0,
0,
0,
0,
0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8,
16,
8,
16,
0,
0
};
char *skip_nsid_names[MAX_ALGS] = {
"none",
"IPv4",
"Posix/Xopen UID",
"IPv6",
"MD5 DNS",
"MD5 ASN.1 DN",
"MD5 U.S. Soc. #",
"802.x MAC",
"MD5 DH Public Key",
"MD5 RFC822 Mail",
"MD5 Bank Account",
"MD5 NIS Name",
};
char *skip_kij_names[MAX_ALGS] = {
"none",
"DES-CBC",
"3DES3-EDE-CBC",
"IDEA-CBC",
};
char skip_kij_sizes[MAX_ALGS] = {
0,
8,
8,
8,
};
char *skip_crypt_names[MAX_ALGS] = {
"none",
"DES-CBC",
"3 key DES-EDE-CBC",
"",
"",
"",
"",
"",
"",
"",
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
"RC4-40",
"RC4-128",
"simple crypt",
"IDEA CBC",
"",
""
};
char *skip_auth_names[MAX_ALGS] = {
"none",
"keyed MD5",
"DES-CBC MAC",
"Keyed SHA",
};
char skip_auth_sizes[MAX_ALGS] = {
0,
16,
8,
20,
};
char skip_crypt_sizes[MAX_ALGS] = {
0,
8,
8,
0,
0,
0,
0,
0,
0,
0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8,
8,
8,
8,
0,
0
};
#ifndef IPPROTO_ESP
#define IPPROTO_ESP 50
#endif
#ifndef IPPROTO_AH
#define IPPROTO_AH 51
#endif
#ifndef IPPROTO_SKIP
#define IPPROTO_SKIP 57
#endif
#ifndef IPPROTO_OSKIP
#define IPPROTO_OSKIP 79
#endif
static int expected_auth_size=0;
static int expected_iv_size=0;
char *skip_protocol_name(int p)
{
switch(p) {
case IPPROTO_IP: return "IP";
case IPPROTO_ICMP: return "ICMP";
case IPPROTO_IGMP: return "IGMP";
case IPPROTO_ENCAP: return "ENCAP";
case IPPROTO_TCP: return "TCP";
case IPPROTO_EGP: return "EGP";
case IPPROTO_UDP: return "UDP";
case IPPROTO_ESP: return "ESP";
case IPPROTO_AH: return "AH";
case IPPROTO_SKIP: return "SKIP";
case IPPROTO_ND: return "ND";
case IPPROTO_OSKIP: return "OLD-SKIP";
case IPPROTO_RAW: return "RAW IP";
default: return "<unknown>";
}
}
void skip_print_next(u_char nxt, const u_char *p, int len, const u_char *bp2)
{
switch(nxt) {
case IPPROTO_IP: ip_print(p,len); break;
case IPPROTO_ICMP: icmp_print(p,bp2); break;
case IPPROTO_TCP: tcp_print(p,len,bp2); break;
case IPPROTO_UDP: udp_print(p,len,bp2); break;
case IPPROTO_ESP: esp_print(p,len,bp2); break;
case IPPROTO_AH: ah_print(p,len,bp2); break;
case IPPROTO_SKIP: skip_print(p,len,bp2); break;
default: break;
}
}
void skip_print(register const u_char *bp, register int length,
const u_char *bp2)
{
struct ip *ip;
const u_char *end;
const u_char *p;
unsigned char kij_alg, crypt_alg, auth_alg, snsid, dnsid, nxt;
unsigned short i;
unsigned short len;
u_int n;
time_t full_n;
ip=(struct ip *)bp2;
p=bp;
end=bp+length<snapend?bp+length:snapend;
printf("%s>%s:%d SKIP",ipaddr_string(&ip->ip_src),
ipaddr_string(&ip->ip_dst),length);
if (!skipflag)
return;
if ((unsigned short) (end - p) < 4) {
printf("[SKIP|] (truncated)\n");
return;
}
printf("\nSKIP: version\t\t\t%d\n", (int) (*p & 0xf0) >> 4);
if (*p & 0xf)
printf("SKIP: version byte \t\treserved,\tis now 0x%x\n",
(int) (*p & 0xf));
p++;
snsid = *p;
printf("SKIP: Source NSID\t\t0x%02x\t\t%s\n",
snsid, skip_alg_to_name(skip_nsid_names,snsid));
p++;
dnsid = *p;
printf("SKIP: Destination NSID\t\t0x%02x\t\t%s\n",
dnsid, skip_alg_to_name(skip_nsid_names,dnsid));
p++;
nxt = *p;
printf("SKIP: Next Protocol Field\t0x%02x\t\t%s\n", nxt,
skip_protocol_name(nxt));
p++;
if ((unsigned short) (end - p) < 4) {
printf("[SKIP|] (truncated)\n");
return;
}
n=*p++<<24;
n+=*p++<<16;
n+=*p++<<8;
n+=*p;
full_n=(((365*25+6)*24)+n)*3600;
printf("SKIP: Counter n Field\t\t0x%08x\t%s", n,
asctime(gmtime(&full_n)));
p++;
if ((unsigned short) (end - p) < 4) {
printf("[SKIP|] (truncated)\n");
return;
}
kij_alg = *p;
printf("SKIP: Kij alg (key encryption)\t0x%02x\t\t%s\n",
kij_alg, skip_alg_to_name(skip_kij_names,kij_alg));
p++;
crypt_alg = *p;
expected_iv_size=skip_crypt_sizes[crypt_alg];
printf("SKIP: Crypt Alg\t\t\t0x%02x\t\t%s\n",
crypt_alg, skip_alg_to_name(skip_crypt_names,crypt_alg));
p++;
auth_alg = *p;
expected_auth_size=skip_auth_sizes[auth_alg];
printf("SKIP: Auth Alg\t\t\t0x%02x\t\t%s\n",
auth_alg, skip_alg_to_name(skip_auth_names,auth_alg));
p++;
if (*p) printf("SKIP: compression\t\treserved,\tis now0x%02x\n",
(int) *p++);
else p++;
if (kij_alg==0 && (crypt_alg || auth_alg)) {
printf("Warning: Kij Alg. undefined, but Auth. or Crypt. used!");
printf("Warning: Assuming empty Kp\n");
crypt_alg=auth_alg=0;
}
len = skip_ekp_sizes[crypt_alg];
len = len>(int)skip_auth_sizes[auth_alg]?len:skip_auth_sizes[auth_alg];
if (len && skip_kij_sizes[kij_alg] && len % skip_kij_sizes[kij_alg]) {
len += skip_kij_sizes[kij_alg] - (len%skip_kij_sizes[kij_alg]);
}
if ((unsigned short) (end - p) < len) {
printf("[SKIP|] (truncated)\n");
return;
}
printf("SKIP: Encrypted Kp\t\t");
for (i = 0; i < len; i++) {
printf("%02x ", (unsigned char) *p++);
}
printf("\n");
if (snsid) {
if ((end - p) < skip_nsid_sizes[snsid]) {
printf("[SKIP|] (truncated)\n");
return;
}
printf("SKIP: Source Master Key-ID\t");
if (snsid==1) {
printf("%s",ipaddr_string(p));
p+=skip_nsid_sizes[snsid];
} else {
for (i = 0; i < skip_nsid_sizes[snsid]; i++) {
printf("%02x ", (unsigned char) *p++);
}
}
printf("\n");
}
if (dnsid) {
if ((end - p) < skip_nsid_sizes[dnsid]) {
printf("[SKIP|] (truncated)\n");
return;
}
printf("SKIP: Dest. Master Key-ID\t");
if (dnsid==1) {
printf("%s",ipaddr_string(p));
p+=skip_nsid_sizes[dnsid];
} else {
for (i = 0; i < skip_nsid_sizes[dnsid]; i++) {
printf("%02x ", (unsigned char) *p++);
}
}
printf("\n");
}
if (p<end) skip_print_next(nxt,p,end-p,bp2);
else printf("(truncated)\n");
}
void ah_print(register const u_char *bp, register int length,
const u_char *bp2)
{
struct ip *ip;
const u_char *end;
const u_char *p;
u_char nxt;
int len, i;
u_int spi;
ip=(struct ip *)bp2;
p=bp;
end=bp+length<snapend?bp+length:snapend;
printf("SKIP-AH: %s>%s:%d",ipaddr_string(&ip->ip_src),
ipaddr_string(&ip->ip_dst),length);
if (!skipflag)
return;
if (end-p <4) {
printf("[SKIP-AH|]\n");
return;
}
nxt = *p;
printf("\nSKIP-AH: Next Protocol Field\t0x%02x\t\t%s\n", nxt,
skip_protocol_name(nxt));
p++;
len= 4 * (int) *p;
printf("SKIP-AH: length\t\t\t%d\n", len);
p++;
if (*p) printf("SKIP-AH: byte 3\t\t\treserved,\tis now0x%02x\n",
(int) *p++);
else p++;
if (*p) printf("SKIP-AH: byte 4\t\t\treserved,\tis now0x%02x\n",
(int) *p++);
else p++;
if (end-p <4) {
printf("[SKIP-AH|]\n");
return;
}
spi=*p++<<24;
spi+=*p++<<16;
spi+=*p++<<8;
spi+=*p;
printf("SKIP-AH: SPI\t\t\t0x%08x\t", spi );
if (spi==0) {
printf("NO association\n");
} else if (spi==1) {
printf("SKIP association\n");
if (expected_auth_size) {
if (expected_auth_size != len) {
printf("Warning: Length does not match SKIP Auth Alg!\n");
}
expected_auth_size=0;
}
} else if (spi<256) {
printf("UNKNOWN association\n");
} else {
printf("DYNAMIC association\n");
}
p++;
if ((unsigned short) (end - p) < len) {
printf("[SKIP-AH|] (truncated)\n");
return;
}
printf("SKIP-AH: Authentication Data\t");
for (i = 0; i < len; i++) {
printf("%02x ", (unsigned char) *p++);
if (i<len-1 && (i+1)%16==0) printf("\n\t\t\t\t");
}
printf("\n");
if (p<end) skip_print_next(nxt,p,end-p,bp2);
else printf("(truncated)\n");
}
void esp_print(register const u_char *bp, register int length,
const u_char *bp2)
{
struct ip *ip;
const u_char *end;
const u_char *p;
int len, i;
u_int spi;
ip=(struct ip *)bp2;
p=bp;
end=bp+length<snapend?bp+length:snapend;
printf("SKIP-ESP: %s>%s:%d",ipaddr_string(&ip->ip_src),
ipaddr_string(&ip->ip_dst),length);
if (!skipflag)
return;
if (end-p <4) {
printf("[SKIP-ESP|]\n");
}
spi=*p++<<24;
spi+=*p++<<16;
spi+=*p++<<8;
spi+=*p;
printf("\nSKIP-ESP: SPI\t\t\t0x%08x\t", spi );
if (spi==0) {
printf("NO association\n");
len=0;
} else if (spi==1) {
printf("SKIP association\n");
len=expected_iv_size;
if (!expected_iv_size) {
printf("Warning: IV size not defined by SKIP Crypt Alg!\n");
} else expected_iv_size=0;
} else if (spi<256) {
printf("UNKNOWN association\n");
len=0;
} else {
printf("DYNAMIC association\n");
len=0;
}
p++;
if ((unsigned short) (end - p) < len) {
printf("[SKIP-ESP|] (truncated)\n");
return;
}
printf("SKIP-ESP: Initalization Vector\t");
if (len) {
for (i = 0; i < len; i++) {
printf("%02x ", (unsigned char) *p++);
if (i<len-1 && (i+1)%16==0) printf("\n\t\t\t\t");
}
} else {
printf("UNDEFINED (unknown algorithm)");
}
printf("\n");
}