summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-imf.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-imf.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-imf.c')
-rw-r--r--epan/dissectors/packet-imf.c1410
1 files changed, 1410 insertions, 0 deletions
diff --git a/epan/dissectors/packet-imf.c b/epan/dissectors/packet-imf.c
new file mode 100644
index 00000000..95be6b1a
--- /dev/null
+++ b/epan/dissectors/packet-imf.c
@@ -0,0 +1,1410 @@
+/* packet-imf.c
+ * Routines for Internet Message Format (IMF) packet disassembly
+ *
+ * Copyright (c) 2007 by Graeme Lunt
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1999 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/uat.h>
+#include <epan/expert.h>
+#include <wsutil/str_util.h>
+
+#include <epan/tap.h>
+#include <epan/export_object.h>
+
+#include "packet-ber.h"
+#include "packet-media-type.h"
+#include "packet-imf.h"
+#include "packet-ess.h"
+#include "packet-p1.h"
+
+void proto_register_imf(void);
+void proto_reg_handoff_imf(void);
+
+static int imf_eo_tap = -1;
+
+#define PNAME "Internet Message Format"
+#define PSNAME "IMF"
+#define PFNAME "imf"
+
+static int proto_imf = -1;
+
+static int hf_imf_date = -1;
+static int hf_imf_from = -1;
+static int hf_imf_sender = -1;
+static int hf_imf_reply_to = -1;
+static int hf_imf_to = -1;
+static int hf_imf_cc = -1;
+static int hf_imf_bcc = -1;
+static int hf_imf_message_id = -1;
+static int hf_imf_in_reply_to = -1;
+static int hf_imf_references = -1;
+static int hf_imf_subject = -1;
+static int hf_imf_comments = -1;
+static int hf_imf_user_agent = -1;
+static int hf_imf_keywords = -1;
+static int hf_imf_resent_date = -1;
+static int hf_imf_resent_from = -1;
+static int hf_imf_resent_sender = -1;
+static int hf_imf_resent_to = -1;
+static int hf_imf_resent_cc = -1;
+static int hf_imf_resent_bcc = -1;
+static int hf_imf_resent_message_id = -1;
+static int hf_imf_return_path = -1;
+static int hf_imf_received = -1;
+static int hf_imf_content_type = -1;
+static int hf_imf_content_type_type = -1;
+static int hf_imf_content_type_parameters = -1;
+static int hf_imf_content_id = -1;
+static int hf_imf_content_transfer_encoding = -1;
+static int hf_imf_content_description = -1;
+static int hf_imf_mime_version = -1;
+static int hf_imf_thread_index = -1;
+static int hf_imf_lines = -1;
+static int hf_imf_precedence = -1;
+static int hf_imf_ext_mailer = -1;
+static int hf_imf_ext_mimeole = -1;
+static int hf_imf_ext_tnef_correlator = -1;
+static int hf_imf_ext_expiry_date = -1;
+static int hf_imf_ext_uidl = -1;
+static int hf_imf_ext_authentication_warning = -1;
+static int hf_imf_ext_virus_scanned = -1;
+static int hf_imf_ext_original_to = -1;
+static int hf_imf_extension = -1;
+static int hf_imf_extension_type = -1;
+static int hf_imf_extension_value = -1;
+
+/* RFC 2156 */
+static int hf_imf_autoforwarded = -1;
+static int hf_imf_autosubmitted = -1;
+static int hf_imf_x400_content_identifier = -1;
+static int hf_imf_content_language = -1;
+static int hf_imf_conversion = -1;
+static int hf_imf_conversion_with_loss = -1;
+static int hf_imf_delivery_date = -1;
+static int hf_imf_discarded_x400_ipms_extensions = -1;
+static int hf_imf_discarded_x400_mts_extensions = -1;
+static int hf_imf_dl_expansion_history = -1;
+static int hf_imf_deferred_delivery = -1;
+static int hf_imf_expires = -1;
+static int hf_imf_importance = -1;
+static int hf_imf_incomplete_copy = -1;
+static int hf_imf_latest_delivery_time = -1;
+static int hf_imf_message_type = -1;
+static int hf_imf_original_encoded_information_types = -1;
+static int hf_imf_originator_return_address = -1;
+static int hf_imf_priority = -1;
+static int hf_imf_reply_by = -1;
+static int hf_imf_sensitivity = -1;
+static int hf_imf_supersedes = -1;
+static int hf_imf_x400_content_type = -1;
+static int hf_imf_x400_mts_identifier = -1;
+static int hf_imf_x400_originator = -1;
+static int hf_imf_x400_received = -1;
+static int hf_imf_x400_recipients = -1;
+
+static int hf_imf_delivered_to = -1;
+
+static int hf_imf_message_text = -1;
+
+static int hf_imf_display_name = -1;
+static int hf_imf_address = -1;
+/* static int hf_imf_mailbox_list = -1; */
+static int hf_imf_mailbox_list_item = -1;
+/* static int hf_imf_address_list = -1; */
+static int hf_imf_address_list_item = -1;
+
+/* draft-zeilenga-email-seclabel-04 */
+static int hf_imf_siolabel = -1;
+static int hf_imf_siolabel_marking = -1;
+static int hf_imf_siolabel_fgcolor = -1;
+static int hf_imf_siolabel_bgcolor = -1;
+static int hf_imf_siolabel_type = -1;
+static int hf_imf_siolabel_label = -1;
+static int hf_imf_siolabel_unknown = -1;
+
+static int ett_imf = -1;
+static int ett_imf_content_type = -1;
+static int ett_imf_mailbox = -1;
+static int ett_imf_group = -1;
+static int ett_imf_mailbox_list = -1;
+static int ett_imf_address_list = -1;
+static int ett_imf_siolabel = -1;
+static int ett_imf_extension = -1;
+static int ett_imf_message_text = -1;
+
+static dissector_handle_t imf_handle;
+
+static expert_field ei_imf_unknown_param = EI_INIT;
+
+/* Used for IMF Export Object feature */
+typedef struct _imf_eo_t {
+ gchar *filename;
+ gchar *sender_data;
+ gchar *subject_data;
+ guint32 payload_len;
+ gchar *payload_data;
+} imf_eo_t;
+
+static tap_packet_status
+imf_eo_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data, tap_flags_t flags _U_)
+{
+ export_object_list_t *object_list = (export_object_list_t *)tapdata;
+ const imf_eo_t *eo_info = (const imf_eo_t *)data;
+ export_object_entry_t *entry;
+
+ if(eo_info) { /* We have data waiting for us */
+ /* These values will be freed when the Export Object window
+ * is closed. */
+ entry = g_new(export_object_entry_t, 1);
+
+ gchar *start = g_strrstr_len(eo_info->sender_data, -1, "<");
+ gchar *stop = g_strrstr_len(eo_info->sender_data, -1, ">");
+ /* Only include the string inside of the "<>" brackets. If there is nothing between
+ the two brackets use the sender_data string */
+ if(start && stop && stop > start && (stop - start) > 2){
+ entry->hostname = ws_strdup_printf("%.*s", (int) (stop - start - 1), start + 1);
+ } else {
+ entry->hostname = g_strdup(eo_info->sender_data);
+ }
+
+ entry->pkt_num = pinfo->num;
+ entry->content_type = g_strdup("EML file");
+ entry->filename = ws_strdup_printf("%s.eml", eo_info->subject_data);
+ entry->payload_len = eo_info->payload_len;
+ entry->payload_data = (guint8 *)g_memdup2(eo_info->payload_data, eo_info->payload_len);
+
+ object_list->add_entry(object_list->gui_data, entry);
+
+ return TAP_PACKET_REDRAW; /* State changed - window should be redrawn */
+ } else {
+ return TAP_PACKET_DONT_REDRAW; /* State unchanged - no window updates needed */
+ }
+}
+
+
+struct imf_field {
+ char *name; /* field name - in lower case for matching purposes */
+ int *hf_id; /* wireshark field */
+ void (*subdissector)(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
+ gboolean add_to_col_info; /* add field to column info */
+};
+
+#define NO_SUBDISSECTION NULL
+
+static void dissect_imf_mailbox(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
+static void dissect_imf_address(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
+static void dissect_imf_address_list(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
+static void dissect_imf_mailbox_list(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
+static void dissect_imf_siolabel(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
+
+static struct imf_field imf_fields[] = {
+ {"unknown-extension", &hf_imf_extension_type, NO_SUBDISSECTION, FALSE}, /* unknown extension */
+ {"date", &hf_imf_date, NO_SUBDISSECTION, FALSE}, /* date-time */
+ {"from", &hf_imf_from, dissect_imf_mailbox_list , TRUE}, /* mailbox_list */
+ {"sender", &hf_imf_sender, dissect_imf_mailbox, FALSE}, /* mailbox */
+ {"reply-to", &hf_imf_reply_to, dissect_imf_address_list , FALSE}, /* address_list */
+ {"to", &hf_imf_to, dissect_imf_address_list , FALSE}, /* address_list */
+ {"cc", &hf_imf_cc, dissect_imf_address_list , FALSE}, /* address_list */
+ {"bcc", &hf_imf_bcc, dissect_imf_address_list , FALSE}, /* address_list */
+ {"message-id", &hf_imf_message_id, NO_SUBDISSECTION, FALSE}, /* msg-id */
+ {"in-reply-to", &hf_imf_in_reply_to, NO_SUBDISSECTION, FALSE}, /* msg-id */
+ {"references", &hf_imf_references, NO_SUBDISSECTION, FALSE}, /* msg-id */
+ {"subject", &hf_imf_subject, NO_SUBDISSECTION, TRUE}, /* unstructured */
+ {"comments", &hf_imf_comments, NO_SUBDISSECTION, FALSE}, /* unstructured */
+ {"user-agent", &hf_imf_user_agent, NO_SUBDISSECTION, FALSE}, /* unstructured */
+ {"keywords", &hf_imf_keywords, NULL, FALSE}, /* phrase_list */
+ {"resent-date", &hf_imf_resent_date, NO_SUBDISSECTION, FALSE},
+ {"resent-from", &hf_imf_resent_from, dissect_imf_mailbox_list, FALSE},
+ {"resent-sender", &hf_imf_resent_sender, dissect_imf_mailbox, FALSE},
+ {"resent-to", &hf_imf_resent_to, dissect_imf_address_list, FALSE},
+ {"resent-cc", &hf_imf_resent_cc, dissect_imf_address_list, FALSE},
+ {"resent-bcc", &hf_imf_resent_bcc, dissect_imf_address_list, FALSE},
+ {"resent-message-id", &hf_imf_resent_message_id, NO_SUBDISSECTION, FALSE},
+ {"return-path", &hf_imf_return_path, NULL, FALSE},
+ {"received", &hf_imf_received, NO_SUBDISSECTION, FALSE},
+ /* these are really multi-part - but we parse them anyway */
+ {"content-type", &hf_imf_content_type, NULL, FALSE}, /* handled separately as a special case */
+ {"content-id", &hf_imf_content_id, NULL, FALSE},
+ {"content-description", &hf_imf_content_description, NULL, FALSE},
+ {"content-transfer-encoding", &hf_imf_content_transfer_encoding, NULL, FALSE},
+ {"mime-version", &hf_imf_mime_version, NO_SUBDISSECTION, FALSE},
+ /* MIXER - RFC 2156 */
+ {"autoforwarded", &hf_imf_autoforwarded, NULL, FALSE},
+ {"autosubmitted", &hf_imf_autosubmitted, NULL, FALSE},
+ {"x400-content-identifier", &hf_imf_x400_content_identifier, NULL, FALSE},
+ {"content-language", &hf_imf_content_language, NULL, FALSE},
+ {"conversion", &hf_imf_conversion, NULL, FALSE},
+ {"conversion-with-loss", &hf_imf_conversion_with_loss, NULL, FALSE},
+ {"delivery-date", &hf_imf_delivery_date, NULL, FALSE},
+ {"discarded-x400-ipms-extensions", &hf_imf_discarded_x400_ipms_extensions, NULL, FALSE},
+ {"discarded-x400-mts-extensions", &hf_imf_discarded_x400_mts_extensions, NULL, FALSE},
+ {"dl-expansion-history", &hf_imf_dl_expansion_history, NULL, FALSE},
+ {"deferred-delivery", &hf_imf_deferred_delivery, NULL, FALSE},
+ {"expires", &hf_imf_expires, NULL, FALSE},
+ {"importance", &hf_imf_importance, NULL, FALSE},
+ {"incomplete-copy", &hf_imf_incomplete_copy, NULL, FALSE},
+ {"latest-delivery-time", &hf_imf_latest_delivery_time, NULL, FALSE},
+ {"message-type", &hf_imf_message_type, NULL, FALSE},
+ {"original-encoded-information-types", &hf_imf_original_encoded_information_types, NULL, FALSE},
+ {"originator-return-address", &hf_imf_originator_return_address, NULL, FALSE},
+ {"priority", &hf_imf_priority, NULL, FALSE},
+ {"reply-by", &hf_imf_reply_by, NULL, FALSE},
+ {"sensitivity", &hf_imf_sensitivity, NULL, FALSE},
+ {"supersedes", &hf_imf_supersedes, NULL, FALSE},
+ {"x400-content-type", &hf_imf_x400_content_type, NULL, FALSE},
+ {"x400-mts-identifier", &hf_imf_x400_mts_identifier, NULL, FALSE},
+ {"x400-originator", &hf_imf_x400_originator, NULL, FALSE},
+ {"x400-received", &hf_imf_x400_received, NULL, FALSE},
+ {"x400-recipients", &hf_imf_x400_recipients, NULL, FALSE},
+ /* delivery */
+ {"delivered-to", &hf_imf_delivered_to, dissect_imf_mailbox, FALSE}, /* mailbox */
+ /* some others */
+ {"x-mailer", &hf_imf_ext_mailer, NO_SUBDISSECTION, FALSE}, /* unstructured */
+ {"thread-index", &hf_imf_thread_index, NO_SUBDISSECTION, FALSE}, /* unstructured */
+ {"lines", &hf_imf_lines, NULL, FALSE},
+ {"precedence", &hf_imf_precedence, NULL, FALSE},
+ {"x-mimeole", &hf_imf_ext_mimeole, NO_SUBDISSECTION, FALSE}, /* unstructured */
+ {"expiry-date", &hf_imf_ext_expiry_date, NO_SUBDISSECTION, FALSE}, /* unstructured */
+ {"x-ms-tnef-correlator", &hf_imf_ext_tnef_correlator, NO_SUBDISSECTION, FALSE}, /* unstructured */
+ {"x-uidl", &hf_imf_ext_uidl, NO_SUBDISSECTION, FALSE}, /* unstructured */
+ {"x-authentication-warning", &hf_imf_ext_authentication_warning, NO_SUBDISSECTION, FALSE}, /* unstructured */
+ {"x-virus-scanned", &hf_imf_ext_virus_scanned, NO_SUBDISSECTION, FALSE}, /* unstructured */
+ {"x-original-to", &hf_imf_ext_original_to, dissect_imf_address_list, FALSE},
+ {"sio-label", &hf_imf_siolabel, dissect_imf_siolabel, FALSE}, /* sio-label */
+ {NULL, NULL, NULL, FALSE},
+};
+
+static wmem_map_t *imf_field_table=NULL;
+
+#define FORMAT_UNSTRUCTURED 0
+#define FORMAT_MAILBOX 1
+#define FORMAT_ADDRESS 2
+#define FORMAT_MAILBOX_LIST 3
+#define FORMAT_ADDRESS_LIST 4
+#define FORMAT_SIO_LABEL 5
+
+static const value_string header_format[] = {
+ { FORMAT_UNSTRUCTURED, "Unstructured" },
+ { FORMAT_MAILBOX, "Mailbox" },
+ { FORMAT_ADDRESS, "Address" },
+ { FORMAT_MAILBOX_LIST, "Mailbox List" },
+ { FORMAT_ADDRESS_LIST, "Address List" },
+ { FORMAT_SIO_LABEL, "SIO-Label" },
+ { 0, NULL }
+};
+
+static const value_string add_to_col_info[] = {
+ { 0, "No" },
+ { 1, "Yes" },
+ { 0, NULL }
+};
+
+typedef struct _header_field_t {
+ gchar *header_name;
+ gchar *description;
+ guint header_format;
+ guint add_to_col_info;
+} header_field_t;
+
+static header_field_t *header_fields;
+static guint num_header_fields;
+
+static GHashTable *custom_field_table;
+static hf_register_info *dynamic_hf;
+static guint dynamic_hf_size;
+
+static bool
+header_fields_update_cb(void *r, char **err)
+{
+ header_field_t *rec = (header_field_t *)r;
+ char c;
+
+ if (rec->header_name == NULL) {
+ *err = g_strdup("Header name can't be empty");
+ return FALSE;
+ }
+
+ g_strstrip(rec->header_name);
+ if (rec->header_name[0] == 0) {
+ *err = g_strdup("Header name can't be empty");
+ return FALSE;
+ }
+
+ /* Check for invalid characters (to avoid asserting out when
+ * registering the field).
+ */
+ c = proto_check_field_name(rec->header_name);
+ if (c) {
+ *err = ws_strdup_printf("Header name can't contain '%c'", c);
+ return FALSE;
+ }
+
+ *err = NULL;
+ return TRUE;
+}
+
+static void *
+header_fields_copy_cb(void *n, const void *o, size_t siz _U_)
+{
+ header_field_t *new_rec = (header_field_t *)n;
+ const header_field_t *old_rec = (const header_field_t *)o;
+
+ new_rec->header_name = g_strdup(old_rec->header_name);
+ new_rec->description = g_strdup(old_rec->description);
+ new_rec->header_format = old_rec->header_format;
+ new_rec->add_to_col_info = old_rec->add_to_col_info;
+
+ return new_rec;
+}
+
+static void
+header_fields_free_cb(void *r)
+{
+ header_field_t *rec = (header_field_t *)r;
+
+ g_free(rec->header_name);
+ g_free(rec->description);
+}
+
+UAT_CSTRING_CB_DEF(header_fields, header_name, header_field_t)
+UAT_CSTRING_CB_DEF(header_fields, description, header_field_t)
+UAT_VS_DEF(header_fields, header_format, header_field_t, guint, 0, "Unstructured")
+UAT_VS_DEF(header_fields, add_to_col_info, header_field_t, guint, 0, "No")
+
+
+/* Define media_type/Content type table */
+static dissector_table_t media_type_dissector_table;
+
+static void
+dissect_imf_address(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
+{
+ proto_tree *group_tree;
+ proto_item *group_item;
+ int addr_pos;
+
+ /* if there is a colon present it is a group */
+ if((addr_pos = tvb_find_guint8(tvb, offset, length, ':')) == -1) {
+
+ /* there isn't - so it must be a mailbox */
+ dissect_imf_mailbox(tvb, offset, length, item, pinfo);
+
+ } else {
+
+ /* it is a group */
+ group_tree = proto_item_add_subtree(item, ett_imf_group);
+
+ /* the display-name is mandatory */
+ group_item = proto_tree_add_item(group_tree, hf_imf_display_name, tvb, offset, addr_pos - offset - 1, ENC_ASCII);
+
+ /* consume any whitespace */
+ for(addr_pos++ ;addr_pos < (offset + length); addr_pos++) {
+ if(!g_ascii_isspace(tvb_get_guint8(tvb, addr_pos))) {
+ break;
+ }
+ }
+
+ if(tvb_get_guint8(tvb, addr_pos) != ';') {
+
+ dissect_imf_mailbox_list(tvb, addr_pos, length - (addr_pos - offset), group_item, pinfo);
+
+ /* XXX: need to check for final ';' */
+
+ }
+
+ }
+}
+
+static void
+dissect_imf_mailbox(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo _U_)
+{
+ proto_tree *mbox_tree;
+ int addr_pos, end_pos;
+
+ mbox_tree = proto_item_add_subtree(item, ett_imf_mailbox);
+
+ /* Here is the plan:
+ If we can't find and angle brackets, then the whole field is an address.
+ If we find angle brackets, then the address is between them and the display name is
+ anything before the opening angle bracket
+ */
+
+ if((addr_pos = tvb_find_guint8(tvb, offset, length, '<')) == -1) {
+ /* we can't find an angle bracket - the whole field is therefore the address */
+
+ (void) proto_tree_add_item(mbox_tree, hf_imf_address, tvb, offset, length, ENC_ASCII);
+
+ } else {
+ /* we can find an angle bracket - let's see if we can find a display name */
+ /* XXX: the '<' could be in the display name */
+
+ for(; offset < addr_pos; offset++) {
+ if(!g_ascii_isspace(tvb_get_guint8(tvb, offset))) {
+ break;
+ }
+ }
+
+ if(offset != addr_pos) { /* there is a display name */
+ (void) proto_tree_add_item(mbox_tree, hf_imf_display_name, tvb, offset, addr_pos - offset - 1, ENC_ASCII);
+ }
+ end_pos = tvb_find_guint8(tvb, addr_pos + 1, length - (addr_pos + 1 - offset), '>');
+
+ if(end_pos != -1) {
+ (void) proto_tree_add_item(mbox_tree, hf_imf_address, tvb, addr_pos + 1, end_pos - addr_pos - 1, ENC_ASCII);
+ }
+ }
+}
+
+static void
+dissect_imf_address_list(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
+{
+ proto_item *addr_item = NULL;
+ proto_tree *tree = NULL;
+ int count = 0;
+ int item_offset;
+ int end_offset;
+ int item_length;
+
+ /* a comma separated list of addresses */
+ tree = proto_item_add_subtree(item, ett_imf_address_list);
+
+ item_offset = offset;
+
+ do {
+
+ end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ',');
+
+ count++; /* increase the number of items */
+
+ if(end_offset == -1) {
+ /* length is to the end of the buffer */
+ item_length = length - (item_offset - offset);
+ } else {
+ item_length = end_offset - item_offset;
+ }
+ addr_item = proto_tree_add_item(tree, hf_imf_address_list_item, tvb, item_offset, item_length, ENC_ASCII);
+ dissect_imf_address(tvb, item_offset, item_length, addr_item, pinfo);
+
+ if(end_offset != -1) {
+ item_offset = end_offset + 1;
+ }
+ } while(end_offset != -1);
+
+ /* now indicate the number of items found */
+ proto_item_append_text(item, ", %d item%s", count, plurality(count, "", "s"));
+}
+
+static void
+dissect_imf_mailbox_list(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
+{
+ proto_item *mbox_item = NULL;
+ proto_tree *tree = NULL;
+ int count = 0;
+ int item_offset;
+ int end_offset;
+ int item_length;
+
+ /* a comma separated list of mailboxes */
+ tree = proto_item_add_subtree(item, ett_imf_mailbox_list);
+
+ item_offset = offset;
+
+ do {
+
+ end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ',');
+
+ count++; /* increase the number of items */
+
+ if(end_offset == -1) {
+ /* length is to the end of the buffer */
+ item_length = length - (item_offset - offset);
+ } else {
+ item_length = end_offset - item_offset;
+ }
+ mbox_item = proto_tree_add_item(tree, hf_imf_mailbox_list_item, tvb, item_offset, item_length, ENC_ASCII);
+ dissect_imf_mailbox(tvb, item_offset, item_length, mbox_item, pinfo);
+
+ if(end_offset != -1) {
+ item_offset = end_offset + 1;
+ }
+ } while(end_offset != -1);
+
+ /* now indicate the number of items found */
+ proto_item_append_text(item, ", %d item%s", count, plurality(count, "", "s"));
+}
+
+static void
+dissect_imf_siolabel(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
+{
+ proto_tree *tree = NULL;
+ proto_item *sub_item = NULL;
+ int item_offset, item_length;
+ int value_offset, value_length;
+ int end_offset;
+ tvbuff_t *label_tvb;
+ gchar *type = NULL;
+ wmem_strbuf_t *label_string = wmem_strbuf_new(pinfo->pool, "");
+
+ /* a semicolon separated list of attributes */
+ tree = proto_item_add_subtree(item, ett_imf_siolabel);
+ item_offset = offset;
+
+ do {
+ end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ';');
+
+ /* skip leading space */
+ while (g_ascii_isspace(tvb_get_guint8(tvb, item_offset))) {
+ item_offset++;
+ }
+
+ if (end_offset == -1) {
+ /* length is to the end of the buffer */
+ item_length = tvb_find_line_end(tvb, item_offset, length - (item_offset - offset), NULL, FALSE);
+ } else {
+ item_length = end_offset - item_offset;
+ }
+
+ value_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), '=') + 1;
+ while (g_ascii_isspace(tvb_get_guint8(tvb, value_offset))) {
+ value_offset++;
+ }
+
+ value_length = item_length - (value_offset - item_offset);
+ while (g_ascii_isspace(tvb_get_guint8(tvb, value_offset + value_length - 1))) {
+ value_length--;
+ }
+
+ if (tvb_strneql(tvb, item_offset, "marking", 7) == 0) {
+ const guint8* marking;
+ proto_tree_add_item_ret_string(tree, hf_imf_siolabel_marking, tvb, value_offset, value_length, ENC_ASCII|ENC_NA, pinfo->pool, &marking);
+ proto_item_append_text(item, ": %s", marking);
+
+ } else if (tvb_strneql(tvb, item_offset, "fgcolor", 7) == 0) {
+ proto_tree_add_item(tree, hf_imf_siolabel_fgcolor, tvb, value_offset, value_length, ENC_ASCII);
+
+ } else if (tvb_strneql(tvb, item_offset, "bgcolor", 7) == 0) {
+ proto_tree_add_item(tree, hf_imf_siolabel_bgcolor, tvb, value_offset, value_length, ENC_ASCII);
+
+ } else if (tvb_strneql(tvb, item_offset, "type", 4) == 0) {
+ type = tvb_get_string_enc(pinfo->pool, tvb, value_offset + 1, value_length - 2, ENC_ASCII); /* quoted */
+ proto_tree_add_item(tree, hf_imf_siolabel_type, tvb, value_offset, value_length, ENC_ASCII);
+
+ } else if (tvb_strneql(tvb, item_offset, "label", 5) == 0) {
+ gchar *label = tvb_get_string_enc(pinfo->pool, tvb, value_offset + 1, value_length - 2, ENC_ASCII); /* quoted */
+ wmem_strbuf_append(label_string, label);
+
+ if (tvb_get_guint8(tvb, item_offset + 5) == '*') { /* continuations */
+ int num = (int)strtol(tvb_get_string_enc(pinfo->pool, tvb, item_offset + 6, value_offset - item_offset + 6, ENC_ASCII), NULL, 10);
+ proto_tree_add_string_format(tree, hf_imf_siolabel_label, tvb, value_offset, value_length,
+ label, "Label[%d]: \"%s\"", num, label);
+ } else {
+ proto_tree_add_item(tree, hf_imf_siolabel_label, tvb, value_offset, value_length, ENC_ASCII);
+ }
+
+ } else {
+ sub_item = proto_tree_add_item(tree, hf_imf_siolabel_unknown, tvb, item_offset, item_length, ENC_ASCII);
+ expert_add_info(pinfo, sub_item, &ei_imf_unknown_param);
+ }
+
+ if (end_offset != -1) {
+ item_offset = end_offset + 1;
+ }
+ } while (end_offset != -1);
+
+ if (type && wmem_strbuf_get_len(label_string) > 0) {
+ if (strcmp (type, ":ess") == 0) {
+ label_tvb = base64_to_tvb(tvb, wmem_strbuf_get_str(label_string));
+ add_new_data_source(pinfo, label_tvb, "ESS Security Label");
+ dissect_ess_ESSSecurityLabel_PDU(label_tvb, pinfo, tree, NULL);
+ } else if (strcmp (type, ":x411") == 0) {
+ label_tvb = base64_to_tvb(tvb, wmem_strbuf_get_str(label_string));
+ add_new_data_source(pinfo, label_tvb, "X.411 Security Label");
+ dissect_p1_MessageSecurityLabel_PDU(label_tvb, pinfo, tree, NULL);
+ }
+ }
+}
+
+static void
+dissect_imf_content_type(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_item *item,
+ const guint8 **type, const guint8 **parameters)
+{
+ int first_colon;
+ int end_offset;
+ int len;
+ int i;
+ proto_tree *ct_tree;
+
+ /* first strip any whitespace */
+ for(i = 0; i < length; i++) {
+ if(!g_ascii_isspace(tvb_get_guint8(tvb, offset + i))) {
+ offset += i;
+ break;
+ }
+ }
+
+ /* find the first colon - there has to be a colon as there will have to be a boundary */
+ first_colon = tvb_find_guint8(tvb, offset, length, ';');
+
+ if(first_colon != -1) {
+ ct_tree = proto_item_add_subtree(item, ett_imf_content_type);
+
+ len = first_colon - offset;
+ proto_tree_add_item_ret_string(ct_tree, hf_imf_content_type_type, tvb, offset, len, ENC_ASCII|ENC_NA, pinfo->pool, type);
+ end_offset = imf_find_field_end (tvb, first_colon + 1, offset + length, NULL);
+ if (end_offset == -1) {
+ /* No end found */
+ return;
+ }
+ len = end_offset - (first_colon + 1) - 2; /* Do not include the last CRLF */
+ proto_tree_add_item_ret_string(ct_tree, hf_imf_content_type_parameters, tvb, first_colon + 1, len, ENC_ASCII|ENC_NA, pinfo->pool, parameters);
+ }
+}
+
+
+int
+imf_find_field_end(tvbuff_t *tvb, int offset, gint max_length, gboolean *last_field)
+{
+
+ while(offset < max_length) {
+
+ /* look for CR */
+ offset = tvb_find_guint8(tvb, offset, max_length - offset, '\r');
+
+ if(offset != -1) {
+ /* protect against buffer overrun and only then look for next char */
+ if (++offset < max_length && tvb_get_guint8(tvb, offset) == '\n') {
+ /* OK - so we have found CRLF */
+ if (++offset >= max_length) {
+ /* end of buffer and also end of fields */
+ if (last_field) {
+ *last_field = TRUE;
+ }
+ /* caller expects that there is CRLF after returned offset, if last_field is set */
+ return offset - 2;
+ }
+ /* peek the next character */
+ switch(tvb_get_guint8(tvb, offset)) {
+ case '\r':
+ /* probably end of the fields */
+ if ((offset + 1) < max_length && tvb_get_guint8(tvb, offset + 1) == '\n') {
+ if(last_field) {
+ *last_field = TRUE;
+ }
+ }
+ return offset;
+ case ' ':
+ case '\t':
+ /* continuation line */
+ break;
+ default:
+ /* this is a new field */
+ return offset;
+ }
+ }
+ } else {
+ /* couldn't find a CR - strange */
+ break;
+ }
+
+ }
+
+ return -1; /* Fail: No CR found (other than possible continuation) */
+
+}
+
+static int
+dissect_imf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *item;
+ proto_tree *unknown_tree, *text_tree;
+ const guint8 *content_type_str = NULL;
+ char *content_encoding_str = NULL;
+ const guint8 *parameters = NULL;
+ int hf_id;
+ gint start_offset = 0;
+ gint value_offset = 0;
+ gint unknown_offset = 0;
+ gint end_offset = 0;
+ gint max_length;
+ guint8 *key;
+ gboolean last_field = FALSE;
+ tvbuff_t *next_tvb;
+ struct imf_field *f_info;
+ imf_eo_t *eo_info = NULL;
+
+ if (have_tap_listener(imf_eo_tap)) {
+ eo_info = wmem_new(pinfo->pool, imf_eo_t);
+ /* initialize the eo_info fields in case they are missing later */
+ eo_info->sender_data = "";
+ eo_info->subject_data = "";
+ }
+
+ /* Want to preserve existing protocol name and show that it is carrying IMF */
+ col_append_str(pinfo->cinfo, COL_PROTOCOL, "/");
+ col_set_fence(pinfo->cinfo, COL_PROTOCOL);
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
+
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ item = proto_tree_add_item(tree, proto_imf, tvb, 0, -1, ENC_NA);
+ tree = proto_item_add_subtree(item, ett_imf);
+
+ max_length = tvb_captured_length(tvb);
+ /* first go through the tvb until we find a blank line and extract the content type if
+ we find one */
+
+ /* XXX: What if the tvb contains encrypted data ? is there a way to bypass dissection if so ? */
+ /* As it is, the following code blithely tries to parse what may be binary data. */
+
+ while(!last_field) {
+
+ /* look for a colon first */
+ end_offset = tvb_find_guint8(tvb, start_offset, max_length - start_offset, ':');
+
+ if(end_offset == -1) {
+ /* we couldn't find another colon - strange - we should have broken out of here by now */
+ /* XXX: flag an error */
+ break;
+ } else {
+ key = tvb_get_string_enc(pinfo->pool, tvb, start_offset, end_offset - start_offset, ENC_ASCII);
+
+ /* convert to lower case */
+ ascii_strdown_inplace (key);
+
+ /* look up the key in built-in fields */
+ f_info = (struct imf_field *)wmem_map_lookup(imf_field_table, key);
+
+ if(f_info == NULL && custom_field_table) {
+ /* look up the key in custom fields */
+ f_info = (struct imf_field *)g_hash_table_lookup(custom_field_table, key);
+ }
+
+ if(f_info == NULL) {
+ /* set as an unknown extension */
+ f_info = imf_fields;
+ unknown_offset = start_offset;
+ }
+
+ hf_id = *(f_info->hf_id);
+
+ /* value starts immediately after the colon */
+ start_offset = end_offset+1;
+
+ end_offset = imf_find_field_end(tvb, start_offset, max_length, &last_field);
+ if(end_offset == -1) {
+ break; /* Something's fishy */
+ }
+
+ /* remove any leading whitespace */
+
+ for(value_offset = start_offset; value_offset < end_offset; value_offset++)
+ if(!g_ascii_isspace(tvb_get_guint8(tvb, value_offset))) {
+ break;
+ }
+
+ if(value_offset == end_offset) {
+ /* empty field - show whole value */
+ value_offset = start_offset;
+ }
+
+ if(hf_id == hf_imf_extension_type) {
+
+ /* remove 2 bytes to take off the final CRLF to make things a little prettier */
+ item = proto_tree_add_item(tree, hf_imf_extension, tvb, unknown_offset, end_offset - unknown_offset - 2, ENC_ASCII);
+
+ proto_item_append_text(item, " (Contact Wireshark developers if you want this supported.)");
+
+ unknown_tree = proto_item_add_subtree(item, ett_imf_extension);
+
+ proto_tree_add_item(unknown_tree, hf_imf_extension_type, tvb, unknown_offset, start_offset - 1 - unknown_offset, ENC_ASCII);
+
+ /* remove 2 bytes to take off the final CRLF to make things a little prettier */
+ item = proto_tree_add_item(unknown_tree, hf_imf_extension_value, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII);
+
+ } else {
+ /* remove 2 bytes to take off the final CRLF to make things a little prettier */
+ item = proto_tree_add_item(tree, hf_id, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII|ENC_NA);
+ }
+ if(f_info->add_to_col_info) {
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s: %s, ", f_info->name,
+ tvb_format_text(pinfo->pool, tvb, value_offset, end_offset - value_offset - 2));
+
+ /* if sender or subject, store for sending to the tap */
+ if (eo_info && have_tap_listener(imf_eo_tap)) {
+ if (*f_info->hf_id == hf_imf_from) {
+ eo_info->sender_data = tvb_get_string_enc(pinfo->pool, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII|ENC_NA);
+ } else if(*f_info->hf_id == hf_imf_subject) {
+ eo_info->subject_data = tvb_get_string_enc(pinfo->pool, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII|ENC_NA);
+ }
+ }
+ }
+
+ if(hf_id == hf_imf_content_type) {
+ /* we need some additional processing to extract the content type and parameters */
+
+ dissect_imf_content_type(tvb, pinfo, start_offset, end_offset - start_offset, item,
+ &content_type_str, &parameters);
+
+ } else if (hf_id == hf_imf_content_transfer_encoding) {
+ content_encoding_str = tvb_get_string_enc (pinfo->pool, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII);
+ } else if(f_info->subdissector) {
+
+ /* we have a subdissector */
+ f_info->subdissector(tvb, value_offset, end_offset - value_offset, item, pinfo);
+
+ }
+ }
+ start_offset = end_offset;
+ }
+
+ if (last_field) {
+ /* Remove the extra CRLF after all the fields */
+ end_offset += 2;
+ }
+
+ if (end_offset == -1) {
+ end_offset = 0;
+ }
+
+ /* specify a content type until we can work it out for ourselves */
+ /* content_type_str = "multipart/mixed"; */
+
+ /* now dissect the MIME based upon the content type */
+
+ if(content_type_str && media_type_dissector_table) {
+ media_content_info_t content_info;
+
+ col_set_fence(pinfo->cinfo, COL_INFO);
+
+ if(content_encoding_str && !g_ascii_strncasecmp(content_encoding_str, "base64", 6)) {
+ char *string_data = tvb_get_string_enc(pinfo->pool, tvb, end_offset, tvb_reported_length(tvb) - end_offset, ENC_ASCII);
+ next_tvb = base64_to_tvb(tvb, string_data);
+ add_new_data_source(pinfo, next_tvb, content_encoding_str);
+ } else {
+ next_tvb = tvb_new_subset_remaining(tvb, end_offset);
+ }
+
+ content_info.type = MEDIA_CONTAINER_OTHER;
+ content_info.media_str = parameters;
+ content_info.data = NULL;
+ dissector_try_string(media_type_dissector_table, content_type_str, next_tvb, pinfo, tree, (void*)&content_info);
+ } else {
+
+ /* just show the lines or highlight the rest of the buffer as message text */
+
+ item = proto_tree_add_item(tree, hf_imf_message_text, tvb, end_offset, tvb_reported_length_remaining(tvb, end_offset) , ENC_NA);
+ text_tree = proto_item_add_subtree(item, ett_imf_message_text);
+
+ start_offset = end_offset;
+ while (tvb_offset_exists(tvb, start_offset)) {
+
+ /*
+ * Find the end of the line.
+ */
+ tvb_find_line_end(tvb, start_offset, -1, &end_offset, FALSE);
+
+ /*
+ * Put this line.
+ */
+ proto_tree_add_format_wsp_text(text_tree, tvb, start_offset, end_offset - start_offset);
+ col_append_sep_str(pinfo->cinfo, COL_INFO, ", ",
+ tvb_format_text_wsp(pinfo->pool, tvb, start_offset, end_offset - start_offset));
+
+ /*
+ * Step to the next line.
+ */
+ start_offset = end_offset;
+ }
+ }
+
+ if (eo_info && have_tap_listener(imf_eo_tap)) {
+ /* Set payload info */
+ eo_info->payload_len = max_length;
+ eo_info->payload_data = (gchar *) tvb_memdup(pinfo->pool, tvb, 0, max_length);
+
+ /* Send to tap */
+ tap_queue_packet(imf_eo_tap, pinfo, eo_info);
+ }
+ return tvb_captured_length(tvb);
+}
+
+static void
+free_imf_field (gpointer data)
+{
+ struct imf_field *imffield = (struct imf_field *) data;
+
+ g_free (imffield->name);
+ g_free (imffield);
+}
+
+static void
+deregister_header_fields(void)
+{
+ if (dynamic_hf) {
+ /* Deregister all fields */
+ for (guint i = 0; i < dynamic_hf_size; i++) {
+ proto_deregister_field (proto_imf, *(dynamic_hf[i].p_id));
+ g_free (dynamic_hf[i].p_id);
+ }
+
+ proto_add_deregistered_data (dynamic_hf);
+ dynamic_hf = NULL;
+ dynamic_hf_size = 0;
+ }
+
+ if (custom_field_table) {
+ g_hash_table_destroy (custom_field_table);
+ custom_field_table = NULL;
+ }
+}
+
+static void
+header_fields_post_update_cb (void)
+{
+ gint *hf_id;
+ struct imf_field *imffield;
+ gchar *header_name;
+
+ deregister_header_fields();
+
+ if (num_header_fields) {
+ custom_field_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_imf_field);
+ dynamic_hf = g_new0(hf_register_info, num_header_fields);
+ dynamic_hf_size = num_header_fields;
+
+ for (guint i = 0; i < dynamic_hf_size; i++) {
+ hf_id = g_new(gint, 1);
+ *hf_id = -1;
+ header_name = g_strdup (header_fields[i].header_name);
+
+ dynamic_hf[i].p_id = hf_id;
+ dynamic_hf[i].hfinfo.name = header_name;
+ dynamic_hf[i].hfinfo.abbrev = ws_strdup_printf ("imf.header.%s", header_name);
+ dynamic_hf[i].hfinfo.type = FT_STRING;
+ dynamic_hf[i].hfinfo.display = BASE_NONE;
+ dynamic_hf[i].hfinfo.strings = NULL;
+ dynamic_hf[i].hfinfo.bitmask = 0;
+ dynamic_hf[i].hfinfo.blurb = g_strdup (header_fields[i].description);
+ HFILL_INIT(dynamic_hf[i]);
+
+ imffield = g_new(struct imf_field, 1);
+ imffield->hf_id = hf_id;
+ imffield->name = g_ascii_strdown(header_name, -1);
+ switch (header_fields[i].header_format) {
+ case FORMAT_UNSTRUCTURED:
+ imffield->subdissector = NO_SUBDISSECTION;
+ break;
+ case FORMAT_MAILBOX:
+ imffield->subdissector = dissect_imf_mailbox;
+ break;
+ case FORMAT_ADDRESS:
+ imffield->subdissector = dissect_imf_address;
+ break;
+ case FORMAT_MAILBOX_LIST:
+ imffield->subdissector = dissect_imf_mailbox_list;
+ break;
+ case FORMAT_ADDRESS_LIST:
+ imffield->subdissector = dissect_imf_address_list;
+ break;
+ case FORMAT_SIO_LABEL:
+ dynamic_hf[i].hfinfo.type = FT_NONE; /* constructed */
+ imffield->subdissector = dissect_imf_siolabel;
+ break;
+ default:
+ /* unknown */
+ imffield->subdissector = NO_SUBDISSECTION;
+ break;
+ }
+ imffield->add_to_col_info = header_fields[i].add_to_col_info;
+ g_hash_table_insert (custom_field_table, (gpointer)imffield->name, (gpointer)imffield);
+ }
+
+ proto_register_field_array (proto_imf, dynamic_hf, dynamic_hf_size);
+ }
+}
+
+static void
+header_fields_reset_cb(void)
+{
+ deregister_header_fields();
+}
+
+/* Register all the bits needed by the filtering engine */
+
+void
+proto_register_imf(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_imf_date,
+ { "Date", "imf.date", FT_STRING, BASE_NONE, NULL, 0x0,
+ "DateTime", HFILL }},
+ { &hf_imf_from,
+ { "From", "imf.from", FT_STRING, BASE_NONE, NULL, 0x0,
+ "MailboxList", HFILL }},
+ { &hf_imf_sender,
+ { "Sender", "imf.sender", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_reply_to,
+ { "Reply-To", "imf.reply_to", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_to,
+ { "To", "imf.to", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_cc,
+ { "Cc", "imf.cc", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_bcc,
+ { "Bcc", "imf.bcc", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_message_id,
+ { "Message-ID", "imf.message_id", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_in_reply_to,
+ { "In-Reply-To", "imf.in_reply_to", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_references,
+ { "References", "imf.references", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_subject,
+ { "Subject", "imf.subject", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_comments,
+ { "Comments", "imf.comments", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_user_agent,
+ { "User-Agent", "imf.user_agent", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_keywords,
+ { "Keywords", "imf.keywords", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_resent_date,
+ { "Resent-Date", "imf.resent.date", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_resent_from,
+ { "Resent-From", "imf.resent.from", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_resent_sender,
+ { "Resent-Sender", "imf.resent.sender", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_resent_to,
+ { "Resent-To", "imf.resent.to", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_resent_cc,
+ { "Resent-Cc", "imf.resent.cc", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_resent_bcc,
+ { "Resent-Bcc", "imf.resent.bcc", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_resent_message_id,
+ { "Resent-Message-ID", "imf.resent.message_id", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_return_path,
+ { "Return-Path", "imf.return_path", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_received,
+ { "Received", "imf.received", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_content_type,
+ { "Content-Type", "imf.content.type", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_content_type_type,
+ { "Type", "imf.content.type.type", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_content_type_parameters,
+ { "Parameters", "imf.content.type.parameters", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_content_description,
+ { "Content-Description", "imf.content.description", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_content_id,
+ { "Content-ID", "imf.content.id", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_content_transfer_encoding,
+ { "Content-Transfer-Encoding", "imf.content.transfer_encoding", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_mime_version,
+ { "MIME-Version", "imf.mime_version", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_autoforwarded,
+ { "Autoforwarded", "imf.autoforwarded", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_autosubmitted,
+ { "Autosubmitted", "imf.autosubmitted", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_x400_content_identifier,
+ { "X400-Content-Identifier", "imf.x400_content_identifier", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_content_language,
+ { "Content-Language", "imf.content_language", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_conversion,
+ { "Conversion", "imf.conversion", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_conversion_with_loss,
+ { "Conversion-With-Loss", "imf.conversion_with_loss", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_delivery_date,
+ { "Delivery-Date", "imf.delivery_date", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_discarded_x400_ipms_extensions,
+ { "Discarded-X400-IPMS-Extensions", "imf.discarded_x400_ipms_extensions", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_discarded_x400_mts_extensions,
+ { "Discarded-X400-MTS-Extensions", "imf.discarded_x400_mts_extensions", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_dl_expansion_history,
+ { "DL-Expansion-History", "imf.dl_expansion_history", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_deferred_delivery,
+ { "Deferred-Delivery", "imf.deferred_delivery", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_expires,
+ { "Expires", "imf.expires", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_importance,
+ { "Importance", "imf.importance", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_incomplete_copy,
+ { "Incomplete-Copy", "imf.incomplete_copy", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_latest_delivery_time,
+ { "Latest-Delivery-Time", "imf.latest_delivery_time", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_message_type,
+ { "Message-Type", "imf.message_type", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_original_encoded_information_types,
+ { "Original-Encoded-Information-Types", "imf.original_encoded_information_types", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_originator_return_address,
+ { "Originator-Return-Address", "imf.originator_return_address", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_priority,
+ { "Priority", "imf.priority", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_reply_by,
+ { "Reply-By", "imf.reply_by", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_sensitivity,
+ { "Sensitivity", "imf.sensitivity", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_supersedes,
+ { "Supersedes", "imf.supersedes", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_x400_content_type,
+ { "X400-Content-Type", "imf.x400_content_type", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_x400_mts_identifier,
+ { "X400-MTS-Identifier", "imf.x400_mts_identifier", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_x400_originator,
+ { "X400-Originator", "imf.x400_originator", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_x400_received,
+ { "X400-Received", "imf.x400_received", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_x400_recipients,
+ { "X400-Recipients", "imf.x400_recipients", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_delivered_to,
+ { "Delivered-To", "imf.delivered_to", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_ext_mailer,
+ { "X-Mailer", "imf.ext.mailer", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_ext_mimeole,
+ { "X-MimeOLE", "imf.ext.mimeole", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_ext_expiry_date,
+ { "Expiry-Date", "imf.ext.expiry-date", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_ext_tnef_correlator,
+ { "X-MS-TNEF-Correlator", "imf.ext.tnef-correlator", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_ext_uidl,
+ { "X-UIDL", "imf.ext.uidl", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_ext_authentication_warning,
+ { "X-Authentication-Warning", "imf.ext.authentication_warning", FT_STRING, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_imf_ext_virus_scanned,
+ { "X-Virus-Scanned", "imf.ext.virus_scanned", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_ext_original_to,
+ { "X-Original-To", "imf.ext.original-to", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_thread_index,
+ { "Thread-Index", "imf.thread-index", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_lines,
+ { "Lines", "imf.lines", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_precedence,
+ { "Precedence", "imf.precedence", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_extension,
+ { "Unknown-Extension", "imf.extension", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_extension_type,
+ { "Type", "imf.extension.type", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_extension_value,
+ { "Value", "imf.extension.value", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_display_name,
+ { "Display-Name", "imf.display_name", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_address,
+ { "Address", "imf.address", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+#if 0
+ { &hf_imf_address_list,
+ { "Address List", "imf.address_list", FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+#endif
+ { &hf_imf_address_list_item,
+ { "Item", "imf.address_list.item", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+#if 0
+ { &hf_imf_mailbox_list,
+ { "Mailbox List", "imf.mailbox_list", FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+#endif
+ { &hf_imf_mailbox_list_item,
+ { "Item", "imf.mailbox_list.item", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_siolabel,
+ { "SIO-Label", "imf.siolabel", FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_siolabel_marking,
+ { "Marking", "imf.siolabel.marking", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_siolabel_fgcolor,
+ { "Foreground Color", "imf.siolabel.fgcolor", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_siolabel_bgcolor,
+ { "Background Color", "imf.siolabel.bgcolor", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_siolabel_type,
+ { "Type", "imf.siolabel.type", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_siolabel_label,
+ { "Label", "imf.siolabel.label", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_siolabel_unknown,
+ { "Unknown parameter", "imf.siolabel.unknown", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_imf_message_text,
+ { "Message-Text", "imf.message_text", FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_imf,
+ &ett_imf_content_type,
+ &ett_imf_group,
+ &ett_imf_mailbox,
+ &ett_imf_mailbox_list,
+ &ett_imf_address_list,
+ &ett_imf_siolabel,
+ &ett_imf_extension,
+ &ett_imf_message_text,
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_imf_unknown_param, { "imf.unknown_param", PI_PROTOCOL, PI_WARN, "Unknown parameter", EXPFILL }},
+ };
+
+ static uat_field_t attributes_flds[] = {
+ UAT_FLD_CSTRING(header_fields, header_name, "Header name", "IMF header name"),
+ UAT_FLD_CSTRING(header_fields, description, "Description", "Description of the value contained in the header"),
+ UAT_FLD_VS(header_fields, header_format, "Format", header_format, 0),
+ UAT_FLD_VS(header_fields, add_to_col_info, "Add to Info column", add_to_col_info, 0),
+ UAT_END_FIELDS
+ };
+
+ uat_t *headers_uat = uat_new("Custom IMF headers",
+ sizeof(header_field_t),
+ "imf_header_fields",
+ TRUE,
+ &header_fields,
+ &num_header_fields,
+ /* specifies named fields, so affects dissection
+ and the set of named fields */
+ UAT_AFFECTS_DISSECTION|UAT_AFFECTS_FIELDS,
+ NULL,
+ header_fields_copy_cb,
+ header_fields_update_cb,
+ header_fields_free_cb,
+ header_fields_post_update_cb,
+ header_fields_reset_cb,
+ attributes_flds);
+
+ module_t *imf_module;
+ expert_module_t* expert_imf;
+ struct imf_field *f;
+
+ proto_imf = proto_register_protocol(PNAME, PSNAME, PFNAME);
+
+ proto_register_field_array(proto_imf, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_imf = expert_register_protocol(proto_imf);
+ expert_register_field_array(expert_imf, ei, array_length(ei));
+
+ /* Allow dissector to find be found by name. */
+ imf_handle = register_dissector(PFNAME, dissect_imf, proto_imf);
+
+ imf_module = prefs_register_protocol(proto_imf, NULL);
+ prefs_register_uat_preference(imf_module, "custom_header_fields", "Custom IMF headers",
+ "A table to define custom IMF headers for which fields can be "
+ "setup and used for filtering/data extraction etc.",
+ headers_uat);
+
+ imf_field_table=wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal); /* oid to syntax */
+
+ /* register the fields for lookup */
+ for(f = imf_fields; f->name; f++)
+ wmem_map_insert(imf_field_table, (gpointer)f->name, (gpointer)f);
+
+ /* Register for tapping */
+ imf_eo_tap = register_export_object(proto_imf, imf_eo_packet, NULL);
+
+}
+
+/* The registration hand-off routine */
+void
+proto_reg_handoff_imf(void)
+{
+ dissector_add_string("media_type",
+ "message/rfc822", imf_handle);
+
+ register_ber_oid_dissector_handle("1.2.840.113549.1.7.1", imf_handle, proto_imf, "id-data");
+
+ /*
+ * Get the content type and Internet media type table
+ */
+ media_type_dissector_table = find_dissector_table("media_type");
+
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=2 tabstop=8 expandtab:
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */