diff options
author | Hakan Olsson <ho@cvs.openbsd.org> | 1999-09-30 07:22:56 +0000 |
---|---|---|
committer | Hakan Olsson <ho@cvs.openbsd.org> | 1999-09-30 07:22:56 +0000 |
commit | 2b4ada78073333ab67bae9272ef23c5aae301d0a (patch) | |
tree | 608cb5f80fce9639ec3ebfc72f4be32536f59ec3 /usr.sbin/tcpdump | |
parent | 5e968c689b0e8819ee0e4bc8958b0963fdb18439 (diff) |
Improve tcpdump's IKE/ISAKMP knowledge. (jakob@, hugh@ ok)
Diffstat (limited to 'usr.sbin/tcpdump')
-rw-r--r-- | usr.sbin/tcpdump/print-ike.c | 386 |
1 files changed, 332 insertions, 54 deletions
diff --git a/usr.sbin/tcpdump/print-ike.c b/usr.sbin/tcpdump/print-ike.c index 2d36358b84a..82abf648d58 100644 --- a/usr.sbin/tcpdump/print-ike.c +++ b/usr.sbin/tcpdump/print-ike.c @@ -22,11 +22,14 @@ * By Tero Kivinen <kivinen@ssh.fi>, Tero Mononen <tmo@ssh.fi>, * Tatu Ylonen <ylo@ssh.fi> and Timo J. Rinne <tri@ssh.fi> * in co-operation with SSH Communications Security, Espoo, Finland + * + * Rewritten and extended (quite a lot, too) by Hakan Olsson <ho@openbsd.org> + * */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-ike.c,v 1.2 1999/09/16 17:08:01 brad Exp $ (XXX)"; + "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-ike.c,v 1.3 1999/09/30 07:22:55 ho Exp $ (XXX)"; #endif #include <sys/param.h> @@ -65,8 +68,11 @@ struct isakmp_header { static int isakmp_doi; -#define FLAGS_ENCRYPTION 1 -#define FLAGS_COMMIT 2 +/* XXX Perhaps move these to an <ike.h> file? */ + +#define IPSEC_DOI 1 + +#define PROTO_ISAKMP 1 #define PAYLOAD_NONE 0 #define PAYLOAD_SA 1 @@ -81,12 +87,173 @@ static int isakmp_doi; #define PAYLOAD_NONCE 10 #define PAYLOAD_NOTIFICATION 11 #define PAYLOAD_DELETE 12 +#define PAYLOAD_VENDOR 13 -#define IPSEC_DOI 1 +#define IKE_ATTR_ENCRYPTION_ALGORITHM 1 +#define IKE_ATTR_HASH_ALGORITHM 2 +#define IKE_ATTR_AUTHENTICATION_METHOD 3 +#define IKE_ATTR_GROUP_DESC 4 +#define IKE_ATTR_GROUP_TYPE 5 +#define IKE_ATTR_LIFE_TYPE 11 -static void isakmp_pl_print(register u_char type, - register u_char *payload, - register int paylen); +#define IKE_ATTR_ENCRYPT_INITIALIZER \ + { "NONE", "DES_CBS", "IDEA_CBC", "BLOWFISH_CBC", \ + "RC5_R16_B64_CBC", "3DES_CBC", "CAST_CBC", \ + } +#define IKE_ATTR_HASH_INITIALIZER \ + { "NONE", "MD5", "SHA", "TIGER", \ + } +#define IKE_ATTR_AUTH_INITIALIZER \ + { "NONE", "PRE_SHARED", "DSS", "RSA_SIG", \ + "RSA_ENC", "RSA_ENC_REV", \ + } +#define IKE_ATTR_GROUP_DESC_INITIALIZER \ + { "NONE", "MODP_768", "MODP_1024", \ + "E2CN_155", "E2CN_185", "MODP_1536", \ + } +#define IKE_ATTR_GROUP_INITIALIZER \ + { "NONE", "MODP", "ECP", "E2CN", \ + } +#define IKE_ATTR_SA_DURATION_INITIALIZER \ + { "NONE", "SECONDS", "KILOBYTES", \ + } + +#define IKE_ATTR_INITIALIZER \ + { "NONE", /* 0 (not in RFC) */ \ + "ENCRYPTION_ALGORITHM", /* 1 */ \ + "HASH_ALGORITHM", /* 2 */ \ + "AUTHENTICATION_METHOD", /* 3 */ \ + "GROUP_DESCRIPTION", /* 4 */ \ + "GROUP_TYPE", /* 5 */ \ + "GROUP_PRIME", /* 6 */ \ + "GROUP_GENERATOR_1", /* 7 */ \ + "GROUP_GENERATOR_2", /* 8 */ \ + "GROUP_CURVE_1", /* 9 */ \ + "GROUP_CURVE_2", /* 10 */ \ + "LIFE_TYPE", /* 11 */ \ + "LIFE_DURATION", /* 12 */ \ + "PRF", /* 13 */ \ + "KEY_LENGTH", /* 14 */ \ + "FIELD_SIZE", /* 15 */ \ + "GROUP_ORDER", /* 16 */ \ + } + +#define IKE_SITUATION_IDENTITY_ONLY 1 +#define IKE_SITUATION_SECRECY 2 +#define IKE_SITUATION_INTEGRITY 4 +/* Mask is all the above, i.e 1+2+4 = 7 */ +#define IKE_SITUATION_MASK 7 + +#define IKE_PAYLOAD_TYPES_INITIALIZER \ + { "NONE", /* 0 */ \ + "SA", /* 1 */ \ + "PROPOSAL", /* 2 */ \ + "TRANSFORM", /* 3 */ \ + "KEY_EXCH", /* 4 */ \ + "ID", /* 5 */ \ + "CERT", /* 6 */ \ + "CERTREQUEST", /* 7 */ \ + "HASH", /* 8 */ \ + "SIG", /* 9 */ \ + "NONCE", /* 10 */ \ + "NOTIFICATION", /* 11 */ \ + "DELETE", /* 12 */ \ + "VENDOR", /* 13 */ \ + } + +/* Exchange types */ +#define EXCHANGE_NONE 0 +#define EXCHANGE_BASE 1 +#define EXCHANGE_ID_PROT 2 +#define EXCHANGE_AUTH_ONLY 3 +#define EXCHANGE_AGGRESSIVE 4 +#define EXCHANGE_INFO 5 +#define EXCHANGE_QUICK_MODE 32 +#define EXCHANGE_NEW_GROUP_MODE 33 + +/* Exchange types */ +#define IKE_EXCHANGE_TYPES_INITIALIZER \ + { "NONE", /* 0 */ \ + "BASE", /* 1 */ \ + "ID_PROT", /* 2 */ \ + "AUTH_ONLY", /* 3 */ \ + "AGGRESSIVE", /* 4 */ \ + "INFO", /* 5 */ \ + /* step up to type 32 with unknowns */ \ + "unknown", "unknown", "unknown", "unknown", \ + "unknown", "unknown", "unknown", "unknown", \ + "unknown", "unknown", "unknown", "unknown", \ + "unknown", "unknown", "unknown", "unknown", \ + "unknown", "unknown", "unknown", "unknown", \ + "unknown", "unknown", "unknown", "unknown", \ + "unknown", "unknown", \ + "QUICK_MODE", /* 32 */ \ + "NEW_GROUP_MODE", /* 33 */ \ + } + +#define FLAGS_ENCRYPTION 1 +#define FLAGS_COMMIT 2 +#define FLAGS_AUTH_ONLY 4 + +#define CERT_NONE 0 +#define CERT_PKCS 1 +#define CERT_PGP 2 +#define CERT_DNS 3 +#define CERT_X509_SIG 4 +#define CERT_X509_KE 5 +#define CERT_KERBEROS 6 +#define CERT_CRL 7 +#define CERT_ARL 8 +#define CERT_SPKI 9 +#define CERT_X509_ATTR 10 + +#define NOTIFY_INVALID_PAYLOAD_TYPE 1 +#define NOTIFY_DOI_NOT_SUPPORTED 2 +#define NOTIFY_SITUATION_NOT_SUPPORTED 3 +#define NOTIFY_INVALID_COOKIE 4 +#define NOTIFY_INVALID_MAJOR_VERSION 5 +#define NOTIFY_INVALID_MINOR_VERSION 6 +#define NOTIFY_INVALID_EXCHANGE_TYPE 7 +#define NOTIFY_INVALID_FLAGS 8 +#define NOTIFY_INVALID_MESSAGE_ID 9 +#define NOTIFY_INVALID_PROTOCOL_ID 10 +#define NOTIFY_INVALID_SPI 11 +#define NOTIFY_INVALID_TRANSFORM_ID 12 +#define NOTIFY_ATTRIBUTES_NOT_SUPPORTED 13 +#define NOTIFY_NO_PROPOSAL_CHOSEN 14 +#define NOTIFY_BAD_PROPOSAL_SYNTAX 15 +#define NOTIFY_PAYLOAD_MALFORMED 16 +#define NOTIFY_INVALID_KEY_INFORMATION 17 +#define NOTIFY_INVALID_ID_INFORMATION 18 +#define NOTIFY_INVALID_CERT_ENCODING 19 +#define NOTIFY_INVALID_CERTIFICATE 20 +#define NOTIFY_CERT_TYPE_UNSUPPORTED 21 +#define NOTIFY_INVALID_CERT_AUTHORITY 22 +#define NOTIFY_INVALID_HASH_INFORMATION 23 +#define NOTIFY_AUTHENTICATION_FAILED 24 +#define NOTIFY_INVALID_SIGNATURE 25 +#define NOTIFY_ADDRESS_NOTIFICATION 26 +#define NOTIFY_NOTIFY_SA_LIFETIME 27 +#define NOTIFY_CERTIFICATE_UNAVAILABLE 28 +#define NOTIFY_UNSUPPORTED_EXCHANGE_TYPE 29 +#define NOTIFY_UNEQUAL_PAYLOAD_LENGTHS 30 + +static void isakmp_pl_print(register u_char type, register u_char *payload); + +int ike_tab_level = 0; + +#define SMALL_TABS 4 +#define SPACES " " +const char *ike_tab_offset(void) +{ + const char *p, *endline; + static const char line[] = SPACES; + + endline = line + sizeof line - 1; + p = endline - SMALL_TABS * (ike_tab_level); + + return (p > line ? p : line); +} /* * Print isakmp requests @@ -99,6 +266,7 @@ void isakmp_print(register const u_char *cp, register int length) u_char nextpayload, np1; u_int paylen; int encrypted; + static const char *exgtypes[] = IKE_EXCHANGE_TYPES_INITIALIZER; encrypted = 0; @@ -118,7 +286,13 @@ void isakmp_print(register const u_char *cp, register int length) printf(" isakmp"); - printf(" v%d.%d\n\t", ih->version >> 4, ih->version & 0xf); + printf(" v%d.%d", ih->version >> 4, ih->version & 0xf); + + printf(" exchange "); + if (ih->exgtype < (sizeof exgtypes/sizeof exgtypes[0])) + printf("%s", exgtypes[ih->exgtype]); + else + printf("%d (unknown)", ih->exgtype); if (ih->flags & FLAGS_ENCRYPTION) { printf(" encrypted"); @@ -129,7 +303,8 @@ void isakmp_print(register const u_char *cp, register int length) printf(" commit"); } - printf(" cookie: %02x%02x%02x%02x%02x%02x%02x%02x->%02x%02x%02x%02x%02x%02x%02x%02x\n\t", + printf("\n\tcookie: %02x%02x%02x%02x%02x%02x%02x%02x->" + "%02x%02x%02x%02x%02x%02x%02x%02x", ih->init_cookie[0], ih->init_cookie[1], ih->init_cookie[2], ih->init_cookie[3], ih->init_cookie[4], ih->init_cookie[5], @@ -140,19 +315,18 @@ void isakmp_print(register const u_char *cp, register int length) ih->resp_cookie[6], ih->resp_cookie[7]); TCHECK(ih->msgid, sizeof(ih->msgid)); - printf(" msgid:%02x%02x%02x%02x", + printf(" msgid: %02x%02x%02x%02x", ih->msgid[0], ih->msgid[1], ih->msgid[2], ih->msgid[3]); TCHECK(ih->length, sizeof(ih->length)); - printf(" length %d", ntohl(ih->length)); + printf(" len: %d", ntohl(ih->length)); if (ih->version > 16) { printf(" new version"); return; } - /* now, process payloads */ payload = ih->payloads; nextpayload = ih->nextpayload; @@ -162,16 +336,9 @@ void isakmp_print(register const u_char *cp, register int length) return; } - while (nextpayload != 0) { - np1 = payload[0]; - paylen = (payload[2] << 8) + payload[3]; - printf("\n\t\tload: %02x len: %04x", - nextpayload, paylen); - TCHECK(payload[0], paylen); - isakmp_pl_print(nextpayload, payload, paylen); - payload += paylen; - nextpayload = np1; - } + /* if verbose, print payload data */ + if (vflag) + isakmp_pl_print(nextpayload, payload); return; @@ -181,65 +348,161 @@ trunc: void isakmp_sa_print(register u_char *buf, register int len) { - isakmp_doi = ntohl((*(u_int32_t *)(buf+4))); - printf(" SA doi: %d", - isakmp_doi, (isakmp_doi == IPSEC_DOI ? "(ipsec)" : "")); - printf(" situation\n"); + u_int32_t situation = ntohl(*(u_int32_t *)(buf + 4)); + isakmp_doi = ntohl((*(u_int32_t *)buf)); + printf(" DOI: %d", isakmp_doi); + if (isakmp_doi == IPSEC_DOI) { + printf("(IPSEC) situation: "); + if (situation & IKE_SITUATION_IDENTITY_ONLY) + printf("IDENTITY_ONLY "); + if (situation & IKE_SITUATION_SECRECY) + printf("SECRECY "); + if (situation & IKE_SITUATION_INTEGRITY) + printf("INTEGRITY "); + if ((situation & IKE_SITUATION_MASK) == 0) + printf("0x%x (unknown)", situation); + isakmp_pl_print (PAYLOAD_PROPOSAL, buf + 8); + } + else + printf(" situation: (unknown)"); } - -void isakmp_proposal_print(register u_char *buf, register int len) + +int isakmp_attribute_print(register u_char *buf) { - u_char *spis; - int spisize, numspi, i; - - spisize = buf[6]; - numspi = buf[7]; - - - printf(" proposal number: %d protocol: %d spisize: %d #spi: %d", - buf[4], buf[5], spisize, numspi); - - spis = buf+8; - while (numspi) { - printf("\n\t "); - for (i=0; i<spisize; i++) { - printf("%02x", *spis); - spis++; + static char *attrs[] = IKE_ATTR_INITIALIZER; + static char *attr_enc[] = IKE_ATTR_ENCRYPT_INITIALIZER; + static char *attr_hash[] = IKE_ATTR_HASH_INITIALIZER; + static char *attr_auth[] = IKE_ATTR_AUTH_INITIALIZER; + static char *attr_gdesc[] = IKE_ATTR_GROUP_DESC_INITIALIZER; + static char *attr_gtype[] = IKE_ATTR_GROUP_INITIALIZER; + static char *attr_ltype[] = IKE_ATTR_SA_DURATION_INITIALIZER; + + unsigned short type = buf[0]<<8 | buf[1]; + unsigned short length = 0, p; + + printf("\n\t%sattribute %s = ", ike_tab_offset(), + ((type & 0x7fff) < sizeof attrs / sizeof attrs[0] ? + attrs[type & 0x7fff] : "unknown")); + if (!(type >> 15)) { + length = buf[2]<<8 | buf[3]; + for (p = 0; p < length; p++) + printf("%02x", (char)*(buf + 4 + p)); + } + else { + p = buf[2]<<8 | buf[3]; + +#define CASE_PRINT(TYPE,var) \ + case TYPE : \ + if (p < sizeof var / sizeof var [0]) \ + printf("%s", var [p]); \ + else \ + printf("%d (unknown)", p); \ + break; + + switch(type & 0x7fff) { + CASE_PRINT(IKE_ATTR_ENCRYPTION_ALGORITHM, attr_enc); + CASE_PRINT(IKE_ATTR_HASH_ALGORITHM, attr_hash); + CASE_PRINT(IKE_ATTR_AUTHENTICATION_METHOD, attr_auth); + CASE_PRINT(IKE_ATTR_GROUP_DESC, attr_gdesc); + CASE_PRINT(IKE_ATTR_GROUP_TYPE, attr_gtype); + CASE_PRINT(IKE_ATTR_LIFE_TYPE, attr_ltype); + default: + printf("%d", p); } } + return length + 4; } + +void isakmp_transform_print(register u_char *buf, register int len) +{ + u_char *attr = buf + 4; + + printf("\n\t%stransform: %d ID: %d", ike_tab_offset(), + (char)buf[0], (char)buf[1]); + ike_tab_level++; + while((int)(attr - buf) < len - 4) /* Skip last 'NONE' attr */ + attr += isakmp_attribute_print(attr); + ike_tab_level--; +} + +void isakmp_proposal_print(register u_char *buf, register int len) +{ + printf(" proposal: %d proto: %d(%s) spisz: %d xforms: %d", + buf[0], buf[1], (buf[1] == PROTO_ISAKMP ? "ISAKMP" : "unknown"), + buf[2], buf[3]); + + if((char)buf[3] > 0) + isakmp_pl_print(PAYLOAD_TRANSFORM, buf+4); +} + void isakmp_ke_print(register u_char *buf, register int len) { - if (isakmp_doi != IPSEC_DOI) { - printf("KE unknown doi\n"); + if (isakmp_doi != IPSEC_DOI) return; - } + + printf(" <KE payload data (not shown)> len: %d", len); +} + +void isakmp_id_print(register u_char *buf, register int len) +{ + if (isakmp_doi != IPSEC_DOI) + return; + + printf(" <ID payload data (not shown)> len: %d", len); } -void isakmp_pl_print(register u_char type, - register u_char *buf, - register int len) +void isakmp_vendor_print(register u_char *buf, register int len) { + u_char *p = buf; + + if (isakmp_doi != IPSEC_DOI) + return; + + printf(" \""); + for(p = buf; (int)(p - buf) < len; p++) + printf("%c",(isprint(*p) ? *p : '.')); + printf("\""); +} + +void isakmp_pl_print(register u_char type, register u_char *buf) +{ + static const char *pltypes[] = IKE_PAYLOAD_TYPES_INITIALIZER; + int next_type = buf[0]; + int this_len = buf[2]<<8 | buf[3]; + + printf("\n\t%spayload: %s len: %d", ike_tab_offset(), + (type < (sizeof pltypes/sizeof pltypes[0]) ? + pltypes[type] : "<unknown>"), this_len); + + if ((u_char *)&(buf[0]) > snapend - this_len) + goto pltrunc; + + ike_tab_level++; switch(type) { case PAYLOAD_NONE: return; + case PAYLOAD_SA: - isakmp_sa_print(buf, len); + isakmp_sa_print(buf+4, this_len); break; case PAYLOAD_PROPOSAL: - isakmp_proposal_print(buf, len); + isakmp_proposal_print(buf+4, this_len); break; case PAYLOAD_TRANSFORM: + isakmp_transform_print(buf+4, this_len); break; case PAYLOAD_KE: - isakmp_ke_print(buf, len); + isakmp_ke_print(buf+4, this_len); break; case PAYLOAD_ID: + isakmp_id_print(buf+4, this_len); + break; + case PAYLOAD_CERT: case PAYLOAD_CERTREQUEST: case PAYLOAD_HASH: @@ -248,12 +511,27 @@ void isakmp_pl_print(register u_char type, case PAYLOAD_NONCE: #if 0 - isakmp_nonce_print(buf, len); + isakmp_nonce_print(buf+4, this_len); #endif break; case PAYLOAD_NOTIFICATION: case PAYLOAD_DELETE: + break; + + case PAYLOAD_VENDOR: + isakmp_vendor_print(buf+4, this_len); + break; + default: } + ike_tab_level--; + + if(next_type) /* Recurse over next payload */ + isakmp_pl_print(next_type, buf + this_len); + + return; + +pltrunc: + fputs(" [|isakmp]", stdout); } |