Wireshark-dev: [Wireshark-dev] [PATCH v2] Add support for the CIPSO IPv4 option
From: Paul Moore <paul.moore@xxxxxx>
Date: Fri, 19 Jan 2007 16:17:12 -0500
Attached is the an updated version of the patch I sent on January 17th. The only two changes are the shift from glib-2.0 specific string functions to the more portable standard C library string functions as well as a small bugfix found during the shift. Below is the text/abstract from the original posting. *** This patch adds support for the IPv4 Commercial IP Security Option (CIPSO) as defined in the IETF draft, draft-ietf-cipso-ipsecurity-01.txt. While this draft has long since expired, it has become a de-facto standard for labeled networking with support from several commercial Multi-Level Security (MLS) operating systems such as HP-UX CMW and Trusted Solaris; in addition, Linux Kernels 2.6.19 and later provide support for CIPSO in conjunction with SELinux. Copies of the expired CIPSO draft can be found at the NetLabel project page: * http://netlabel.sf.net A sample packet capture demonstrating the three types of CIPSO tags can be found here: * http://free.linux.hp.com/~pmoore/files/tcpdump_out.pcap This patch is backed against the current SVN sources and has been fuzz tested using the fuzz-test.sh script. Please consider it for inclusion into the wireshark source tree. Thank you. *** -- paul moore linux security @ hp
Subject: Add support for the CIPSO IPv4 option This patch adds support for the IPv4 Commercial IP Security Option (CIPSO) as defined in the IETF draft, draft-ietf-cipso-ipsecurity-01.txt. While this draft has long since expired, it has become a de-facto standard for labeled networking with support from several commercial Multi-Level Security (MLS) operating systems such as HP-UX CMW and Trusted Solaris; in addition, Linux Kernels 2.6.19 and later provide support for CIPSO in conjunction with SELinux. Copies of the expired CIPSO draft can be found at the NetLabel project page: * http://netlabel.sf.net A sample packet capture demonstrating the three types of CIPSO tags can be found here: * http://free.linux.hp.com/~pmoore/files/tcpdump_out.pcap This patch is backed against the current SVN sources and has been fuzz tested using the fuzz-test.sh script. Please consider it for inclusion into the wireshark source tree. Thank you. --- epan/dissectors/packet-ip.c | 265 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) Index: wireshark/epan/dissectors/packet-ip.c =================================================================== --- wireshark.orig/epan/dissectors/packet-ip.c +++ wireshark/epan/dissectors/packet-ip.c @@ -13,6 +13,11 @@ * by Maria-Luiza Crivat <luizacri@xxxxxxxxx> * & Brice Augustin <bricecotte@xxxxxxxxx> * + * Wednesday, January 17, 2006 + * Support for the CIPSO IPv4 option + * (http://sourceforge.net/docman/display_doc.php?docid=34650&group_id=174379) + * by Paul Moore <paul.moore@xxxxxx> + * * 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 @@ -124,6 +129,7 @@ static gint ett_ip_options = -1; static gint ett_ip_option_sec = -1; static gint ett_ip_option_route = -1; static gint ett_ip_option_timestamp = -1; +static gint ett_ip_option_cipso = -1; static gint ett_ip_fragments = -1; static gint ett_ip_fragment = -1; static gint ett_ip_checksum = -1; @@ -326,6 +332,7 @@ static gint ett_icmp_mpls_stack_object = #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT) +#define IPOPT_CIPSO (6 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_RR (7 |IPOPT_CONTROL) #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY) @@ -339,6 +346,7 @@ static gint ett_icmp_mpls_stack_object = #define IPOLEN_SID 4 #define IPOLEN_SSRR_MIN 3 #define IPOLEN_RA 4 +#define IPOLEN_CIPSO_MIN 10 #define IPSEC_UNCLASSIFIED 0x0000 #define IPSEC_CONFIDENTIAL 0xF135 @@ -461,6 +469,254 @@ dissect_ipopt_security(const ip_tcp_opt tvb_get_guint8(tvb, offset + 2)); } +/* USHRT_MAX can hold at most 5 (base 10) digits (6 for the NULL byte) */ +#define USHRT_MAX_STRLEN 6 + +/* Maximum CIPSO tag length: + * (IP hdr max)60 - (IPv4 hdr std)20 - (CIPSO base)6 = 34 */ +#define CIPSO_TAG_LEN_MAX 34 + +/* The Commercial IP Security Option (CIPSO) is defined in IETF draft + * draft-ietf-cipso-ipsecurity-01.txt and FIPS 188, a copy of both documents + * can be found at the NetLabel project page, http://netlabel.sf.net. */ +static void +dissect_ipopt_cipso(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, + guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree) +{ + proto_tree *field_tree = NULL; + proto_item *tf; + guint tagtype, taglen; + int offset_max = offset + optlen; + + tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s", optp->name); + field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + offset += 2; + + proto_tree_add_text(field_tree, tvb, offset, 4, "DOI: %u", + tvb_get_ntohl(tvb, offset)); + offset += 4; + + /* loop through all of the tags in the CIPSO option */ + while (offset < offset_max) { + tagtype = tvb_get_guint8(tvb, offset); + + if ((offset + 1) < offset_max) + taglen = tvb_get_guint8(tvb, offset + 1); + else + taglen = 1; + + switch (tagtype) { + case 0: + /* padding - skip this tag */ + offset += 1; + continue; + break; + case 1: + /* restrictive bitmap, see CIPSO draft section 3.4.2 for tag format */ + if ((taglen < 4) || (taglen > CIPSO_TAG_LEN_MAX) || + ((offset + (int)taglen - 1) > offset_max)) { + proto_tree_add_text(field_tree, tvb, offset, offset_max - offset, + "Malformed CIPSO tag"); + return; + } + + proto_tree_add_text(field_tree, tvb, offset, 1, + "Tag Type: Restrictive Category Bitmap (%u)", + tagtype); + + /* skip past alignment octet */ + offset += 3; + + proto_tree_add_text(field_tree, tvb, offset, 1, "Sensitivity Level: %u", + tvb_get_guint8(tvb, offset)); + offset += 1; + + if (taglen > 4) { + guint bit_spot = 0; + guint byte_spot = 0; + unsigned char bitmask; + char *cat_str; + char *cat_str_tmp = ep_alloc(USHRT_MAX_STRLEN); + size_t cat_str_len; + const guint8 *val_ptr = tvb_get_ptr(tvb, offset, taglen - 4); + + /* this is just a guess regarding string size, but we grow it below + * if needed */ + cat_str_len = 256; + cat_str = ep_alloc0(cat_str_len); + + /* we checked the length above so the highest category value + * possibile here is 240 */ + while (byte_spot < (taglen - 4)) { + bitmask = 0x80; + bit_spot = 0; + while (bit_spot < 8) { + if (val_ptr[byte_spot] & bitmask) { + snprintf(cat_str_tmp, USHRT_MAX_STRLEN, "%u", + byte_spot * 8 + bit_spot); + cat_str_tmp[USHRT_MAX_STRLEN - 1] = '\0'; + if (cat_str_len < (strlen(cat_str) + 2 + USHRT_MAX_STRLEN)) { + char *cat_str_new; + while (cat_str_len < (strlen(cat_str) + 2 + USHRT_MAX_STRLEN)) + cat_str_len += cat_str_len; + cat_str_new = ep_alloc(cat_str_len); + strncpy(cat_str_new, cat_str, cat_str_len); + cat_str_new[cat_str_len - 1] = '\0'; + cat_str = cat_str_new; + } + if (cat_str[0] != '\0') + strncat(cat_str, ",", cat_str_len - 1); + strncat(cat_str, cat_str_tmp, cat_str_len - 1); + } + bit_spot++; + bitmask >>= 1; + } + byte_spot++; + } + + if (cat_str) + proto_tree_add_text(field_tree, tvb, offset, taglen - 4, + "Categories: %s", cat_str); + else + proto_tree_add_text(field_tree, tvb, offset, taglen - 4, + "Categories: ERROR PARSING CATEGORIES"); + + offset += taglen - 4; + } + break; + case 2: + /* enumerated categories, see CIPSO draft section 3.4.3 for tag format */ + if ((taglen < 4) || (taglen > CIPSO_TAG_LEN_MAX) || + ((offset + (int)taglen - 1) > offset_max)) { + proto_tree_add_text(field_tree, tvb, offset, offset_max - offset, + "Malformed CIPSO tag"); + return; + } + + proto_tree_add_text(field_tree, tvb, offset, 1, + "Tag Type: Enumerated Categories (%u)", tagtype); + + /* skip past alignment octet */ + offset += 3; + + /* sensitvity level */ + proto_tree_add_text(field_tree, tvb, offset, 1, "Sensitivity Level: %u", + tvb_get_guint8(tvb, offset)); + offset += 1; + + if (taglen > 4) { + int offset_max_cat = offset + taglen - 4; + char *cat_str = ep_alloc0(USHRT_MAX_STRLEN * 15); + char *cat_str_tmp = ep_alloc(USHRT_MAX_STRLEN); + + while ((offset + 2) <= offset_max_cat) { + snprintf(cat_str_tmp, USHRT_MAX_STRLEN, "%u", + tvb_get_ntohs(tvb, offset)); + offset += 2; + cat_str_tmp[USHRT_MAX_STRLEN - 1] = '\0'; + if (cat_str[0] != '\0') + strncat(cat_str, ",", USHRT_MAX_STRLEN * 15 - 1); + strncat(cat_str, cat_str_tmp, USHRT_MAX_STRLEN * 15 - 1); + } + + proto_tree_add_text(field_tree, tvb, offset - taglen + 4, taglen - 4, + "Categories: %s", cat_str); + } + break; + case 5: + /* ranged categories, see CIPSO draft section 3.4.4 for tag format */ + if ((taglen < 4) || (taglen > CIPSO_TAG_LEN_MAX) || + ((offset + (int)taglen - 1) > offset_max)) { + proto_tree_add_text(field_tree, tvb, offset, offset_max - offset, + "Malformed CIPSO tag"); + return; + } + + proto_tree_add_text(field_tree, tvb, offset, 1, + "Tag Type: Ranged Categories (%u)", tagtype); + + /* skip past alignment octet */ + offset += 3; + + /* sensitvity level */ + proto_tree_add_text(field_tree, tvb, offset, 1, "Sensitivity Level: %u", + tvb_get_guint8(tvb, offset)); + offset += 1; + + if (taglen > 4) { + guint16 cat_low, cat_high; + int offset_max_cat = offset + taglen - 4; + char *cat_str = ep_alloc0(USHRT_MAX_STRLEN * 16); + char *cat_str_tmp = ep_alloc(USHRT_MAX_STRLEN * 2); + + while ((offset + 2) <= offset_max_cat) { + cat_high = tvb_get_ntohs(tvb, offset); + if ((offset + 4) <= offset_max_cat) { + cat_low = tvb_get_ntohs(tvb, offset + 2); + offset += 4; + } else { + cat_low = 0; + offset += 2; + } + if (cat_low != cat_high) + snprintf(cat_str_tmp, USHRT_MAX_STRLEN * 2, "%u-%u", + cat_high, cat_low); + else + snprintf(cat_str_tmp, USHRT_MAX_STRLEN * 2, "%u", cat_high); + if (cat_str[0] != '\0') + strncat(cat_str, ",", USHRT_MAX_STRLEN * 16 - 1); + strncat(cat_str, cat_str_tmp, USHRT_MAX_STRLEN * 16 - 1); + } + + proto_tree_add_text(field_tree, tvb, offset - taglen + 4, taglen - 4, + "Categories: %s", cat_str); + } + break; + case 6: + /* permissive categories, see FIPS 188 section 6.9 for tag format */ + if ((taglen < 4) || (taglen > CIPSO_TAG_LEN_MAX) || + ((offset + (int)taglen - 1) > offset_max)) { + proto_tree_add_text(field_tree, tvb, offset, offset_max - offset, + "Malformed CIPSO tag"); + return; + } + + proto_tree_add_text(field_tree, tvb, offset, 1, + "Tag Type: Permissive Categories (%u)", tagtype); + proto_tree_add_text(field_tree, tvb, offset + 2, taglen - 2, "Tag data"); + offset += taglen; + break; + case 7: + /* free form, see FIPS 188 section 6.10 for tag format */ + if ((taglen < 2) || (taglen > CIPSO_TAG_LEN_MAX) || + ((offset + (int)taglen - 1) > offset_max)) { + proto_tree_add_text(field_tree, tvb, offset, offset_max - offset, + "Malformed CIPSO tag"); + return; + } + + proto_tree_add_text(field_tree, tvb, offset, 1, + "Tag Type: Free Form (%u)", tagtype); + proto_tree_add_text(field_tree, tvb, offset + 2, taglen - 2, "Tag data"); + offset += taglen; + break; + default: + /* unknown tag - stop parsing this IPv4 option */ + if ((offset + 1) <= offset_max) { + taglen = tvb_get_guint8(tvb, offset + 1); + proto_tree_add_text(field_tree, tvb, offset, 1, + "Tag Type: Unknown (%u) (%u bytes)", + tagtype, taglen); + return; + } + proto_tree_add_text(field_tree, tvb, offset, 1, + "Tag Type: Unknown (%u) (invalid format)", + tagtype); + return; + } + } +} + static void dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, guint optlen, packet_info *pinfo _U_, @@ -644,6 +900,14 @@ static const ip_tcp_opt ipopts[] = { dissect_ipopt_route }, { + IPOPT_CIPSO, + "Commercial IP security option", + &ett_ip_option_cipso, + VARIABLE_LENGTH, + IPOLEN_CIPSO_MIN, + dissect_ipopt_cipso + }, + { IPOPT_RR, "Record route", &ett_ip_option_route, @@ -2124,6 +2388,7 @@ proto_register_ip(void) &ett_ip_option_sec, &ett_ip_option_route, &ett_ip_option_timestamp, + &ett_ip_option_cipso, &ett_ip_fragments, &ett_ip_fragment, &ett_ip_checksum,
- Follow-Ups:
- Re: [Wireshark-dev] [PATCH v2] Add support for the CIPSO IPv4 option
- From: Jaap Keuter
- Re: [Wireshark-dev] [PATCH v2] Add support for the CIPSO IPv4 option
- Prev by Date: Re: [Wireshark-dev] Use of ep/se mem
- Next by Date: Re: [Wireshark-dev] Wireshark 0.99.5pre1 is now available
- Previous by thread: Re: [Wireshark-dev] Wireshark 0.99.5pre1 is now available
- Next by thread: Re: [Wireshark-dev] [PATCH v2] Add support for the CIPSO IPv4 option
- Index(es):