/* packet-isakmp.c * Routines for the Internet Security Association and Key Management Protocol * (ISAKMP) (RFC 2408) and the Internet IP Security Domain of Interpretation * for ISAKMP (RFC 2407) * Brad Robel-Forrest * * $Id: packet-isakmp.c,v 1.59 2002/08/28 21:00:18 jmayer Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #ifdef NEED_SNPRINTF_H # include "snprintf.h" #endif #include #include "ipproto.h" #define isakmp_min(a, b) ((a= 4) { /* XXX = > 4? */ if (payload < NUM_LOAD_TYPES) { (*strfuncs[payload].func)(tvb, offset + 4, payload_length - 4, ntree, -1); } else { proto_tree_add_text(ntree, tvb, offset + 4, payload_length - 4, "Payload"); } } else { proto_tree_add_text(ntree, tvb, offset + 4, 0, "Payload (bogus, length is %u, must be at least 4)", payload_length); payload_length = 4; } offset += payload_length; length -= payload_length; } } static void dissect_isakmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; struct isakmp_hdr hdr; proto_item * ti; proto_tree * isakmp_tree = NULL; struct udp_encap_hdr encap_hdr; guint32 len; static const guint8 non_esp_marker[4] = { 0, 0, 0, 0 }; tvbuff_t * next_tvb; if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISAKMP"); if (check_col(pinfo->cinfo, COL_INFO)) col_clear(pinfo->cinfo, COL_INFO); hdr.length = tvb_get_ntohl(tvb, offset + sizeof(hdr) - sizeof(hdr.length)); if (tree) { ti = proto_tree_add_item(tree, proto_isakmp, tvb, offset, hdr.length, FALSE); isakmp_tree = proto_item_add_subtree(ti, ett_isakmp); } tvb_memcpy(tvb, (guint8 *)&encap_hdr, 0, sizeof(encap_hdr)); if (encap_hdr.non_esp_marker[0] == 0xFF) { if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, "UDP encapsulated IPSec - NAT Keepalive"); return; } if (memcmp(encap_hdr.non_esp_marker,non_esp_marker,4) == 0) { if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, "UDP encapsulated IPSec - ESP"); if (tree) proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(encap_hdr.non_esp_marker), "Non-ESP-Marker"); offset += sizeof(encap_hdr.non_esp_marker); next_tvb = tvb_new_subset(tvb, offset, -1, -1); call_dissector(esp_handle, next_tvb, pinfo, tree); return; } hdr.exch_type = tvb_get_guint8(tvb, sizeof(hdr.icookie) + sizeof(hdr.rcookie) + sizeof(hdr.next_payload) + sizeof(hdr.version)); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, exchtype2str(hdr.exch_type)); if (tree) { tvb_memcpy(tvb, (guint8 *)&hdr.icookie, offset, sizeof(hdr.icookie)); proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.icookie), "Initiator cookie: 0x%s", tvb_bytes_to_str(tvb, offset, sizeof(hdr.icookie))); offset += sizeof(hdr.icookie); tvb_memcpy(tvb, (guint8 *)&hdr.rcookie, offset, sizeof(hdr.rcookie)); proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.rcookie), "Responder cookie: 0x%s", tvb_bytes_to_str(tvb, offset, sizeof(hdr.rcookie))); offset += sizeof(hdr.rcookie); hdr.next_payload = tvb_get_guint8(tvb, offset); proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.next_payload), "Next payload: %s (%u)", payloadtype2str(hdr.next_payload), hdr.next_payload); offset += sizeof(hdr.next_payload); hdr.version = tvb_get_guint8(tvb, offset); proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.version), "Version: %u.%u", hi_nibble(hdr.version), lo_nibble(hdr.version)); offset += sizeof(hdr.version); hdr.exch_type = tvb_get_guint8(tvb, offset); proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.exch_type), "Exchange type: %s (%u)", exchtype2str(hdr.exch_type), hdr.exch_type); offset += sizeof(hdr.exch_type); { proto_item * fti; proto_tree * ftree; hdr.flags = tvb_get_guint8(tvb, offset); fti = proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.flags), "Flags"); ftree = proto_item_add_subtree(fti, ett_isakmp_flags); proto_tree_add_text(ftree, tvb, offset, 1, "%s", decode_boolean_bitfield(hdr.flags, E_FLAG, sizeof(hdr.flags)*8, "Encryption", "No encryption")); proto_tree_add_text(ftree, tvb, offset, 1, "%s", decode_boolean_bitfield(hdr.flags, C_FLAG, sizeof(hdr.flags)*8, "Commit", "No commit")); proto_tree_add_text(ftree, tvb, offset, 1, "%s", decode_boolean_bitfield(hdr.flags, A_FLAG, sizeof(hdr.flags)*8, "Authentication", "No authentication")); offset += sizeof(hdr.flags); } proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.message_id), "Message ID: 0x%s", tvb_bytes_to_str(tvb, offset, sizeof(hdr.message_id))); offset += sizeof(hdr.message_id); proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.length), "Length: %u", hdr.length); offset += sizeof(hdr.length); len = hdr.length - sizeof(hdr); if (hdr.flags & E_FLAG) { if (len && isakmp_tree) { proto_tree_add_text(isakmp_tree, tvb, offset, len, "Encrypted payload (%d byte%s)", len, plurality(len, "", "s")); } } else dissect_payloads(tvb, isakmp_tree, hdr.next_payload, offset, len); } } static proto_tree * dissect_payload_header(tvbuff_t *tvb, int offset, int length, guint8 payload, guint8 *next_payload_p, guint16 *payload_length_p, proto_tree *tree) { guint8 next_payload; guint16 payload_length; proto_item * ti; proto_tree * ntree; if (length < 4) { proto_tree_add_text(tree, tvb, offset, length, "Not enough room in payload for all transforms"); return NULL; } next_payload = tvb_get_guint8(tvb, offset); payload_length = tvb_get_ntohs(tvb, offset + 2); ti = proto_tree_add_text(tree, tvb, offset, payload_length, "%s payload", loadtype2str(payload)); ntree = proto_item_add_subtree(ti, ett_isakmp_payload); proto_tree_add_text(ntree, tvb, offset, 1, "Next payload: %s (%u)", payloadtype2str(next_payload), next_payload); proto_tree_add_text(ntree, tvb, offset+2, 2, "Length: %u", payload_length); *next_payload_p = next_payload; *payload_length_p = payload_length; return ntree; } static void dissect_sa(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { guint32 doi; guint32 situation; if (length < 4) { proto_tree_add_text(tree, tvb, offset, length, "DOI %s (length is %u, should be >= 4)", tvb_bytes_to_str(tvb, offset, length), length); return; } doi = tvb_get_ntohl(tvb, offset); proto_tree_add_text(tree, tvb, offset, 4, "Domain of interpretation: %s (%u)", doitype2str(doi), doi); offset += 4; length -= 4; if (doi == 1) { /* IPSEC */ if (length < 4) { proto_tree_add_text(tree, tvb, offset, length, "Situation: %s (length is %u, should be >= 4)", tvb_bytes_to_str(tvb, offset, length), length); return; } situation = tvb_get_ntohl(tvb, offset); proto_tree_add_text(tree, tvb, offset, 4, "Situation: %s (%u)", situation2str(situation), situation); offset += 4; length -= 4; dissect_payloads(tvb, tree, LOAD_TYPE_PROPOSAL, offset, length); } else { /* Unknown */ proto_tree_add_text(tree, tvb, offset, length, "Situation: %s", tvb_bytes_to_str(tvb, offset, length)); } } static void dissect_proposal(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { guint8 protocol_id; guint8 spi_size; guint8 num_transforms; guint8 next_payload; guint16 payload_length; proto_tree * ntree; guint8 proposal_num; proposal_num = tvb_get_guint8(tvb, offset); proto_item_append_text(tree, " # %d",proposal_num); proto_tree_add_text(tree, tvb, offset, 1, "Proposal number: %u", proposal_num); offset += 1; length -= 1; protocol_id = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "Protocol ID: %s (%u)", proto2str(protocol_id), protocol_id); offset += 1; length -= 1; spi_size = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "SPI size: %u", spi_size); offset += 1; length -= 1; num_transforms = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "Number of transforms: %u", num_transforms); offset += 1; length -= 1; if (spi_size) { proto_tree_add_text(tree, tvb, offset, spi_size, "SPI: %s", tvb_bytes_to_str(tvb, offset, spi_size)); offset += spi_size; length -= spi_size; } while (num_transforms > 0) { ntree = dissect_payload_header(tvb, offset, length, LOAD_TYPE_TRANSFORM, &next_payload, &payload_length, tree); if (ntree == NULL) break; if (length < payload_length) { proto_tree_add_text(tree, tvb, offset + 4, length, "Not enough room in payload for all transforms"); break; } if (payload_length >= 4) dissect_transform(tvb, offset + 4, payload_length - 4, ntree, protocol_id); else proto_tree_add_text(ntree, tvb, offset + 4, payload_length - 4, "Payload"); offset += payload_length; length -= payload_length; num_transforms--; } } static void dissect_transform(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int protocol_id) { guint8 transform_id; guint8 transform_num; transform_num = tvb_get_guint8(tvb, offset); proto_item_append_text(tree," # %d",transform_num); proto_tree_add_text(tree, tvb, offset, 1, "Transform number: %u", transform_num); offset += 1; length -= 1; transform_id = tvb_get_guint8(tvb, offset); switch (protocol_id) { default: proto_tree_add_text(tree, tvb, offset, 1, "Transform ID: %u", transform_id); break; case 1: /* ISAKMP */ proto_tree_add_text(tree, tvb, offset, 1, "Transform ID: %s (%u)", trans2str(transform_id), transform_id); break; case 2: /* AH */ proto_tree_add_text(tree, tvb, offset, 1, "Transform ID: %s (%u)", ah_trans2str(transform_id), transform_id); break; case 3: /* ESP */ proto_tree_add_text(tree, tvb, offset, 1, "Transform ID: %s (%u)", esp_trans2str(transform_id), transform_id); break; case 4: /* IPCOMP */ proto_tree_add_text(tree, tvb, offset, 1, "Transform ID: %s (%u)", ipcomp_trans2str(transform_id), transform_id); break; } offset += 3; length -= 3; while (length>0) { const char *str; int ike_phase1 = 0; guint16 aft = tvb_get_ntohs(tvb, offset); guint16 type = aft & 0x7fff; guint16 len; guint32 val; guint pack_len; if (protocol_id == 1 && transform_id == 1) { ike_phase1 = 1; str = p1_atttype2str(type); } else { str = atttype2str(type); } if (aft & 0x8000) { val = tvb_get_ntohs(tvb, offset + 2); proto_tree_add_text(tree, tvb, offset, 4, "%s (%u): %s (%u)", str, type, value2str(ike_phase1, type, val), val); offset += 4; length -= 4; } else { len = tvb_get_ntohs(tvb, offset + 2); pack_len = 4 + len; if (!get_num(tvb, offset + 4, len, &val)) { proto_tree_add_text(tree, tvb, offset, pack_len, "%s (%u): ", str, type, len); } else { proto_tree_add_text(tree, tvb, offset, pack_len, "%s (%u): %s (%u)", str, type, value2str(ike_phase1, type, val), val); } offset += pack_len; length -= pack_len; } } } static void dissect_key_exch(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { proto_tree_add_text(tree, tvb, offset, length, "Key Exchange Data"); } static void dissect_id(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { guint8 id_type; guint8 protocol_id; guint16 port; id_type = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "ID type: %s (%u)", id2str(id_type), id_type); offset += 1; length -= 1; protocol_id = tvb_get_guint8(tvb, offset); if (protocol_id == 0) { proto_tree_add_text(tree, tvb, offset, 1, "Protocol ID: Unused"); } else { proto_tree_add_text(tree, tvb, offset, 1, "Protocol ID: %s (%u)", ipprotostr(protocol_id), protocol_id); } offset += 1; length -= 1; port = tvb_get_ntohs(tvb, offset); if (port == 0) proto_tree_add_text(tree, tvb, offset, 2, "Port: Unused"); else proto_tree_add_text(tree, tvb, offset, 2, "Port: %u", port); offset += 2; length -= 2; switch (id_type) { case 1: proto_tree_add_text(tree, tvb, offset, length, "Identification data: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4))); break; case 2: case 3: proto_tree_add_text(tree, tvb, offset, length, "Identification data: %.*s", length, tvb_get_ptr(tvb, offset, length)); break; case 4: proto_tree_add_text(tree, tvb, offset, length, "Identification data: %s/%s", ip_to_str(tvb_get_ptr(tvb, offset, 4)), ip_to_str(tvb_get_ptr(tvb, offset+4, 4))); break; default: proto_tree_add_text(tree, tvb, offset, length, "Identification Data"); break; } } static void dissect_cert(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { guint8 cert_enc; cert_enc = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "Certificate encoding: %u - %s", cert_enc, certtype2str(cert_enc)); offset += 1; length -= 1; proto_tree_add_text(tree, tvb, offset, length, "Certificate Data"); } static void dissect_certreq(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { guint8 cert_type; cert_type = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "Certificate type: %u - %s", cert_type, certtype2str(cert_type)); offset += 1; length -= 1; proto_tree_add_text(tree, tvb, offset, length, "Certificate Authority"); } static void dissect_hash(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { proto_tree_add_text(tree, tvb, offset, length, "Hash Data"); } static void dissect_sig(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { proto_tree_add_text(tree, tvb, offset, length, "Signature Data"); } static void dissect_nonce(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { proto_tree_add_text(tree, tvb, offset, length, "Nonce Data"); } static void dissect_notif(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { guint32 doi; guint8 protocol_id; guint8 spi_size; guint16 msgtype; doi = tvb_get_ntohl(tvb, offset); proto_tree_add_text(tree, tvb, offset, 4, "Domain of Interpretation: %s (%u)", doitype2str(doi), doi); offset += 4; length -= 4; protocol_id = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "Protocol ID: %s (%u)", proto2str(protocol_id), protocol_id); offset += 1; length -= 1; spi_size = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "SPI size: %u", spi_size); offset += 1; length -= 1; msgtype = tvb_get_ntohs(tvb, offset); proto_tree_add_text(tree, tvb, offset, 2, "Message type: %s (%u)", msgtype2str(msgtype), msgtype); offset += 2; length -= 2; if (spi_size) { proto_tree_add_text(tree, tvb, offset, spi_size, "Security Parameter Index"); offset += spi_size; length -= spi_size; } if (length > 0) proto_tree_add_text(tree, tvb, offset, length, "Notification Data"); } static void dissect_delete(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { guint32 doi; guint8 protocol_id; guint8 spi_size; guint16 num_spis; guint16 i; doi = tvb_get_ntohl(tvb, offset); proto_tree_add_text(tree, tvb, offset, 4, "Domain of Interpretation: %s (%u)", doitype2str(doi), doi); offset += 4; length -= 4; protocol_id = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "Protocol ID: %s (%u)", proto2str(protocol_id), protocol_id); offset += 1; length -= 1; spi_size = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "SPI size: %u", spi_size); offset += 1; length -= 1; num_spis = tvb_get_ntohs(tvb, offset); proto_tree_add_text(tree, tvb, offset, 2, "Number of SPIs: %u", num_spis); offset += 2; length -= 2; for (i = 0; i < num_spis; ++i) { if (length < spi_size) { proto_tree_add_text(tree, tvb, offset, length, "Not enough room in payload for all SPI's"); break; } proto_tree_add_text(tree, tvb, offset, spi_size, "SPI (%d)", i); offset += spi_size; length -= spi_size; } } static void dissect_vid(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { guint32 CPproduct, CPversion; const guint8 * pVID; proto_item * pt; proto_tree * ntree; pVID = tvb_get_ptr(tvb, offset, length); pt = proto_tree_add_text(tree, tvb, offset, length, "Vendor ID: "); if (memcmp(pVID, VID_MS_W2K_WXP, isakmp_min(VID_MS_LEN, length)) == 0) proto_item_append_text(pt, "Microsoft Win2K/WinXP"); else if (memcmp(pVID, VID_CP, isakmp_min(VID_CP_LEN, length)) == 0) { proto_item_append_text(pt, "Check Point"); offset += VID_CP_LEN; CPproduct = tvb_get_ntohl(tvb, offset); ntree = proto_item_add_subtree(pt, ett_isakmp_payload); pt = proto_tree_add_text(ntree, tvb, offset, sizeof(CPproduct), "Check Point Product: "); switch (CPproduct) { case 1: proto_item_append_text(pt, "VPN-1"); break; case 2: proto_item_append_text(pt, "SecuRemote/SecureClient"); break; default: proto_item_append_text(pt, "Unknown CP product!"); break; } offset += sizeof(CPproduct); CPversion = tvb_get_ntohl(tvb, offset); pt = proto_tree_add_text(ntree, tvb, offset, length, "Version: "); switch (CPversion) { case 2: proto_item_append_text(pt, "4.1"); break; case 3: proto_item_append_text(pt, "4.1 SP-1"); break; case 4002: proto_item_append_text(pt, "4.1 (SP-2 or above)"); break; case 5000: proto_item_append_text(pt, "NG"); break; case 5001: proto_item_append_text(pt, "NG Feature Pack 1"); break; case 5002: proto_item_append_text(pt, "NG Feature Pack 2"); break; case 5003: proto_item_append_text(pt, "NG Feature Pack 3"); break; default: proto_item_append_text(pt, " Uknown CP version!"); break; } } else if (memcmp(pVID, VID_CYBERGUARD, isakmp_min(VID_LEN, length)) == 0) proto_item_append_text(pt, "Cyber Guard"); else if (memcmp(pVID, VID_SAFENET, isakmp_min(VID_LEN, length)) == 0) proto_item_append_text(pt, "SafeNet"); else if (memcmp(pVID, VID_draft_ietf_ipsec_nat_t_ike_03, isakmp_min(VID_LEN, length)) == 0) proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-03"); else proto_item_append_text(pt, "unknown vendor ID: 0x%s",tvb_bytes_to_str(tvb, offset, length)); } static void dissect_config(tvbuff_t *tvb, int offset, int length, proto_tree *tree, int unused _U_) { guint8 type; type = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "Type %s (%u)",attrtype2str(type),type); offset += 2; length -= 2; proto_tree_add_text(tree, tvb, offset, 2, "Identifier: %u", tvb_get_ntohs(tvb, offset)); offset += 2; length -= 2; while(length>0) { guint16 aft = tvb_get_ntohs(tvb, offset); guint16 type = aft & 0x7fff; guint16 len; guint32 val; guint pack_len; if (aft & 0x8000) { val = tvb_get_ntohs(tvb, offset + 2); proto_tree_add_text(tree, tvb, offset, 4, "%s (%u)", cfgattrident2str(type), val); offset += 4; length -= 4; } else { len = tvb_get_ntohs(tvb, offset + 2); pack_len = 4 + len; if (!get_num(tvb, offset + 4, len, &val)) { proto_tree_add_text(tree, tvb, offset, pack_len, "%s: ", cfgattrident2str(type), len); } else { proto_tree_add_text(tree, tvb, offset, 4, "%s (%ue)", cfgattrident2str(type), val); } offset += pack_len; length -= pack_len; } } } static const char * payloadtype2str(guint8 type) { if (type < NUM_LOAD_TYPES) return strfuncs[type].str; if (type < 128) return "RESERVED"; if (type < 256) return "Private USE"; return "Huh? You should never see this! Shame on you!"; } static const char * exchtype2str(guint8 type) { #define NUM_EXCHSTRS 7 static const char * exchstrs[NUM_EXCHSTRS] = { "NONE", "Base", "Identity Protection (Main Mode)", "Authentication Only", "Aggressive", "Informational", "Transaction (Config Mode)" }; if (type < NUM_EXCHSTRS) return exchstrs[type]; if (type < 32) return "ISAKMP Future Use"; switch (type) { case 32: return "Quick Mode"; case 33: return "New Group Mode"; } if (type < 240) return "DOI Specific Use"; if (type < 256) return "Private Use"; return "Huh? You should never see this! Shame on you!"; } static const char * doitype2str(guint32 type) { if (type == 1) return "IPSEC"; return "Unknown DOI Type"; } static const char * msgtype2str(guint16 type) { #define NUM_PREDEFINED 31 static const char *msgs[NUM_PREDEFINED] = { "", "INVALID-PAYLOAD-TYPE", "DOI-NOT-SUPPORTED", "SITUATION-NOT-SUPPORTED", "INVALID-COOKIE", "INVALID-MAJOR-VERSION", "INVALID-MINOR-VERSION", "INVALID-EXCHANGE-TYPE", "INVALID-FLAGS", "INVALID-MESSAGE-ID", "INVALID-PROTOCOL-ID", "INVALID-SPI", "INVALID-TRANSFORM-ID", "ATTRIBUTES-NOT-SUPPORTED", "NO-PROPOSAL-CHOSEN", "BAD-PROPOSAL-SYNTAX", "PAYLOAD-MALFORMED", "INVALID-KEY-INFORMATION", "INVALID-ID-INFORMATION", "INVALID-CERT-ENCODING", "INVALID-CERTIFICATE", "CERT-TYPE-UNSUPPORTED", "INVALID-CERT-AUTHORITY", "INVALID-HASH-INFORMATION", "AUTHENTICATION-FAILED", "INVALID-SIGNATURE", "ADDRESS-NOTIFICATION", "NOTIFY-SA-LIFETIME", "CERTIFICATE-UNAVAILABLE", "UNSUPPORTED-EXCHANGE-TYPE", "UNEQUAL-PAYLOAD-LENGTHS" }; if (type < NUM_PREDEFINED) return msgs[type]; if (type < 8192) return "RESERVED (Future Use)"; if (type < 16384) return "Private Use"; if (type < 16385) return "CONNECTED"; if (type < 24576) return "RESERVED (Future Use) - status"; if (type < 24577) return "RESPONDER-LIFETIME"; if (type < 24578) return "REPLAY-STATUS"; if (type < 24579) return "INITIAL-CONTACT"; if (type < 32768) return "DOI-specific codes"; if (type < 40960) return "Private Use - status"; if (type < 65535) return "RESERVED (Future Use) - status (2)"; return "Huh? You should never see this! Shame on you!"; } static const char * situation2str(guint32 type) { #define SIT_MSG_NUM 1024 #define SIT_IDENTITY 0x01 #define SIT_SECRECY 0x02 #define SIT_INTEGRITY 0x04 static char msg[SIT_MSG_NUM]; int n = 0; char * sep = ""; int ret; if (type & SIT_IDENTITY) { ret = snprintf(msg, SIT_MSG_NUM-n, "%sIDENTITY", sep); if (ret == -1) { /* Some versions of snprintf return -1 if they'd truncate the output. */ return msg; } n += ret; sep = " & "; } if (type & SIT_SECRECY) { if (n >= SIT_MSG_NUM) { /* No more room. */ return msg; } ret = snprintf(msg, SIT_MSG_NUM-n, "%sSECRECY", sep); if (ret == -1) { /* Some versions of snprintf return -1 if they'd truncate the output. */ return msg; } n += ret; sep = " & "; } if (type & SIT_INTEGRITY) { if (n >= SIT_MSG_NUM) { /* No more room. */ return msg; } ret = snprintf(msg, SIT_MSG_NUM-n, "%sINTEGRITY", sep); if (ret == -1) { /* Some versions of snprintf return -1 if they'd truncate the output. */ return msg; } n += ret; sep = " & "; } return msg; } static const char * value2str(int ike_p1, guint16 att_type, guint16 value) { if (value == 0) return "RESERVED"; if (!ike_p1) { switch (att_type) { case 1: switch (value) { case 0: return "RESERVED"; case 1: return "Seconds"; case 2: return "Kilobytes"; default: return "UNKNOWN-SA-VALUE"; } case 2: return "Duration-Value"; case 3: return "Group-Value"; case 4: switch (value) { case 0: return "RESERVED"; case 1: return "Tunnel"; case 2: return "Transport"; case 61440: return "Check Point IPSec UDP Encapsulation"; case 61443: return "UDP-Encapsulated-Tunnel (draft)"; case 61444: return "UDP-Encapsulated-Transport (draft)"; default: return "UNKNOWN-ENCAPSULATION-VALUE"; } case 5: switch (value) { case 0: return "RESERVED"; case 1: return "HMAC-MD5"; case 2: return "HMAC-SHA"; case 3: return "DES-MAC"; case 4: return "KPDK"; case 5: return "HMAC-SHA2-256"; case 6: return "HMAC-SHA2-384"; case 7: return "HMAC-SHA2-512"; default: return "UNKNOWN-AUTHENTICATION-VALUE"; } case 6: return "Key-Length"; case 7: return "Key-Rounds"; case 8: return "Compress-Dictionary-size"; case 9: return "Compress Private Algorithm"; default: return "UNKNOWN-ATTRIBUTE-TYPE"; } } else { switch (att_type) { case 1: switch (value) { case 1: return "DES-CBC"; case 2: return "IDEA-CBC"; case 3: return "BLOWFISH-CBC"; case 4: return "RC5-R16-B64-CBC"; case 5: return "3DES-CBC"; case 6: return "CAST-CBC"; case 7: return "AES-CBC"; default: return "UNKNOWN-ENCRYPTION-ALG"; } case 2: switch (value) { case 1: return "MD5"; case 2: return "SHA"; case 3: return "TIGER"; case 4: return "SHA2-256"; case 5: return "SHA2-384"; case 6: return "SHA2-512"; default: return "UNKNOWN-HASH-ALG"; } case 3: switch (value) { case 1: return "PSK"; case 2: return "DSS-SIG"; case 3: return "RSA-SIG"; case 4: return "RSA-ENC"; case 5: return "RSA-Revised-ENC"; case 6: return "Encryption with El-Gamal"; case 7: return "Revised encryption with El-Gamal"; case 8: return "ECDSA signatures"; case 64221: return "HybridInitRSA"; case 64222: return "HybridRespRSA"; case 64223: return "HybridInitDSS"; case 64224: return "HybridRespDSS"; case 65001: return "XAUTHInitPreShared"; case 65002: return "XAUTHRespPreShared"; case 65003: return "XAUTHInitDSS"; case 65004: return "XAUTHRespDSS"; case 65005: return "XAUTHInitRSA"; case 65006: return "XAUTHRespRSA"; case 65007: return "XAUTHInitRSAEncryption"; case 65008: return "XAUTHRespRSAEncryption"; case 65009: return "XAUTHInitRSARevisedEncryption"; case 65010: return "XAUTHRespRSARevisedEncryption"; default: return "UNKNOWN-AUTH-METHOD"; } case 4: return grpdesc2str(value); case 6: case 7: case 8: case 9: case 10: case 16: return "Group-Value"; case 5: switch (value) { case 1: return "MODP"; case 2: return "ECP"; case 3: return "EC2N"; default: return "UNKNOWN-GROUPT-TYPE"; } case 11: switch (value) { case 1: return "Seconds"; case 2: return "Kilobytes"; default: return "UNKNOWN-SA-VALUE"; } case 12: return "Duration-Value"; case 13: return "PRF-Value"; case 14: return "Key-Length"; case 15: return "Field-Size"; default: return "UNKNOWN-ATTRIBUTE-TYPE"; } } } static const char * attrtype2str(guint8 type) { switch (type) { case 0: return "Reserved"; case 1: return "ISAKMP_CFG_REQUEST"; case 2: return "ISAKMP_CFG_REPLY"; case 3: return "ISAKMP_CFG_SET"; case 4: return "ISAKMP_CFG_ACK"; } if(type < 127) return "Future use"; return "Private use"; } static const char * cfgattrident2str(guint16 ident) { #define NUM_ATTR_DEFINED 12 static const char *msgs[NUM_PREDEFINED] = { "RESERVED", "INTERNAL_IP4_ADDRESS", "INTERNAL_IP4_NETMASK", "INTERNAL_IP4_DNS", "INTERNAL_IP4_NBNS", "INTERNAL_ADDRESS_EXPIREY", "INTERNAL_IP4_DHCP", "APPLICATION_VERSION" "INTERNAL_IP6_ADDRESS", "INTERNAL_IP6_NETMASK", "INTERNAL_IP6_DNS", "INTERNAL_IP6_NBNS", "INTERNAL_IP6_DHCP", }; if(ident < NUM_ATTR_DEFINED) return msgs[ident]; if(ident < 16383) return "Future use"; switch(ident) { case 16520: return "XAUTH_TYPE"; case 16521: return "XAUTH_USER_NAME"; case 16522: return "XAUTH_USER_PASSWORD"; case 16523: return "XAUTH_PASSCODE"; case 16524: return "XAUTH_MESSAGE"; case 16525: return "XAUTH_CHALLANGE"; case 16526: return "XAUTH_DOMAIN"; case 16527: return "XAUTH_STATUS"; case 16528: return "XAUTH_NEXT_PIN"; case 16529: return "XAUTH_ANSWER"; default: return "Private use"; } } static const char * certtype2str(guint8 type) { #define NUM_CERTTYPE 11 static const char *msgs[NUM_CERTTYPE] = { "NONE", "PKCS #7 wrapped X.509 certificate", "PGP Certificate", "DNS Signed Key", "X.509 Certificate - Signature", "X.509 Certificate - Key Exchange", "Kerberos Tokens", "Certificate Revocation List (CRL)", "Authority Revocation List (ARL)", "SPKI Certificate", "X.509 Certificate - Attribute", }; if(type > NUM_CERTTYPE) return "RESERVED"; return msgs[type]; } static gboolean get_num(tvbuff_t *tvb, int offset, guint16 len, guint32 *num_p) { switch (len) { case 1: *num_p = tvb_get_guint8(tvb, offset); break; case 2: *num_p = tvb_get_ntohs(tvb, offset); break; case 3: *num_p = tvb_get_ntoh24(tvb, offset); break; case 4: *num_p = tvb_get_ntohl(tvb, offset); break; default: return FALSE; } return TRUE; } void proto_register_isakmp(void) { /* static hf_register_info hf[] = { { &variable, { "Name", "isakmp.abbreviation", TYPE, VALS_POINTER }}, };*/ static gint *ett[] = { &ett_isakmp, &ett_isakmp_flags, &ett_isakmp_payload, }; proto_isakmp = proto_register_protocol("Internet Security Association and Key Management Protocol", "ISAKMP", "isakmp"); /* proto_register_field_array(proto_isakmp, hf, array_length(hf));*/ proto_register_subtree_array(ett, array_length(ett)); } void proto_reg_handoff_isakmp(void) { dissector_handle_t isakmp_handle; /* * Get handle for the AH & ESP dissectors. */ esp_handle = find_dissector("esp"); ah_handle = find_dissector("ah"); isakmp_handle = create_dissector_handle(dissect_isakmp, proto_isakmp); dissector_add("udp.port", UDP_PORT_ISAKMP, isakmp_handle); dissector_add("tcp.port", TCP_PORT_ISAKMP, isakmp_handle); }