New "decode as ..." feature for BER-encoded files (WTAP_FILE_BER).

A BER-encoded file can be dissected as one of a number of registered syntaxes (registered using register_ber_syntax_dissector()). 
Syntaxes may also be associated with OIDs (or other strings) using register_ber_oid_syntax(). 

A default syntax with which to dissect a BER-encoded file is determined from its filename (extension). For example, ".cer" and ".crt" files will be dissected as "Certificate".


svn path=/trunk/; revision=20414
This commit is contained in:
Graeme Lunt 2007-01-13 12:59:27 +00:00
parent 13a095e055
commit 2fd7d2c620
13 changed files with 421 additions and 10 deletions

View File

@ -113,4 +113,8 @@ void proto_reg_handoff_s4406(void) {
#include "packet-s4406-dis-tab.c"
register_ber_oid_dissector("1.3.26.0.4406.0.4.1", dissect_s4406, proto_s4406, "Military Message");
register_ber_syntax_dissector("MilitaryMessage", proto_s4406, dissect_s4406);
register_ber_oid_syntax(".p772", NULL, "MilitaryMessage");
}

View File

@ -170,5 +170,12 @@ void proto_reg_handoff_x509af(void) {
register_ldap_name_dissector("crossCertificatePair", dissect_CertificatePair_PDU, proto_x509af);
register_ber_syntax_dissector("Certificate", proto_x509af, dissect_Certificate_PDU);
register_ber_oid_syntax(".cer", NULL, "Certificate");
register_ber_oid_syntax(".crt", NULL, "Certificate");
register_ber_syntax_dissector("CertificateList", proto_x509af, dissect_CertificateList_PDU);
register_ber_oid_syntax(".crl", NULL, "CertificateList");
register_ber_syntax_dissector("CrossCertificatePair", proto_x509af, dissect_CertificatePair_PDU);
}

View File

@ -108,9 +108,14 @@ static gint ett_ber_SEQUENCE = -1;
static gboolean show_internal_ber_fields = FALSE;
static gchar *decode_as_syntax = NULL;
static gchar *ber_filename = NULL;
proto_item *ber_last_created_item=NULL;
static dissector_table_t ber_oid_dissector_table=NULL;
static dissector_table_t ber_syntax_dissector_table=NULL;
static GHashTable *syntax_table=NULL;
static const value_string ber_class_codes[] = {
{ BER_CLASS_UNI, "UNIVERSAL" },
@ -158,6 +163,11 @@ static const value_string ber_uni_tag_codes[] = {
{ 0, NULL }
};
typedef struct _da_data {
GHFunc func;
gpointer user_data;
} da_data;
proto_item *get_ber_last_created_item(void) {
return ber_last_created_item;
@ -188,6 +198,94 @@ register_ber_oid_dissector(const char *oid, dissector_t dissector, int proto, co
add_oid_str_name(oid, name);
}
void
register_ber_syntax_dissector(const char *syntax, int proto, dissector_t dissector)
{
dissector_handle_t dissector_handle;
dissector_handle=create_dissector_handle(dissector, proto);
dissector_add_string("ber.syntax", syntax, dissector_handle);
}
void
register_ber_oid_syntax(const char *oid, const char *name, const char *syntax)
{
if(syntax && *syntax)
g_hash_table_insert(syntax_table, (gpointer)oid, (gpointer)syntax);
if(name && *name)
register_ber_oid_name(oid, name);
}
/* Register the oid name to get translation in proto dissection */
void
register_ber_oid_name(const char *oid, const char *name)
{
add_oid_str_name(oid, name);
}
static void ber_decode_as_dt(gchar *table_name, ftenum_t selector_type, gpointer key, gpointer value, gpointer user_data)
{
da_data *decode_as_data;
decode_as_data = (da_data *)user_data;
decode_as_data->func(key, value, decode_as_data->user_data);
}
void ber_decode_as_foreach(GHFunc func, gpointer user_data)
{
da_data decode_as_data;
decode_as_data.func = func;
decode_as_data.user_data = user_data;
dissector_table_foreach("ber.syntax", ber_decode_as_dt, &decode_as_data);
}
void ber_decode_as(gchar *syntax)
{
if(decode_as_syntax) {
g_free(decode_as_syntax);
decode_as_syntax = NULL;
}
if(syntax)
decode_as_syntax = g_strdup(syntax);
}
/* Get oid syntax from hash table to get translation in proto dissection(packet-per.c) */
const char *
get_ber_oid_syntax(const char *oid)
{
return g_hash_table_lookup(syntax_table, oid);
}
void ber_set_filename(gchar *filename)
{
gchar *ptr;
if(ber_filename) {
g_free(ber_filename);
ber_filename = NULL;
}
if(filename) {
ber_filename = g_strdup(filename);
if((ptr = strrchr(ber_filename, '.')) != NULL) {
ber_decode_as(get_ber_oid_syntax(ptr));
}
}
}
int dissect_ber_tagged_type(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gint8 tag_cls, gint32 tag_tag, gboolean tag_impl, ber_type_fn type)
{
gint8 tmp_cls;
@ -432,6 +530,38 @@ call_ber_oid_callback(const char *oid, tvbuff_t *tvb, int offset, packet_info *p
return offset;
}
int
call_ber_syntax_callback(const char *syntax, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
tvbuff_t *next_tvb;
const char *fsyntax = NULL;
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
if(syntax == NULL ||
!dissector_try_string(ber_syntax_dissector_table, syntax, next_tvb, pinfo, tree)){
proto_item *item=NULL;
proto_tree *next_tree=NULL;
if (syntax == NULL)
item=proto_tree_add_text(tree, next_tvb, 0, tvb_length_remaining(tvb, offset), "BER: No syntax supplied to call_ber_syntax_callback");
else
item=proto_tree_add_text(tree, next_tvb, 0, tvb_length_remaining(tvb, offset), "BER: Dissector for syntax: %s not implemented. Contact Wireshark developers if you want this supported", syntax);
if(item){
next_tree=proto_item_add_subtree(item, ett_ber_unknown);
}
dissect_unknown_ber(pinfo, next_tvb, 0, next_tree);
}
/*XXX until we change the #.REGISTER signature for _PDU()s
* into new_dissector_t we have to do this kludge with
* manually step past the content in the ANY type.
*/
offset+=tvb_length_remaining(tvb, offset);
return offset;
}
static int dissect_ber_sq_of(gboolean implicit_tag, gint32 type, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id);
@ -2416,17 +2546,39 @@ int dissect_ber_bitstring32(gboolean implicit_tag, packet_info *pinfo, proto_tre
static void
dissect_ber(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
const char *name;
if (check_col(pinfo->cinfo, COL_INFO)) {
col_clear(pinfo->cinfo, COL_INFO);
col_append_fstr(pinfo->cinfo, COL_INFO, "%s", "Unknown BER");
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "BER");
if (check_col(pinfo->cinfo, COL_DEF_SRC))
col_set_str(pinfo->cinfo, COL_DEF_SRC, "BER encoded file");
if(!decode_as_syntax) {
/* if we got here we couldn't find anything better */
if (check_col(pinfo->cinfo, COL_INFO)) {
col_clear(pinfo->cinfo, COL_INFO);
col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown BER");
}
(void) dissect_unknown_ber(pinfo, tvb, 0, tree);
} else {
(void) call_ber_syntax_callback(decode_as_syntax, tvb, 0, pinfo, tree);
if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
/* see if we have a better name */
name = get_ber_oid_syntax(decode_as_syntax);
col_clear(pinfo->cinfo, COL_PROTOCOL);
col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "%s", name ? name : decode_as_syntax);
}
}
(void) dissect_unknown_ber(pinfo, tvb, 0, tree);
}
void
proto_register_ber(void)
{
@ -2521,6 +2673,8 @@ proto_register_ber(void)
" ASN.1 BER details such as Identifier and Length fields", &show_internal_ber_fields);
ber_oid_dissector_table = register_dissector_table("ber.oid", "BER OID Dissectors", FT_STRING, BASE_NONE);
ber_syntax_dissector_table = register_dissector_table("ber.syntax", "BER Syntax Dissectors", FT_STRING, BASE_NONE);
syntax_table=g_hash_table_new(g_str_hash, g_str_equal); /* oid to syntax */
}
void

View File

@ -26,6 +26,7 @@
#ifndef __PACKET_BER_H__
#define __PACKET_BER_H__
#include <epan/proto.h>
#include <epan/to_str.h>
#define BER_NOT_DECODED_YET(x) \
@ -174,8 +175,15 @@ extern proto_item *get_ber_last_created_item(void);
int call_ber_oid_callback(const char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
void register_ber_oid_dissector_handle(const char *oid, dissector_handle_t dissector, int proto, const char *name);
void register_ber_oid_dissector(const char *oid, dissector_t dissector, int proto, const char *name);
void register_ber_syntax_dissector(const char *oid, int proto, dissector_t dissector);
void register_ber_oid_name(const char *oid, const char *name);
void register_ber_oid_syntax(const char *oid, const char *name, const char *syntax);
void dissect_ber_oid_NULL_callback(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
void ber_decode_as_foreach(GHFunc func, gpointer user_data); /* iterate through known syntaxes */
void ber_decode_as(gchar *syntax); /* decode the current capture as this syntax */
void ber_set_filename(gchar *filename); /* name of current BER-encoded file */
gboolean oid_has_dissector(const char *oid);
#endif /* __PACKET_BER_H__ */

View File

@ -1304,4 +1304,8 @@ void proto_reg_handoff_s4406(void) {
#line 114 "packet-s4406-template.c"
register_ber_oid_dissector("1.3.26.0.4406.0.4.1", dissect_s4406, proto_s4406, "Military Message");
register_ber_syntax_dissector("MilitaryMessage", proto_s4406, dissect_s4406);
register_ber_oid_syntax(".p772", NULL, "MilitaryMessage");
}

View File

@ -1,6 +1,6 @@
/* Do not modify this file. */
/* It is created automatically by the ASN.1 to Wireshark dissector compiler */
/* .\packet-x509af.c */
/* ./packet-x509af.c */
/* ../../tools/asn2wrs.py -b -e -p x509af -c x509af.cnf -s packet-x509af-template AuthenticationFramework.asn */
/* Input file: packet-x509af-template.c */
@ -1557,5 +1557,12 @@ void proto_reg_handoff_x509af(void) {
register_ldap_name_dissector("crossCertificatePair", dissect_CertificatePair_PDU, proto_x509af);
register_ber_syntax_dissector("Certificate", proto_x509af, dissect_Certificate_PDU);
register_ber_oid_syntax(".cer", NULL, "Certificate");
register_ber_oid_syntax(".crt", NULL, "Certificate");
register_ber_syntax_dissector("CertificateList", proto_x509af, dissect_CertificateList_PDU);
register_ber_oid_syntax(".crl", NULL, "CertificateList");
register_ber_syntax_dissector("CrossCertificatePair", proto_x509af, dissect_CertificatePair_PDU);
}

View File

@ -1,6 +1,6 @@
/* Do not modify this file. */
/* It is created automatically by the ASN.1 to Wireshark dissector compiler */
/* .\packet-x509af.h */
/* ./packet-x509af.h */
/* ../../tools/asn2wrs.py -b -e -p x509af -c x509af.cnf -s packet-x509af-template AuthenticationFramework.asn */
/* Input file: packet-x509af-template.h */

View File

@ -30,6 +30,9 @@ ansi_a_ios501_dtap_strings DATA
ansi_map_opr_code_strings DATA
asn1_ctx_init
BandRejectReason_vals DATA
ber_decode_as
ber_decode_as_foreach
ber_set_filename
build_follow_filter
bytes_to_str_punct
bytes_to_str
@ -599,6 +602,8 @@ reassembled_table_init
register_all_plugin_tap_listeners
register_all_protocols
register_all_protocol_handoffs
register_ber_syntax_dissector
register_ber_oid_syntax
register_dissector
register_dissector_table
register_final_registration_routine

6
file.c
View File

@ -72,6 +72,7 @@
#include "stat_menu.h"
#include "tap_dfilter_dlg.h"
#include <epan/dissectors/packet-data.h>
#include <epan/dissectors/packet-ber.h>
#include <epan/timestamp.h>
#include "file_util.h"
@ -265,6 +266,11 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
fileset_file_opened(fname);
if(cf->cd_t == WTAP_FILE_BER) {
/* tell the BER dissector the file name */
ber_set_filename(cf->filename);
}
return CF_OK;
fail:

View File

@ -55,6 +55,7 @@ WIRESHARK_GTK_SRC = \
colors.c \
column_prefs.c \
conversations_table.c \
decode_as_ber.c \
decode_as_dlg.c \
decode_as_dcerpc.c \
dfilter_expr_dlg.c \

165
gtk/decode_as_ber.c Normal file
View File

@ -0,0 +1,165 @@
/* decode_as_ber.c
*
* $Id$
*
* Routines to modify BER decoding on the fly.
*
* Copyright 2006 Graeme Lunt
*
* 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 <gtk/gtk.h>
#include <string.h>
#include "decode_as_dlg.h"
#include "dlg_utils.h"
#include "globals.h"
#include "simple_dialog.h"
#include <epan/packet.h>
#include <epan/ipproto.h>
#include "gui_utils.h"
#include <epan/epan_dissect.h>
#include "compat_macros.h"
#include "decode_as_dcerpc.h"
#include "decode_as_ber.h"
#include <epan/dissectors/packet-ber.h>
/**************************************************/
/* Action routines for the "Decode As..." dialog */
/* - called when the OK button pressed */
/**************************************************/
/*
* This routine is called when the user clicks the "OK" button in the
* "Decode As..." dialog window and the ASN.1 page is foremost.
* This routine takes care of making any changes requested to the ASN.1
* decoding.
*
* @param notebook_pg A pointer to the "ASN.1" notebook page.
*/
static void
decode_ber(GtkWidget *notebook_pg)
{
GtkWidget *list;
gchar *syntax;
#if GTK_MAJOR_VERSION < 2
gint row;
#else
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
#endif
syntax = NULL;
list = OBJECT_GET_DATA(notebook_pg, E_PAGE_LIST);
if (requested_action == E_DECODE_NO)
#if GTK_MAJOR_VERSION < 2
gtk_clist_unselect_all(GTK_CLIST(list));
#else
gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
#endif
#if GTK_MAJOR_VERSION < 2
if (!GTK_CLIST(list)->selection)
{
syntax = NULL;
} else {
row = GPOINTER_TO_INT(GTK_CLIST(list)->selection->data);
gtk_clist_get_text(GTK_CLIST(list), row, E_LIST_S_PROTO_NAME, &syntax);
}
#else
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
{
syntax = NULL;
} else {
gtk_tree_model_get(model, &iter, E_LIST_S_PROTO_NAME, &syntax, -1);
}
#endif
if ((syntax != NULL && strcmp(syntax, "(default)") == 0) ) {
ber_decode_as(NULL);
} else {
ber_decode_as(syntax);
}
#if GTK_MAJOR_VERSION >= 2
if (syntax != NULL)
g_free(syntax);
#endif
}
/**************************************************/
/* Dialog setup */
/**************************************************/
/* add an interface to the list */
static void
decode_ber_add_to_list(gpointer key, gpointer value, gpointer user_data)
{
decode_add_to_list("ASN.1", key, value, user_data);
}
/* add all interfaces to the list */
static GtkWidget *
decode_add_ber_menu (GtkWidget *page, const gchar *table_name _U_)
{
GtkWidget *scrolled_window;
GtkWidget *list;
decode_list_menu_start(page, &list, &scrolled_window);
ber_decode_as_foreach(decode_ber_add_to_list, list);
decode_list_menu_finish(list);
return(scrolled_window);
}
/* add a BER page to the notebook */
GtkWidget *
decode_ber_add_page (packet_info *pinfo)
{
GtkWidget *page_hb, *info_vb, *label, *scrolled_window;
/* create page content */
page_hb = gtk_hbox_new(FALSE, 5);
OBJECT_SET_DATA(page_hb, E_PAGE_ACTION, decode_ber);
OBJECT_SET_DATA(page_hb, E_PAGE_TABLE, "ASN.1");
OBJECT_SET_DATA(page_hb, E_PAGE_TITLE, "ASN.1");
info_vb = gtk_vbox_new(FALSE, 5);
gtk_box_pack_start(GTK_BOX(page_hb), info_vb, TRUE, TRUE, 0);
/* Always enabled */
label = gtk_label_new("Decode ASN.1 file as:");
gtk_box_pack_start(GTK_BOX(info_vb), label, TRUE, TRUE, 0);
scrolled_window = decode_add_ber_menu(page_hb, "ber" /*table_name*/);
gtk_box_pack_start(GTK_BOX(page_hb), scrolled_window, TRUE, TRUE, 0);
decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
return(page_hb);
}

39
gtk/decode_as_ber.h Normal file
View File

@ -0,0 +1,39 @@
/* decode_as_ber.h
*
* $Id$
*
* Routines to modify BER decoding on the fly.
* Only internally used between decode_as_dlg and decode_as_ber
*
* Copyright 2006 Graeme Lunt
*
* 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.
*
*/
#ifndef __DECODE_AS_BER_H__
#define __DECODE_AS_BER_H__
/** @file
* "Decode As" / "User Specified Decodes" dialog box.
* @ingroup dialog_group
*/
#define E_PAGE_BER "notebook_page_ber" /* ber only */
extern GtkWidget *
decode_ber_add_page(packet_info *pinfo);
#endif

View File

@ -39,6 +39,7 @@
#include <epan/epan_dissect.h>
#include "compat_macros.h"
#include "decode_as_dcerpc.h"
#include "decode_as_ber.h"
#include "help_dlg.h"
#undef DEBUG
@ -71,6 +72,8 @@ enum srcdst_type {
#define E_PAGE_DPORT "dport"
#define E_PAGE_SPORT "sport"
#define E_PAGE_PPID "ppid"
#define E_PAGE_ASN1 "asn1"
/*
* Columns for a "Display" list
@ -1770,7 +1773,8 @@ gboolean
decode_as_ok(void)
{
return cfile.edt->pi.ethertype || cfile.edt->pi.ipproto ||
cfile.edt->pi.ptype == PT_TCP || cfile.edt->pi.ptype == PT_UDP;
cfile.edt->pi.ptype == PT_TCP || cfile.edt->pi.ptype == PT_UDP ||
cfile.cd_t == WTAP_FILE_BER;
}
@ -1844,6 +1848,13 @@ decode_add_notebook (GtkWidget *format_hb)
OBJECT_SET_DATA(decode_w, E_PAGE_DCERPC, page);
}
if(cfile.cd_t == WTAP_FILE_BER) {
page = decode_ber_add_page(&cfile.edt->pi);
label = gtk_label_new("ASN.1");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
OBJECT_SET_DATA(decode_w, E_PAGE_ASN1, page);
}
/* Select the last added page (selects first by default) */
/* Notebook must be visible for set_page to work. */
gtk_widget_show_all(notebook);