2004-02-20 10:04:10 +00:00
/* packet-ber.c
* Helpers for ASN .1 / BER dissection
* Ronnie Sahlberg ( C ) 2004
*
2006-05-21 04:49:01 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
2004-02-20 10:04:10 +00:00
* 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
2012-06-28 22:56:06 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2004-02-20 10:04:10 +00:00
*/
2006-03-09 16:00:33 +00:00
/*
2004-03-25 09:18:03 +00:00
* ITU - T Recommendation X .690 ( 07 / 2002 ) ,
* Information technology ASN .1 encoding rules :
* Specification of Basic Encoding Rules ( BER ) , Canonical Encoding Rules ( CER ) and Distinguished Encoding Rules ( DER )
2006-03-09 16:00:33 +00:00
*
*/
2011-11-22 21:51:24 +00:00
/* TODO: change #.REGISTER signature to new_dissector_t and
* update call_ber_oid_callback ( ) accordingly .
*
* Since we don ' t pass the TAG / LENGTH from the CHOICE / SEQUENCE / SEQUENCE OF /
* SET OF helpers through the callbacks to the next pabket - ber helper
* when the tags are IMPLICIT , this causes a problem when we also have
* indefinite length at the same time as the tags are implicit .
*
* While the proper fix is to change the signatures for packet - ber . c helpers
* as well as the signatures for the callbacks to include the indefinite length
* indication that would be a major job .
*
* Originally we used a kludge - we set a global variable in the
* CHOICE / SEQUENCE [ OF ] / SET [ OF ] helpers to indicate to the next helper
* whether the length is indefinite or not .
* That had currently only been implemented for { SEQUENCE | SET } [ OF ] but not
* CHOICE .
*
* This version attacks the problem ( s ) in a different way . If we see
* indefinite length the get_ber_length traverses the tags within the
* compound value and then we return the true length of the compound value
* including the EOC . Thus the tvb length is now always correct even for
* indefinite length , then if we get implicit tags they can be handled as
* if they were definite length .
*/
/*#define DEBUG_BER 1*/
2004-03-25 09:18:03 +00:00
2012-09-20 02:03:38 +00:00
# include "config.h"
2004-02-20 10:04:10 +00:00
# include <stdio.h>
# include <epan/packet.h>
2013-11-10 15:59:37 +00:00
# include <epan/exceptions.h>
2005-09-06 05:30:06 +00:00
# include <epan/reassemble.h>
2007-08-25 01:14:24 +00:00
# include <epan/oids.h>
2006-12-19 22:04:22 +00:00
# include <epan/expert.h>
2010-06-28 09:33:04 +00:00
# include <epan/uat.h>
2013-11-20 19:17:08 +00:00
# include <epan/decode_as.h>
2013-12-21 17:23:17 +00:00
# include <wiretap/wtap.h>
2010-09-30 19:20:59 +00:00
2004-02-20 10:04:10 +00:00
# include "packet-ber.h"
2011-11-22 21:51:24 +00:00
/*
* Set a limit on recursion so we don ' t blow away the stack . Another approach
* would be to remove recursion completely but then we ' d exhaust CPU + memory
* trying to read a hellabyte of nested indefinite lengths .
2012-08-10 22:55:02 +00:00
2011-11-22 21:51:24 +00:00
* XXX - Max nesting in the ASN .1 plugin is 32. Should they match ?
*/
# define BER_MAX_NESTING 500
2013-03-15 16:39:30 +00:00
void proto_register_ber ( void ) ;
void proto_reg_handoff_ber ( void ) ;
2004-02-20 10:04:10 +00:00
static gint proto_ber = - 1 ;
static gint hf_ber_id_class = - 1 ;
static gint hf_ber_id_pc = - 1 ;
static gint hf_ber_id_uni_tag = - 1 ;
2005-09-18 16:54:00 +00:00
static gint hf_ber_id_uni_tag_ext = - 1 ;
2004-02-20 10:04:10 +00:00
static gint hf_ber_id_tag = - 1 ;
2005-09-18 16:54:00 +00:00
static gint hf_ber_id_tag_ext = - 1 ;
2004-02-20 10:04:10 +00:00
static gint hf_ber_length = - 1 ;
static gint hf_ber_bitstring_padding = - 1 ;
2007-02-17 14:23:09 +00:00
static gint hf_ber_bitstring_empty = - 1 ;
2004-11-25 22:27:52 +00:00
static gint hf_ber_unknown_OID = - 1 ;
2014-04-07 23:41:25 +00:00
static gint hf_ber_unknown_relative_OID = - 1 ;
2005-10-27 11:27:40 +00:00
static gint hf_ber_unknown_BOOLEAN = - 1 ;
2004-11-25 22:27:52 +00:00
static gint hf_ber_unknown_OCTETSTRING = - 1 ;
2007-02-17 11:10:02 +00:00
static gint hf_ber_unknown_BER_OCTETSTRING = - 1 ;
2010-01-30 17:44:45 +00:00
static gint hf_ber_unknown_BER_primitive = - 1 ;
2005-06-24 10:03:20 +00:00
static gint hf_ber_unknown_GraphicString = - 1 ;
2004-12-12 22:59:43 +00:00
static gint hf_ber_unknown_NumericString = - 1 ;
2004-11-18 10:46:27 +00:00
static gint hf_ber_unknown_PrintableString = - 1 ;
2005-12-14 20:45:15 +00:00
static gint hf_ber_unknown_TeletexString = - 1 ;
2007-02-17 11:10:02 +00:00
static gint hf_ber_unknown_VisibleString = - 1 ;
static gint hf_ber_unknown_GeneralString = - 1 ;
2007-08-18 17:39:44 +00:00
static gint hf_ber_unknown_UniversalString = - 1 ;
static gint hf_ber_unknown_BMPString = - 1 ;
2004-11-25 21:30:38 +00:00
static gint hf_ber_unknown_IA5String = - 1 ;
2005-12-14 20:45:15 +00:00
static gint hf_ber_unknown_UTCTime = - 1 ;
2005-10-27 11:27:40 +00:00
static gint hf_ber_unknown_UTF8String = - 1 ;
static gint hf_ber_unknown_GeneralizedTime = - 1 ;
2004-11-18 10:46:27 +00:00
static gint hf_ber_unknown_INTEGER = - 1 ;
2014-11-28 15:53:04 +00:00
static gint hf_ber_unknown_REAL = - 1 ;
2005-12-14 20:45:15 +00:00
static gint hf_ber_unknown_BITSTRING = - 1 ;
2004-12-12 22:59:43 +00:00
static gint hf_ber_unknown_ENUMERATED = - 1 ;
2011-04-06 08:52:42 +00:00
static gint hf_ber_error = - 1 ;
2007-05-03 21:52:57 +00:00
static gint hf_ber_direct_reference = - 1 ; /* OBJECT_IDENTIFIER */
static gint hf_ber_indirect_reference = - 1 ; /* INTEGER */
static gint hf_ber_data_value_descriptor = - 1 ; /* ObjectDescriptor */
static gint hf_ber_encoding = - 1 ; /* T_encoding */
static gint hf_ber_single_ASN1_type = - 1 ; /* T_single_ASN1_type */
static gint hf_ber_octet_aligned = - 1 ; /* OCTET_STRING */
static gint hf_ber_arbitrary = - 1 ; /* BIT_STRING */
2004-02-20 10:04:10 +00:00
2014-11-01 20:55:25 +00:00
/* Generated from convert_proto_tree_add_text.pl */
static int hf_ber_seq_of_eoc = - 1 ;
static int hf_ber_choice_eoc = - 1 ;
static int hf_ber_seq_field_eoc = - 1 ;
static int hf_ber_seq_eoc = - 1 ;
static int hf_ber_set_field_eoc = - 1 ;
static int hf_ber_set_eoc = - 1 ;
static int hf_ber_null_tag = - 1 ;
static int hf_ber_unknown_octetstring = - 1 ;
static int hf_ber_unknown_data = - 1 ;
2010-08-24 15:08:07 +00:00
static int hf_ber_fragments = - 1 ;
static int hf_ber_fragment = - 1 ;
static int hf_ber_fragment_overlap = - 1 ;
static int hf_ber_fragment_overlap_conflicts = - 1 ;
static int hf_ber_fragment_multiple_tails = - 1 ;
static int hf_ber_fragment_too_long_fragment = - 1 ;
static int hf_ber_fragment_error = - 1 ;
2011-01-30 21:01:07 +00:00
static int hf_ber_fragment_count = - 1 ;
2010-08-24 15:08:07 +00:00
static int hf_ber_reassembled_in = - 1 ;
static int hf_ber_reassembled_length = - 1 ;
2004-02-20 10:04:10 +00:00
static gint ett_ber_octet_string = - 1 ;
2010-08-24 15:08:07 +00:00
static gint ett_ber_reassembled_octet_string = - 1 ;
2010-01-30 17:44:45 +00:00
static gint ett_ber_primitive = - 1 ;
2004-11-25 21:30:38 +00:00
static gint ett_ber_unknown = - 1 ;
2004-11-25 22:27:52 +00:00
static gint ett_ber_SEQUENCE = - 1 ;
2007-05-03 21:52:57 +00:00
static gint ett_ber_EXTERNAL = - 1 ;
2007-05-22 21:15:00 +00:00
static gint ett_ber_T_encoding = - 1 ;
2010-08-24 15:08:07 +00:00
static gint ett_ber_fragment = - 1 ;
static gint ett_ber_fragments = - 1 ;
2004-02-20 10:04:10 +00:00
2013-07-02 21:16:10 +00:00
static expert_field ei_ber_size_constraint_string = EI_INIT ;
static expert_field ei_ber_size_constraint_value = EI_INIT ;
static expert_field ei_ber_size_constraint_items = EI_INIT ;
static expert_field ei_ber_sequence_field_wrong = EI_INIT ;
static expert_field ei_ber_expected_octet_string = EI_INIT ;
static expert_field ei_ber_expected_null = EI_INIT ;
static expert_field ei_ber_expected_null_zero_length = EI_INIT ;
static expert_field ei_ber_expected_sequence = EI_INIT ;
static expert_field ei_ber_expected_set = EI_INIT ;
static expert_field ei_ber_expected_string = EI_INIT ;
static expert_field ei_ber_expected_object_identifier = EI_INIT ;
static expert_field ei_ber_expected_generalized_time = EI_INIT ;
static expert_field ei_ber_expected_utc_time = EI_INIT ;
static expert_field ei_ber_expected_bitstring = EI_INIT ;
static expert_field ei_ber_error_length = EI_INIT ;
static expert_field ei_ber_wrong_tag_in_tagged_type = EI_INIT ;
static expert_field ei_ber_universal_tag_unknown = EI_INIT ;
static expert_field ei_ber_no_oid = EI_INIT ;
static expert_field ei_ber_syntax_not_implemented = EI_INIT ;
static expert_field ei_ber_oid_not_implemented = EI_INIT ;
static expert_field ei_ber_value_too_many_bytes = EI_INIT ;
static expert_field ei_ber_unknown_field_sequence = EI_INIT ;
static expert_field ei_ber_unknown_field_set = EI_INIT ;
static expert_field ei_ber_missing_field_set = EI_INIT ;
static expert_field ei_ber_empty_choice = EI_INIT ;
static expert_field ei_ber_choice_not_found = EI_INIT ;
static expert_field ei_ber_bits_unknown = EI_INIT ;
static expert_field ei_ber_bits_set_padded = EI_INIT ;
static expert_field ei_ber_illegal_padding = EI_INIT ;
static expert_field ei_ber_invalid_format_generalized_time = EI_INIT ;
static expert_field ei_ber_invalid_format_utctime = EI_INIT ;
2014-11-01 20:55:25 +00:00
static expert_field ei_hf_field_not_integer_type = EI_INIT ;
2013-07-02 21:16:10 +00:00
2013-08-05 19:09:44 +00:00
static dissector_handle_t ber_handle ;
2012-10-18 02:33:11 +00:00
static gboolean show_internal_ber_fields = FALSE ;
static gboolean decode_octetstring_as_ber = FALSE ;
static gboolean decode_primitive_as_ber = FALSE ;
static gboolean decode_unexpected = FALSE ;
2012-06-05 05:16:06 +00:00
static gboolean decode_warning_leading_zero_bits = FALSE ;
2004-02-20 10:04:10 +00:00
2007-01-13 12:59:27 +00:00
static gchar * decode_as_syntax = NULL ;
2012-10-18 02:33:11 +00:00
static gchar * ber_filename = NULL ;
2007-01-13 12:59:27 +00:00
2012-10-18 02:33:11 +00:00
static dissector_table_t ber_oid_dissector_table = NULL ;
static dissector_table_t ber_syntax_dissector_table = NULL ;
2004-02-20 10:04:10 +00:00
2012-10-18 02:33:11 +00:00
static GHashTable * syntax_table = NULL ;
static gint8 last_class ;
2010-06-02 14:42:57 +00:00
static gboolean last_pc ;
2012-10-18 02:33:11 +00:00
static gint32 last_tag ;
static guint32 last_length ;
2010-06-02 14:42:57 +00:00
static gboolean last_ind ;
2004-02-20 10:04:10 +00:00
static const value_string ber_class_codes [ ] = {
2012-04-23 17:43:56 +00:00
{ BER_CLASS_UNI , " UNIVERSAL " } ,
{ BER_CLASS_APP , " APPLICATION " } ,
{ BER_CLASS_CON , " CONTEXT " } ,
{ BER_CLASS_PRI , " PRIVATE " } ,
{ 0 , NULL }
2004-02-20 10:04:10 +00:00
} ;
static const true_false_string ber_pc_codes = {
2012-04-23 17:43:56 +00:00
" Constructed Encoding " ,
" Primitive Encoding "
2004-02-20 10:04:10 +00:00
} ;
2007-11-19 20:23:49 +00:00
static const true_false_string ber_pc_codes_short = {
2012-04-23 17:43:56 +00:00
" constructed " ,
" primitive "
2007-11-19 20:23:49 +00:00
} ;
2004-02-20 10:04:10 +00:00
static const value_string ber_uni_tag_codes [ ] = {
2012-04-23 17:43:56 +00:00
{ BER_UNI_TAG_EOC , " 'end-of-content' " } ,
{ BER_UNI_TAG_BOOLEAN , " BOOLEAN " } ,
{ BER_UNI_TAG_INTEGER , " INTEGER " } ,
{ BER_UNI_TAG_BITSTRING , " BIT STRING " } ,
{ BER_UNI_TAG_OCTETSTRING , " OCTET STRING " } ,
{ BER_UNI_TAG_NULL , " NULL " } ,
{ BER_UNI_TAG_OID , " OBJECT IDENTIFIER " } ,
{ BER_UNI_TAG_ObjectDescriptor , " ObjectDescriptor " } ,
{ BER_UNI_TAG_EXTERNAL , " EXTERNAL " } ,
{ BER_UNI_TAG_REAL , " REAL " } ,
{ BER_UNI_TAG_ENUMERATED , " ENUMERATED " } ,
{ BER_UNI_TAG_EMBEDDED_PDV , " EMBEDDED PDV " } ,
{ BER_UNI_TAG_UTF8String , " UTF8String " } ,
{ BER_UNI_TAG_RELATIVE_OID , " RELATIVE-OID " } ,
/* UNIVERSAL 14-15
* Reserved for future editions of this
* Recommendation | International Standard
*/
{ 14 , " Reserved for future editions " } ,
{ 15 , " Reserved for future editions " } ,
{ BER_UNI_TAG_SEQUENCE , " SEQUENCE " } ,
{ BER_UNI_TAG_SET , " SET " } ,
{ BER_UNI_TAG_NumericString , " NumericString " } ,
{ BER_UNI_TAG_PrintableString , " PrintableString " } ,
{ BER_UNI_TAG_TeletexString , " TeletexString, T61String " } ,
{ BER_UNI_TAG_VideotexString , " VideotexString " } ,
{ BER_UNI_TAG_IA5String , " IA5String " } ,
{ BER_UNI_TAG_UTCTime , " UTCTime " } ,
{ BER_UNI_TAG_GeneralizedTime , " GeneralizedTime " } ,
{ BER_UNI_TAG_GraphicString , " GraphicString " } ,
{ BER_UNI_TAG_VisibleString , " VisibleString, ISO64String " } ,
{ BER_UNI_TAG_GeneralString , " GeneralString " } ,
{ BER_UNI_TAG_UniversalString , " UniversalString " } ,
{ BER_UNI_TAG_CHARACTERSTRING , " CHARACTER STRING " } ,
{ BER_UNI_TAG_BMPString , " BMPString " } ,
{ 31 , " Continued " } ,
{ 0 , NULL }
2004-02-20 10:04:10 +00:00
} ;
2010-11-11 21:18:15 +00:00
static value_string_ext ber_uni_tag_codes_ext = VALUE_STRING_EXT_INIT ( ber_uni_tag_codes ) ;
2004-02-20 10:04:10 +00:00
2013-10-23 06:29:11 +00:00
#if 0
2007-06-12 21:29:27 +00:00
static const true_false_string ber_real_binary_vals = {
2012-04-23 17:43:56 +00:00
" Binary encoding " ,
" Decimal encoding "
2007-06-12 21:29:27 +00:00
} ;
static const true_false_string ber_real_decimal_vals = {
2012-04-23 17:43:56 +00:00
" SpecialRealValue " ,
" Decimal encoding "
2007-06-12 21:29:27 +00:00
} ;
2013-10-23 06:29:11 +00:00
# endif
2007-06-12 21:29:27 +00:00
2007-01-13 12:59:27 +00:00
typedef struct _da_data {
2012-04-23 17:43:56 +00:00
GHFunc func ;
gpointer user_data ;
2007-01-13 12:59:27 +00:00
} da_data ;
2010-06-28 09:33:04 +00:00
typedef struct _oid_user_t {
2012-04-23 17:43:56 +00:00
char * oid ;
char * name ;
char * syntax ;
2010-06-28 09:33:04 +00:00
} oid_user_t ;
2012-04-13 20:22:31 +00:00
UAT_CSTRING_CB_DEF ( oid_users , oid , oid_user_t )
UAT_CSTRING_CB_DEF ( oid_users , name , oid_user_t )
UAT_VS_CSTRING_DEF ( oid_users , syntax , oid_user_t , 0 , " " )
2010-06-28 09:33:04 +00:00
static oid_user_t * oid_users ;
static guint num_oid_users ;
# define MAX_SYNTAX_NAMES 128
2010-06-29 03:43:17 +00:00
/* Define non_const_value_string as a hack to prevent chackAPIs.pl from complaining */
# define non_const_value_string value_string
static non_const_value_string syntax_names [ MAX_SYNTAX_NAMES + 1 ] = {
2012-04-23 17:43:56 +00:00
{ 0 , " " } ,
{ 0 , NULL }
2010-06-28 09:33:04 +00:00
} ;
2010-08-24 15:08:07 +00:00
static const fragment_items octet_string_frag_items = {
2012-04-23 17:43:56 +00:00
/* Fragment subtrees */
& ett_ber_fragment ,
& ett_ber_fragments ,
/* Fragment fields */
& hf_ber_fragments ,
& hf_ber_fragment ,
& hf_ber_fragment_overlap ,
& hf_ber_fragment_overlap_conflicts ,
& hf_ber_fragment_multiple_tails ,
& hf_ber_fragment_too_long_fragment ,
& hf_ber_fragment_error ,
& hf_ber_fragment_count ,
/* Reassembled in field */
& hf_ber_reassembled_in ,
/* Reassembled length field */
& hf_ber_reassembled_length ,
2012-09-07 02:09:59 +00:00
/* Reassembled data field */
NULL ,
2012-04-23 17:43:56 +00:00
/* Tag */
" OCTET STRING fragments "
2010-08-24 15:08:07 +00:00
} ;
2010-06-28 09:33:04 +00:00
static void *
2010-10-29 21:11:33 +00:00
oid_copy_cb ( void * dest , const void * orig , size_t len _U_ )
2010-06-28 09:33:04 +00:00
{
2013-03-15 16:39:30 +00:00
oid_user_t * u = ( oid_user_t * ) dest ;
const oid_user_t * o = ( const oid_user_t * ) orig ;
2010-06-28 09:33:04 +00:00
2012-04-23 17:43:56 +00:00
u - > oid = g_strdup ( o - > oid ) ;
u - > name = g_strdup ( o - > name ) ;
u - > syntax = o - > syntax ;
2010-06-28 09:33:04 +00:00
2012-04-23 17:43:56 +00:00
return dest ;
2010-06-28 09:33:04 +00:00
}
static void
oid_free_cb ( void * r )
{
2013-03-15 16:39:30 +00:00
oid_user_t * u = ( oid_user_t * ) r ;
2010-06-28 09:33:04 +00:00
2012-04-23 17:43:56 +00:00
g_free ( u - > oid ) ;
g_free ( u - > name ) ;
2010-06-28 09:33:04 +00:00
}
static int
cmp_value_string ( const void * v1 , const void * v2 )
{
2013-03-15 16:39:30 +00:00
const value_string * vs1 = ( const value_string * ) v1 ;
const value_string * vs2 = ( const value_string * ) v2 ;
2010-06-28 09:33:04 +00:00
2012-04-23 17:43:56 +00:00
return strcmp ( vs1 - > strptr , vs2 - > strptr ) ;
2010-06-28 09:33:04 +00:00
}
static uat_field_t users_flds [ ] = {
2012-04-23 17:43:56 +00:00
UAT_FLD_OID ( oid_users , oid , " OID " , " Object Identifier " ) ,
UAT_FLD_CSTRING ( oid_users , name , " Name " , " Human readable name for the OID " ) ,
UAT_FLD_VS ( oid_users , syntax , " Syntax " , syntax_names , " Syntax of values associated with the OID " ) ,
UAT_END_FIELDS
2010-06-28 09:33:04 +00:00
} ;
2004-02-20 10:04:10 +00:00
2013-11-20 19:17:08 +00:00
static void ber_prompt ( packet_info * pinfo _U_ , gchar * result )
{
g_snprintf ( result , MAX_DECODE_AS_PROMPT_LEN , " Decode ASN.1 file as " ) ;
}
static gpointer ber_value ( packet_info * pinfo _U_ )
{
/* Not used */
return NULL ;
}
struct ber_decode_as_populate
{
decode_as_add_to_list_func add_to_list ;
gpointer ui_element ;
} ;
static void
decode_ber_add_to_list ( gpointer key , gpointer value , gpointer user_data )
{
struct ber_decode_as_populate * populate = ( struct ber_decode_as_populate * ) user_data ;
populate - > add_to_list ( " ASN.1 " , ( gchar * ) key , value , populate - > ui_element ) ;
}
2013-11-20 19:52:21 +00:00
static void ber_populate_list ( const gchar * table_name _U_ , decode_as_add_to_list_func add_to_list , gpointer ui_element )
2013-11-20 19:17:08 +00:00
{
struct ber_decode_as_populate populate ;
populate . add_to_list = add_to_list ;
populate . ui_element = ui_element ;
ber_decode_as_foreach ( decode_ber_add_to_list , & populate ) ;
}
static gboolean ber_decode_as_reset ( const char * name _U_ , const gpointer pattern _U_ )
{
ber_decode_as ( NULL ) ;
return FALSE ;
}
static gboolean ber_decode_as_change ( const char * name _U_ , const gpointer pattern _U_ , gpointer handle _U_ , gchar * list_name )
{
ber_decode_as ( list_name ) ;
return FALSE ;
}
2004-07-29 09:52:14 +00:00
void
dissect_ber_oid_NULL_callback ( tvbuff_t * tvb _U_ , packet_info * pinfo _U_ , proto_tree * tree _U_ )
{
2012-04-23 17:43:56 +00:00
return ;
2004-07-29 09:52:14 +00:00
}
2005-06-07 05:49:06 +00:00
void
2005-07-28 07:53:38 +00:00
register_ber_oid_dissector_handle ( const char * oid , dissector_handle_t dissector , int proto _U_ , const char * name )
2005-06-07 05:49:06 +00:00
{
2012-04-23 17:43:56 +00:00
dissector_add_string ( " ber.oid " , oid , dissector ) ;
oid_add_from_string ( name , oid ) ;
2005-06-07 05:49:06 +00:00
}
2004-07-23 07:08:14 +00:00
void
2005-07-28 07:53:38 +00:00
register_ber_oid_dissector ( const char * oid , dissector_t dissector , int proto , const char * name )
2004-07-23 07:08:14 +00:00
{
2012-04-23 17:43:56 +00:00
dissector_handle_t dissector_handle ;
2004-07-23 07:08:14 +00:00
2012-10-18 02:33:11 +00:00
dissector_handle = create_dissector_handle ( dissector , proto ) ;
2012-04-23 17:43:56 +00:00
dissector_add_string ( " ber.oid " , oid , dissector_handle ) ;
oid_add_from_string ( name , oid ) ;
2004-07-23 07:08:14 +00:00
}
2005-06-07 05:49:06 +00:00
2014-10-06 13:17:46 +00:00
void
new_register_ber_oid_dissector ( const char * oid , new_dissector_t dissector , int proto , const char * name )
{
dissector_handle_t dissector_handle ;
dissector_handle = new_create_dissector_handle ( dissector , proto ) ;
dissector_add_string ( " ber.oid " , oid , dissector_handle ) ;
oid_add_from_string ( name , oid ) ;
}
2010-07-07 15:52:09 +00:00
void
2007-01-13 12:59:27 +00:00
register_ber_syntax_dissector ( const char * syntax , int proto , dissector_t dissector )
{
2012-04-23 17:43:56 +00:00
dissector_handle_t dissector_handle ;
2007-01-13 12:59:27 +00:00
2012-10-18 02:33:11 +00:00
dissector_handle = create_dissector_handle ( dissector , proto ) ;
2012-04-23 17:43:56 +00:00
dissector_add_string ( " ber.syntax " , syntax , dissector_handle ) ;
2010-07-07 15:52:09 +00:00
2007-01-13 12:59:27 +00:00
}
2014-10-06 13:17:46 +00:00
void
new_register_ber_syntax_dissector ( const char * syntax , int proto , new_dissector_t dissector )
{
dissector_handle_t dissector_handle ;
dissector_handle = new_create_dissector_handle ( dissector , proto ) ;
dissector_add_string ( " ber.syntax " , syntax , dissector_handle ) ;
}
2007-01-13 12:59:27 +00:00
void
register_ber_oid_syntax ( const char * oid , const char * name , const char * syntax )
{
2012-10-18 02:33:11 +00:00
if ( syntax & & * syntax )
2012-04-23 17:43:56 +00:00
g_hash_table_insert ( syntax_table , ( gpointer ) g_strdup ( oid ) , ( gpointer ) g_strdup ( syntax ) ) ;
2007-01-13 12:59:27 +00:00
2012-10-18 02:33:11 +00:00
if ( name & & * name )
2012-04-23 17:43:56 +00:00
register_ber_oid_name ( oid , name ) ;
2007-01-13 12:59:27 +00:00
}
/* Register the oid name to get translation in proto dissection */
void
register_ber_oid_name ( const char * oid , const char * name )
{
2012-04-23 17:43:56 +00:00
oid_add_from_string ( name , oid ) ;
2007-01-13 12:59:27 +00:00
}
2010-07-07 15:52:09 +00:00
static void
2010-06-28 09:33:04 +00:00
ber_add_syntax_name ( gpointer key , gpointer value _U_ , gpointer user_data )
{
2012-04-23 17:43:56 +00:00
guint * i = ( guint * ) user_data ;
2010-06-28 09:33:04 +00:00
2012-10-18 02:33:11 +00:00
if ( * i < MAX_SYNTAX_NAMES ) {
2012-04-23 17:43:56 +00:00
syntax_names [ * i ] . value = * i ;
syntax_names [ * i ] . strptr = ( const gchar * ) key ;
2010-06-28 09:33:04 +00:00
2012-04-23 17:43:56 +00:00
( * i ) + + ;
}
2010-06-28 09:33:04 +00:00
}
2012-10-18 02:33:11 +00:00
static void
ber_decode_as_dt ( const gchar * table_name _U_ , ftenum_t selector_type _U_ , gpointer key , gpointer value , gpointer user_data )
2007-01-13 12:59:27 +00:00
{
2012-04-23 17:43:56 +00:00
da_data * decode_as_data ;
2010-07-07 15:52:09 +00:00
2012-04-23 17:43:56 +00:00
decode_as_data = ( da_data * ) user_data ;
2007-01-13 12:59:27 +00:00
2012-04-23 17:43:56 +00:00
decode_as_data - > func ( key , value , decode_as_data - > user_data ) ;
2007-01-13 12:59:27 +00:00
}
2012-10-18 02:33:11 +00:00
void
ber_decode_as_foreach ( GHFunc func , gpointer user_data )
2007-01-13 12:59:27 +00:00
{
2012-04-23 17:43:56 +00:00
da_data decode_as_data ;
2007-01-13 12:59:27 +00:00
2012-04-23 17:43:56 +00:00
decode_as_data . func = func ;
decode_as_data . user_data = user_data ;
2007-01-13 12:59:27 +00:00
2012-04-23 17:43:56 +00:00
dissector_table_foreach ( " ber.syntax " , ber_decode_as_dt , & decode_as_data ) ;
2007-01-13 12:59:27 +00:00
}
2012-10-18 02:33:11 +00:00
void
ber_decode_as ( const gchar * syntax )
2007-01-13 12:59:27 +00:00
{
2012-10-18 02:33:11 +00:00
if ( decode_as_syntax ) {
2012-04-23 17:43:56 +00:00
g_free ( decode_as_syntax ) ;
decode_as_syntax = NULL ;
}
2007-01-13 12:59:27 +00:00
2012-10-18 02:33:11 +00:00
if ( syntax )
2012-04-23 17:43:56 +00:00
decode_as_syntax = g_strdup ( syntax ) ;
2007-01-13 12:59:27 +00:00
}
/* Get oid syntax from hash table to get translation in proto dissection(packet-per.c) */
2007-04-23 10:59:26 +00:00
static const gchar *
2007-01-13 12:59:27 +00:00
get_ber_oid_syntax ( const char * oid )
{
2013-03-15 16:39:30 +00:00
return ( const char * ) g_hash_table_lookup ( syntax_table , oid ) ;
2007-01-13 12:59:27 +00:00
}
2012-10-18 02:33:11 +00:00
void
ber_set_filename ( gchar * filename )
2007-01-13 12:59:27 +00:00
{
2012-04-23 17:43:56 +00:00
gchar * ptr ;
2007-01-13 12:59:27 +00:00
2012-10-18 02:33:11 +00:00
if ( ber_filename ) {
2012-04-23 17:43:56 +00:00
g_free ( ber_filename ) ;
ber_filename = NULL ;
}
2007-01-13 12:59:27 +00:00
2012-10-18 02:33:11 +00:00
if ( filename ) {
2007-01-13 12:59:27 +00:00
2012-04-23 17:43:56 +00:00
ber_filename = g_strdup ( filename ) ;
2007-01-13 12:59:27 +00:00
2012-10-18 02:33:11 +00:00
if ( ( ptr = strrchr ( ber_filename , ' . ' ) ) ! = NULL ) {
2010-07-07 15:52:09 +00:00
2012-04-23 17:43:56 +00:00
ber_decode_as ( get_ber_oid_syntax ( ptr ) ) ;
2007-01-13 12:59:27 +00:00
2012-04-23 17:43:56 +00:00
}
2007-01-13 12:59:27 +00:00
}
}
2010-06-23 11:28:59 +00:00
static void
2010-06-28 09:33:04 +00:00
ber_update_oids ( void )
2010-06-23 11:28:59 +00:00
{
2012-04-23 17:43:56 +00:00
guint i ;
2010-06-23 11:28:59 +00:00
2012-10-18 02:33:11 +00:00
for ( i = 0 ; i < num_oid_users ; i + + )
2012-04-23 17:43:56 +00:00
register_ber_oid_syntax ( oid_users [ i ] . oid , oid_users [ i ] . name , oid_users [ i ] . syntax ) ;
2010-06-28 09:33:04 +00:00
}
2010-06-23 14:26:19 +00:00
2009-12-18 15:18:31 +00:00
static void
2010-01-05 11:38:33 +00:00
ber_check_length ( guint32 length , gint32 min_len , gint32 max_len , asn1_ctx_t * actx , proto_item * item , gboolean bit )
2009-12-18 15:18:31 +00:00
{
2012-10-18 02:33:11 +00:00
if ( ( min_len ! = - 1 ) & & ( length < ( guint32 ) min_len ) ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , item , & ei_ber_size_constraint_string ,
2012-10-18 02:33:11 +00:00
" Size constraint: %sstring too short: %d (%d .. %d) " ,
bit ? " bit " : " " , length , min_len , max_len ) ;
} else if ( ( max_len ! = - 1 ) & & ( length > ( guint32 ) max_len ) ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , item , & ei_ber_size_constraint_string ,
2012-10-18 02:33:11 +00:00
" Size constraint: %sstring too long: %d (%d .. %d) " ,
bit ? " bit " : " " , length , min_len , max_len ) ;
2012-04-23 17:43:56 +00:00
}
2009-12-18 15:18:31 +00:00
}
static void
ber_check_value64 ( gint64 value , gint64 min_len , gint64 max_len , asn1_ctx_t * actx , proto_item * item )
{
2012-10-18 02:33:11 +00:00
if ( ( min_len ! = - 1 ) & & ( value < min_len ) ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , item , & ei_ber_size_constraint_value ,
2012-10-18 02:33:11 +00:00
" Size constraint: value too small: % " G_GINT64_MODIFIER " d (% " G_GINT64_MODIFIER " d .. % " G_GINT64_MODIFIER " d) " ,
value , min_len , max_len ) ;
} else if ( ( max_len ! = - 1 ) & & ( value > max_len ) ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , item , & ei_ber_size_constraint_value ,
2012-10-18 02:33:11 +00:00
" Size constraint: value too big: % " G_GINT64_MODIFIER " d (% " G_GINT64_MODIFIER " d .. % " G_GINT64_MODIFIER " d) " ,
value , min_len , max_len ) ;
2012-04-23 17:43:56 +00:00
}
2009-12-18 15:18:31 +00:00
}
static void
ber_check_value ( guint32 value , gint32 min_len , gint32 max_len , asn1_ctx_t * actx , proto_item * item )
{
2012-10-18 02:33:11 +00:00
if ( ( min_len ! = - 1 ) & & ( value < ( guint32 ) min_len ) ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , item , & ei_ber_size_constraint_value ,
2012-10-18 02:33:11 +00:00
" Size constraint: value too small: %d (%d .. %d) " ,
value , min_len , max_len ) ;
} else if ( ( max_len ! = - 1 ) & & ( value > ( guint32 ) max_len ) ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , item , & ei_ber_size_constraint_value ,
2012-10-18 02:33:11 +00:00
" Size constraint: value too big: %d (%d .. %d) " ,
value , min_len , max_len ) ;
2012-04-23 17:43:56 +00:00
}
2009-12-18 15:18:31 +00:00
}
static void
ber_check_items ( int cnt , gint32 min_len , gint32 max_len , asn1_ctx_t * actx , proto_item * item )
{
2012-10-18 02:33:11 +00:00
if ( ( min_len ! = - 1 ) & & ( cnt < min_len ) ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , item , & ei_ber_size_constraint_items ,
2012-10-18 02:33:11 +00:00
" Size constraint: too few items: %d (%d .. %d) " ,
cnt , min_len , max_len ) ;
} else if ( ( max_len ! = - 1 ) & & ( cnt > max_len ) ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , item , & ei_ber_size_constraint_items ,
2012-10-18 02:33:11 +00:00
" Size constraint: too many items: %d (%d .. %d) " ,
cnt , min_len , max_len ) ;
2012-04-23 17:43:56 +00:00
}
2009-12-18 15:18:31 +00:00
}
2014-09-14 00:21:56 +00:00
/*
* XXX - if the specified length is less than the remaining length
* of data in the tvbuff , either 1 ) the specified length is bad and
* we should report that with an expert info or 2 ) the tvbuff is
* unreassembled and we should make the new tvbuff also be an
* unreassembled tvbuff .
*/
static tvbuff_t *
ber_tvb_new_subset_length ( tvbuff_t * tvb , const gint backing_offset , const gint backing_length )
{
gint length_remaining ;
length_remaining = tvb_reported_length_remaining ( tvb , backing_offset ) ;
return tvb_new_subset_length ( tvb , backing_offset , ( length_remaining > backing_length ) ? backing_length : length_remaining ) ;
}
2012-10-18 02:33:11 +00:00
int
dissect_ber_tagged_type ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , gint8 tag_cls , gint32 tag_tag , gboolean tag_impl , ber_type_fn type )
2006-06-15 07:46:07 +00:00
{
2012-10-18 02:33:11 +00:00
gint8 tmp_cls ;
gint32 tmp_tag ;
guint32 tmp_len ;
tvbuff_t * next_tvb = tvb ;
2012-04-23 17:43:56 +00:00
proto_item * cause ;
2006-06-15 07:46:07 +00:00
2007-11-13 21:59:53 +00:00
# ifdef DEBUG_BER
2012-10-18 02:33:11 +00:00
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 3 ) {
printf ( " dissect_ber_tagged_type(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x \n " , name , implicit_tag , offset , tvb_reported_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
printf ( " dissect_ber_tagged_type(%s) entered \n " , name ) ;
}
}
2007-11-13 21:59:53 +00:00
# endif
2012-04-23 17:43:56 +00:00
if ( implicit_tag ) {
offset = type ( tag_impl , tvb , offset , actx , tree , hf_id ) ;
return offset ;
}
2006-06-15 07:46:07 +00:00
2012-04-23 17:43:56 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & tmp_cls , NULL , & tmp_tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & tmp_len , NULL ) ;
2007-05-03 19:56:13 +00:00
2012-04-23 17:43:56 +00:00
if ( ( tmp_cls ! = tag_cls ) | | ( tmp_tag ! = tag_tag ) ) {
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , tmp_len , " wrong_tag " ,
2013-09-30 15:21:09 +00:00
" Wrong tag in tagged type - expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( tag_cls , ber_class_codes , " Unknown " ) ,
tag_cls ,
tag_tag ,
val_to_str_ext_const ( tag_tag , & ber_uni_tag_codes_ext , " Unknown " ) ,
val_to_str_const ( tmp_cls , ber_class_codes , " Unknown " ) ,
tmp_cls ,
tmp_tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_wrong_tag_in_tagged_type ) ;
2012-04-23 17:43:56 +00:00
}
2006-06-15 07:46:07 +00:00
2012-04-23 17:43:56 +00:00
if ( tag_impl ) {
2014-09-14 00:21:56 +00:00
next_tvb = ber_tvb_new_subset_length ( tvb , offset , tmp_len ) ;
2012-04-23 17:43:56 +00:00
type ( tag_impl , next_tvb , 0 , actx , tree , hf_id ) ;
offset + = tmp_len ;
} else {
offset = type ( tag_impl , tvb , offset , actx , tree , hf_id ) ;
}
2006-06-15 07:46:07 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2006-06-15 07:46:07 +00:00
}
2011-01-02 21:27:57 +00:00
/*
* Add a " length bogus " error .
*/
static proto_item *
ber_add_bad_length_error ( packet_info * pinfo , proto_tree * tree ,
const char * name , tvbuff_t * tvb , const gint start ,
gint length )
{
2012-04-23 17:43:56 +00:00
proto_item * ti ;
2011-01-02 21:27:57 +00:00
2012-10-18 02:33:11 +00:00
ti = proto_tree_add_string_format (
tree , hf_ber_error , tvb , start , length , " illegal_length " ,
" %s: length of item (%d) is not valid " ,
name , length ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
pinfo , ti , & ei_ber_error_length ,
2012-04-23 17:43:56 +00:00
" Length of item (%d) is not valid " , length ) ;
return ti ;
2011-01-02 21:27:57 +00:00
}
/*
* Like proto_tree_add_item ( ) , but checks whether the length of the item
* being added is appropriate for the type of the item being added , so
* if it ' s not , we report an error rather than a dissector bug .
*
* This is for use when a field that ' s nominally an OCTET STRING but
* where we want the string further interpreted , e . g . as a number or
* a network address or a UN * X - style time stamp .
2011-01-02 21:49:00 +00:00
*
* XXX - this duplicates the length checking in proto_tree_add_item ( )
* and the routines it calls ; that should really be done in one
* place . We * do * want to report a dissector bug in proto_tree_add_item ( )
* if the dissector explicitly says , for example , " this IPv4 address is
* 7 bytes long " , but we don't want to report a dissector bug if the
* * packet * says " this IPv4 address is 7 bytes long " , we want to report
* a malformed packet .
2011-01-02 21:27:57 +00:00
*/
static proto_item *
ber_proto_tree_add_item ( packet_info * pinfo , proto_tree * tree ,
const int hfindex , tvbuff_t * tvb , const gint start ,
gint length , const guint encoding )
{
2012-04-23 17:43:56 +00:00
header_field_info * hfinfo ;
hfinfo = proto_registrar_get_nth ( ( guint ) hfindex ) ;
if ( hfinfo ! = NULL ) {
switch ( hfinfo - > type ) {
case FT_BOOLEAN :
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2012-10-18 02:33:11 +00:00
if ( ( length ! = 1 ) & & ( length ! = 2 ) & & ( length ! = 3 ) & &
( length ! = 4 ) )
2012-04-23 17:43:56 +00:00
return ber_add_bad_length_error ( pinfo , tree ,
hfinfo - > name , tvb , start , length ) ;
break ;
case FT_IPv4 :
if ( length ! = FT_IPv4_LEN )
return ber_add_bad_length_error ( pinfo , tree ,
hfinfo - > name , tvb , start , length ) ;
break ;
case FT_IPXNET :
if ( length ! = FT_IPXNET_LEN )
return ber_add_bad_length_error ( pinfo , tree ,
hfinfo - > name , tvb , start , length ) ;
break ;
case FT_IPv6 :
2012-10-18 02:33:11 +00:00
if ( ( length < 0 ) | | ( length > FT_IPv6_LEN ) )
2012-04-23 17:43:56 +00:00
return ber_add_bad_length_error ( pinfo , tree ,
hfinfo - > name , tvb , start , length ) ;
break ;
case FT_ETHER :
if ( length ! = FT_ETHER_LEN )
return ber_add_bad_length_error ( pinfo , tree ,
hfinfo - > name , tvb , start , length ) ;
break ;
case FT_GUID :
if ( length ! = FT_GUID_LEN )
return ber_add_bad_length_error ( pinfo , tree ,
hfinfo - > name , tvb , start , length ) ;
break ;
case FT_FLOAT :
if ( length ! = 4 )
return ber_add_bad_length_error ( pinfo , tree ,
hfinfo - > name , tvb , start , length ) ;
break ;
case FT_DOUBLE :
if ( length ! = 8 )
return ber_add_bad_length_error ( pinfo , tree ,
hfinfo - > name , tvb , start , length ) ;
break ;
case FT_ABSOLUTE_TIME :
case FT_RELATIVE_TIME :
2012-10-18 02:33:11 +00:00
if ( ( length ! = 4 ) & & ( length ! = 8 ) )
2012-04-23 17:43:56 +00:00
return ber_add_bad_length_error ( pinfo , tree ,
hfinfo - > name , tvb , start , length ) ;
break ;
default :
break ;
}
}
return proto_tree_add_item ( tree , hfindex , tvb , start , length , encoding ) ;
2011-01-02 21:27:57 +00:00
}
2010-09-13 18:49:55 +00:00
static int
2010-10-15 18:41:12 +00:00
try_dissect_unknown_ber ( packet_info * pinfo , tvbuff_t * tvb , volatile int offset , proto_tree * tree , gint nest_level )
2004-11-18 10:46:27 +00:00
{
2012-10-18 02:33:11 +00:00
int start_offset ;
gint8 ber_class ;
gboolean pc , ind ;
gint32 tag ;
guint32 len ;
int hdr_len ;
proto_item * item = NULL ;
proto_tree * next_tree = NULL ;
guint8 c ;
guint32 i ;
gboolean is_printable ;
volatile gboolean is_decoded_as ;
proto_item * pi , * cause ;
asn1_ctx_t asn1_ctx ;
2012-04-23 17:43:56 +00:00
if ( nest_level > BER_MAX_NESTING ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
2012-10-18 02:33:11 +00:00
start_offset = offset ;
2012-04-23 17:43:56 +00:00
asn1_ctx_init ( & asn1_ctx , ASN1_ENC_BER , TRUE , pinfo ) ;
2012-10-18 02:33:11 +00:00
offset = get_ber_identifier ( tvb , offset , & ber_class , & pc , & tag ) ;
offset = get_ber_length ( tvb , offset , & len , & ind ) ;
2012-04-23 17:43:56 +00:00
2014-10-31 09:48:47 +00:00
if ( len > ( guint32 ) tvb_reported_length_remaining ( tvb , offset ) ) {
2012-10-18 02:33:11 +00:00
/* hmm maybe something bad happened or the frame is short;
2012-04-23 17:43:56 +00:00
since these are not vital outputs just return instead of
throwing an exception .
*/
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
offset = dissect_ber_identifier ( pinfo , tree , tvb , start_offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( pinfo , tree , tvb , offset , & len , NULL ) ;
}
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " illegal_length " ,
2014-10-31 09:48:47 +00:00
" length:%u longer than tvb_reported_length_remaining:%d " ,
2012-10-18 02:33:11 +00:00
len ,
2014-10-31 09:48:47 +00:00
tvb_reported_length_remaining ( tvb , offset ) ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( pinfo , cause , & ei_ber_error_length ) ;
2014-10-31 09:48:47 +00:00
return tvb_reported_length ( tvb ) ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
/* we don't care about the class only on the constructor flag */
switch ( pc ) {
2012-04-23 17:43:56 +00:00
case FALSE : /* this is not constructed */
2012-10-18 02:33:11 +00:00
switch ( ber_class ) { /* we do care about the class */
2012-04-23 17:43:56 +00:00
case BER_CLASS_UNI : /* it a Universal tag - we can decode it */
2012-10-18 02:33:11 +00:00
switch ( tag ) {
2012-04-23 17:43:56 +00:00
case BER_UNI_TAG_EOC :
/* XXX: shouldn't really get here */
break ;
case BER_UNI_TAG_INTEGER :
offset = dissect_ber_integer ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_INTEGER , NULL ) ;
break ;
2014-11-28 15:53:04 +00:00
case BER_UNI_TAG_REAL :
offset = dissect_ber_real ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_REAL , NULL ) ;
break ;
2012-04-23 17:43:56 +00:00
case BER_UNI_TAG_BITSTRING :
offset = dissect_ber_bitstring ( FALSE , & asn1_ctx , tree , tvb , start_offset , NULL , hf_ber_unknown_BITSTRING , - 1 , NULL ) ;
break ;
case BER_UNI_TAG_ENUMERATED :
offset = dissect_ber_integer ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_ENUMERATED , NULL ) ;
break ;
case BER_UNI_TAG_GraphicString :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_GraphicString , NULL ) ;
break ;
case BER_UNI_TAG_OCTETSTRING :
is_decoded_as = FALSE ;
2012-10-18 02:33:11 +00:00
if ( decode_octetstring_as_ber & & ( len > = 2 ) ) {
2012-04-23 17:43:56 +00:00
volatile int ber_offset = 0 ;
guint32 ber_len = 0 ;
TRY {
ber_offset = get_ber_identifier ( tvb , offset , NULL , & pc , NULL ) ;
ber_offset = get_ber_length ( tvb , ber_offset , & ber_len , NULL ) ;
} CATCH_ALL {
}
ENDTRY ;
if ( pc & & ( ber_len > 0 ) & & ( ber_len + ( ber_offset - offset ) = = len ) ) {
/* Decoded a constructed ASN.1 tag with a length indicating this
* could be BER encoded data . Try dissecting as unknown BER .
*/
is_decoded_as = TRUE ;
if ( show_internal_ber_fields ) {
offset = dissect_ber_identifier ( pinfo , tree , tvb , start_offset , NULL , NULL , NULL ) ;
offset = dissect_ber_length ( pinfo , tree , tvb , offset , NULL , NULL ) ;
}
item = ber_proto_tree_add_item ( pinfo , tree , hf_ber_unknown_BER_OCTETSTRING , tvb , offset , len , ENC_NA ) ;
next_tree = proto_item_add_subtree ( item , ett_ber_octet_string ) ;
offset = try_dissect_unknown_ber ( pinfo , tvb , offset , next_tree , nest_level + 1 ) ;
}
}
if ( ! is_decoded_as ) {
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_OCTETSTRING , NULL ) ;
}
break ;
case BER_UNI_TAG_OID :
2012-10-18 02:33:11 +00:00
offset = dissect_ber_object_identifier_str ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_OID , NULL ) ;
2012-04-23 17:43:56 +00:00
break ;
2013-10-06 02:31:10 +00:00
case BER_UNI_TAG_RELATIVE_OID :
2014-04-07 23:41:25 +00:00
offset = dissect_ber_relative_oid_str ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_relative_OID , NULL ) ;
2013-10-06 02:31:10 +00:00
break ;
2012-04-23 17:43:56 +00:00
case BER_UNI_TAG_NumericString :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_NumericString , NULL ) ;
break ;
case BER_UNI_TAG_PrintableString :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_PrintableString , NULL ) ;
break ;
case BER_UNI_TAG_TeletexString :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_TeletexString , NULL ) ;
break ;
case BER_UNI_TAG_VisibleString :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_VisibleString , NULL ) ;
break ;
case BER_UNI_TAG_GeneralString :
offset = dissect_ber_GeneralString ( & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_GeneralString , NULL , 0 ) ;
break ;
case BER_UNI_TAG_BMPString :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_BMPString , NULL ) ;
break ;
case BER_UNI_TAG_UniversalString :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_UniversalString , NULL ) ;
break ;
case BER_UNI_TAG_IA5String :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_IA5String , NULL ) ;
break ;
case BER_UNI_TAG_UTCTime :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_UTCTime , NULL ) ;
break ;
case BER_UNI_TAG_NULL :
2014-11-01 20:55:25 +00:00
proto_tree_add_item ( tree , hf_ber_null_tag , tvb , offset , len , ENC_NA ) ;
2012-04-23 17:43:56 +00:00
break ;
case BER_UNI_TAG_UTF8String :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_UTF8String , NULL ) ;
break ;
case BER_UNI_TAG_GeneralizedTime :
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_GeneralizedTime , NULL ) ;
break ;
case BER_UNI_TAG_BOOLEAN :
offset = dissect_ber_boolean ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_BOOLEAN , NULL ) ;
break ;
default :
2012-10-18 02:33:11 +00:00
offset = dissect_ber_identifier ( pinfo , tree , tvb , start_offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( pinfo , tree , tvb , offset , & len , NULL ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " unknown_universal_tag " ,
2013-09-30 15:21:09 +00:00
" can not handle universal tag:%d " ,
2012-10-18 02:33:11 +00:00
tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( pinfo , cause , & ei_ber_universal_tag_unknown ) ;
2012-04-23 17:43:56 +00:00
offset + = len ;
}
break ;
case BER_CLASS_APP :
case BER_CLASS_CON :
case BER_CLASS_PRI :
default :
/* we dissect again if show_internal_ber_fields is set */
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
offset = dissect_ber_identifier ( pinfo , tree , tvb , start_offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( pinfo , tree , tvb , offset , & len , NULL ) ;
2012-04-23 17:43:56 +00:00
}
/* we can't dissect this directly as it is specific */
pi = proto_tree_add_none_format ( tree , hf_ber_unknown_BER_primitive , tvb , offset , len ,
2012-10-18 02:33:11 +00:00
" [%s %d] " , val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) , tag ) ;
2012-04-23 17:43:56 +00:00
is_decoded_as = FALSE ;
2012-10-18 02:33:11 +00:00
if ( decode_primitive_as_ber & & ( len > = 2 ) ) {
2012-04-23 17:43:56 +00:00
volatile int ber_offset = 0 ;
guint32 ber_len = 0 ;
TRY {
ber_offset = get_ber_identifier ( tvb , offset , NULL , & pc , NULL ) ;
ber_offset = get_ber_length ( tvb , ber_offset , & ber_len , NULL ) ;
} CATCH_ALL {
}
ENDTRY ;
if ( pc & & ( ber_len > 0 ) & & ( ber_len + ( ber_offset - offset ) = = len ) ) {
/* Decoded a constructed ASN.1 tag with a length indicating this
* could be BER encoded data . Try dissecting as unknown BER .
*/
is_decoded_as = TRUE ;
proto_item_append_text ( pi , " [BER encoded] " ) ;
next_tree = proto_item_add_subtree ( pi , ett_ber_primitive ) ;
offset = try_dissect_unknown_ber ( pinfo , tvb , offset , next_tree , nest_level + 1 ) ;
}
}
if ( ! is_decoded_as & & len ) {
/* we may want to do better and show the bytes */
is_printable = TRUE ;
2012-10-18 02:33:11 +00:00
for ( i = 0 ; i < len ; i + + ) {
2012-04-23 17:43:56 +00:00
c = tvb_get_guint8 ( tvb , offset + i ) ;
2012-10-18 02:33:11 +00:00
if ( is_printable & & ! g_ascii_isprint ( c ) )
is_printable = FALSE ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
proto_item_append_text ( pi , " %02x " , c ) ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( is_printable ) { /* give a nicer representation if it looks like a string */
proto_item_append_text ( pi , " ( " ) ;
for ( i = 0 ; i < len ; i + + ) {
proto_item_append_text ( pi , " %c " , tvb_get_guint8 ( tvb , offset + i ) ) ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
proto_item_append_text ( pi , " ) " ) ;
2012-04-23 17:43:56 +00:00
}
offset + = len ;
}
break ;
}
break ;
case TRUE : /* this is constructed */
/* we dissect again if show_internal_ber_fields is set */
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
offset = dissect_ber_identifier ( pinfo , tree , tvb , start_offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( pinfo , tree , tvb , offset , & len , NULL ) ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
hdr_len = offset - start_offset ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
switch ( ber_class ) {
2012-04-23 17:43:56 +00:00
case BER_CLASS_UNI :
2014-06-22 20:01:36 +00:00
next_tree = proto_tree_add_subtree ( tree , tvb , offset , len , ett_ber_SEQUENCE , NULL ,
val_to_str_ext_const ( tag , & ber_uni_tag_codes_ext , " Unknown " ) ) ;
2012-10-18 02:33:11 +00:00
while ( offset < ( int ) ( start_offset + len + hdr_len ) )
offset = try_dissect_unknown_ber ( pinfo , tvb , offset , next_tree , nest_level + 1 ) ;
2012-04-23 17:43:56 +00:00
break ;
case BER_CLASS_APP :
case BER_CLASS_CON :
case BER_CLASS_PRI :
default :
2014-06-22 20:01:36 +00:00
next_tree = proto_tree_add_subtree_format ( tree , tvb , offset , len , ett_ber_SEQUENCE , NULL ,
" [%s %d] " , val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) , tag ) ;
2012-10-18 02:33:11 +00:00
while ( offset < ( int ) ( start_offset + len + hdr_len ) )
offset = try_dissect_unknown_ber ( pinfo , tvb , offset , next_tree , nest_level + 1 ) ;
2012-04-23 17:43:56 +00:00
break ;
}
break ;
}
return offset ;
2004-11-18 10:46:27 +00:00
}
2010-09-13 18:49:55 +00:00
int
dissect_unknown_ber ( packet_info * pinfo , tvbuff_t * tvb , int offset , proto_tree * tree )
{
2012-04-23 17:43:56 +00:00
return try_dissect_unknown_ber ( pinfo , tvb , offset , tree , 1 ) ;
2010-09-13 18:49:55 +00:00
}
2004-11-18 10:46:27 +00:00
2004-07-20 09:11:40 +00:00
int
2013-10-31 00:57:03 +00:00
call_ber_oid_callback ( const char * oid , tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree , void * data )
2004-07-20 09:11:40 +00:00
{
2012-10-18 02:33:11 +00:00
tvbuff_t * next_tvb ;
2012-04-23 17:43:56 +00:00
const char * syntax = NULL ;
2014-10-06 13:17:46 +00:00
int len = 0 ;
2012-04-23 17:43:56 +00:00
if ( ! tvb ) {
return offset ;
}
next_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
2012-10-18 02:33:11 +00:00
if ( oid = = NULL | |
( ( ( ( syntax = get_ber_oid_syntax ( oid ) ) = = NULL ) | |
/* First see if a syntax has been registered for this oid (user defined) */
2014-10-06 13:17:46 +00:00
( len = dissector_try_string ( ber_syntax_dissector_table , syntax , next_tvb , pinfo , tree , data ) ) = = 0 ) & &
2012-10-18 02:33:11 +00:00
/* Then try registered oid's */
2014-10-06 13:17:46 +00:00
( len = dissector_try_string ( ber_oid_dissector_table , oid , next_tvb , pinfo , tree , data ) ) = = 0 ) )
{
2012-10-18 02:33:11 +00:00
proto_item * item = NULL ;
proto_tree * next_tree = NULL ;
gint length_remaining ;
2012-04-23 17:43:56 +00:00
2014-10-06 13:17:46 +00:00
/* XXX we should probably use get_ber_length() here */
2014-10-31 09:48:47 +00:00
length_remaining = tvb_reported_length_remaining ( tvb , offset ) ;
2012-04-23 17:43:56 +00:00
if ( oid = = NULL ) {
2013-07-02 21:16:10 +00:00
item = proto_tree_add_expert ( tree , pinfo , & ei_ber_no_oid , next_tvb , 0 , length_remaining ) ;
2012-04-23 17:43:56 +00:00
} else if ( tvb_get_ntohs ( tvb , offset ) ! = 0x0500 ) { /* Not NULL tag */
2012-10-18 02:33:11 +00:00
if ( syntax ) {
2013-07-02 21:16:10 +00:00
item = proto_tree_add_expert_format (
tree , pinfo , & ei_ber_syntax_not_implemented , next_tvb , 0 , length_remaining ,
2012-10-18 02:33:11 +00:00
" BER: Dissector for syntax:%s not implemented. "
" Contact Wireshark developers if you want this supported " ,
syntax ) ;
} else {
2013-07-02 21:16:10 +00:00
item = proto_tree_add_expert ( tree , pinfo , & ei_ber_oid_not_implemented , next_tvb , 0 , length_remaining ) ;
2012-10-18 02:33:11 +00:00
}
2012-04-23 17:43:56 +00:00
} else {
2012-10-18 02:33:11 +00:00
next_tree = tree ;
2012-04-23 17:43:56 +00:00
}
if ( decode_unexpected ) {
int ber_offset ;
gint32 ber_len ;
2012-10-18 02:33:11 +00:00
if ( item ) {
next_tree = proto_item_add_subtree ( item , ett_ber_unknown ) ;
2012-04-23 17:43:56 +00:00
}
ber_offset = get_ber_identifier ( next_tvb , 0 , NULL , NULL , NULL ) ;
ber_offset = get_ber_length ( next_tvb , ber_offset , & ber_len , NULL ) ;
if ( ( ber_len + ber_offset ) = = length_remaining ) {
/* Decoded an ASN.1 tag with a length indicating this
* could be BER encoded data . Try dissecting as unknown BER .
*/
2014-10-13 12:05:29 +00:00
dissect_unknown_ber ( pinfo , next_tvb , 0 , next_tree ) ;
2012-04-23 17:43:56 +00:00
} else {
2014-11-01 20:55:25 +00:00
proto_tree_add_item ( next_tree , hf_ber_unknown_data , next_tvb , 0 , length_remaining , ENC_NA ) ;
2012-04-23 17:43:56 +00:00
}
}
2014-10-13 12:05:29 +00:00
len = length_remaining ;
2012-04-23 17:43:56 +00:00
}
2014-10-13 12:05:29 +00:00
offset + = len ;
2012-04-23 17:43:56 +00:00
return offset ;
2004-07-20 09:11:40 +00:00
}
2007-04-23 00:32:04 +00:00
static int
2007-01-13 12:59:27 +00:00
call_ber_syntax_callback ( const char * syntax , tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree )
{
2012-04-23 17:43:56 +00:00
tvbuff_t * next_tvb ;
2014-10-06 13:17:46 +00:00
int len = 0 ;
2012-04-23 17:43:56 +00:00
next_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
2012-10-18 02:33:11 +00:00
if ( syntax = = NULL | |
2014-10-06 13:17:46 +00:00
( len = dissector_try_string ( ber_syntax_dissector_table , syntax , next_tvb , pinfo , tree , NULL ) ) = = 0 )
{
2014-10-13 12:05:29 +00:00
proto_item * item = NULL ;
2012-10-18 02:33:11 +00:00
if ( syntax = = NULL ) {
2013-07-02 21:16:10 +00:00
item = proto_tree_add_expert_format (
2014-06-19 17:18:16 +00:00
tree , pinfo , & ei_ber_no_oid , next_tvb , 0 , tvb_length_remaining ( tvb , offset ) ,
2013-07-02 21:16:10 +00:00
" BER: No syntax supplied to call_ber_syntax_callback " ) ;
2012-10-18 02:33:11 +00:00
} else {
2013-07-02 21:16:10 +00:00
item = proto_tree_add_expert_format (
2014-10-31 09:48:47 +00:00
tree , pinfo , & ei_ber_syntax_not_implemented , next_tvb , 0 , tvb_reported_length_remaining ( tvb , offset ) ,
2013-07-02 21:16:10 +00:00
" BER: Dissector for syntax:%s not implemented. "
" Contact Wireshark developers if you want this supported " ,
syntax ) ;
2012-10-18 02:33:11 +00:00
}
2014-10-13 12:05:29 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( item , ett_ber_unknown ) ;
dissect_unknown_ber ( pinfo , next_tvb , 0 , unknown_tree ) ;
2012-04-23 17:43:56 +00:00
}
2014-10-31 09:48:47 +00:00
len = tvb_reported_length_remaining ( tvb , offset ) ;
2012-04-23 17:43:56 +00:00
}
2007-01-13 12:59:27 +00:00
2014-10-13 12:05:29 +00:00
offset + = len ;
2007-01-13 12:59:27 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2007-01-13 12:59:27 +00:00
}
2004-02-20 10:04:10 +00:00
2004-03-25 09:18:03 +00:00
/* 8.1 General rules for encoding */
/* 8.1.2 Identifier octets */
2012-10-18 02:33:11 +00:00
int
get_ber_identifier ( tvbuff_t * tvb , int offset , gint8 * ber_class , gboolean * pc , gint32 * tag ) {
guint8 id , t ;
gint8 tmp_class ;
2012-04-23 17:43:56 +00:00
gboolean tmp_pc ;
2012-10-18 02:33:11 +00:00
gint32 tmp_tag ;
2004-03-25 09:18:03 +00:00
2012-04-23 17:43:56 +00:00
id = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
2005-03-24 14:21:30 +00:00
# ifdef DEBUG_BER
printf ( " BER ID=%02x " , id ) ;
# endif
2012-04-23 17:43:56 +00:00
/* 8.1.2.2 */
2012-10-18 02:33:11 +00:00
tmp_class = ( id > > 6 ) & 0x03 ;
tmp_pc = ( id > > 5 ) & 0x01 ;
tmp_tag = id & 0x1F ;
2012-04-23 17:43:56 +00:00
/* 8.1.2.4 */
if ( tmp_tag = = 0x1F ) {
tmp_tag = 0 ;
2014-10-31 09:48:47 +00:00
while ( tvb_reported_length_remaining ( tvb , offset ) > 0 ) {
2012-04-23 17:43:56 +00:00
t = tvb_get_guint8 ( tvb , offset ) ;
2005-03-24 14:21:30 +00:00
# ifdef DEBUG_BER
printf ( " %02x " , t ) ;
# endif
2012-04-23 17:43:56 +00:00
offset + = 1 ;
tmp_tag < < = 7 ;
tmp_tag | = t & 0x7F ;
if ( ! ( t & 0x80 ) )
break ;
}
}
2004-03-25 09:18:03 +00:00
2005-03-24 14:21:30 +00:00
# ifdef DEBUG_BER
printf ( " \n " ) ;
# endif
2012-04-23 17:43:56 +00:00
if ( ber_class )
* ber_class = tmp_class ;
if ( pc )
2012-10-18 02:33:11 +00:00
* pc = tmp_pc ;
2012-04-23 17:43:56 +00:00
if ( tag )
* tag = tmp_tag ;
2004-03-25 09:18:03 +00:00
2012-04-23 17:43:56 +00:00
last_class = tmp_class ;
2012-10-18 02:33:11 +00:00
last_pc = tmp_pc ;
2012-04-23 17:43:56 +00:00
last_tag = tmp_tag ;
2010-06-02 14:42:57 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2004-03-25 09:18:03 +00:00
}
2004-02-20 10:04:10 +00:00
2012-10-18 02:33:11 +00:00
static void
get_last_ber_identifier ( gint8 * ber_class , gboolean * pc , gint32 * tag )
2010-06-02 14:42:57 +00:00
{
2012-04-23 17:43:56 +00:00
if ( ber_class )
* ber_class = last_class ;
if ( pc )
2012-10-18 02:33:11 +00:00
* pc = last_pc ;
2012-04-23 17:43:56 +00:00
if ( tag )
* tag = last_tag ;
2010-06-02 14:42:57 +00:00
}
2012-10-18 02:33:11 +00:00
int
dissect_ber_identifier ( packet_info * pinfo _U_ , proto_tree * tree , tvbuff_t * tvb , int offset , gint8 * ber_class , gboolean * pc , gint32 * tag )
2004-03-25 09:18:03 +00:00
{
2012-10-18 02:33:11 +00:00
int old_offset = offset ;
gint8 tmp_class ;
2012-04-23 17:43:56 +00:00
gboolean tmp_pc ;
2012-10-18 02:33:11 +00:00
gint32 tmp_tag ;
2012-04-23 17:43:56 +00:00
offset = get_ber_identifier ( tvb , offset , & tmp_class , & tmp_pc , & tmp_tag ) ;
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
proto_tree_add_uint ( tree , hf_ber_id_class , tvb , old_offset , 1 , tmp_class < < 6 ) ;
proto_tree_add_boolean ( tree , hf_ber_id_pc , tvb , old_offset , 1 , ( tmp_pc ) ? 0x20 : 0x00 ) ;
if ( tmp_tag > 0x1F ) {
if ( tmp_class = = BER_CLASS_UNI ) {
2012-04-23 17:43:56 +00:00
proto_tree_add_uint ( tree , hf_ber_id_uni_tag_ext , tvb , old_offset + 1 , offset - ( old_offset + 1 ) , tmp_tag ) ;
} else {
proto_tree_add_uint ( tree , hf_ber_id_tag_ext , tvb , old_offset + 1 , offset - ( old_offset + 1 ) , tmp_tag ) ;
}
} else {
2012-10-18 02:33:11 +00:00
if ( tmp_class = = BER_CLASS_UNI ) {
2012-04-23 17:43:56 +00:00
proto_tree_add_uint ( tree , hf_ber_id_uni_tag , tvb , old_offset , 1 , tmp_tag ) ;
} else {
proto_tree_add_uint ( tree , hf_ber_id_tag , tvb , old_offset , 1 , tmp_tag ) ;
}
}
}
2012-10-18 02:33:11 +00:00
if ( ber_class )
2012-04-23 17:43:56 +00:00
* ber_class = tmp_class ;
2012-10-18 02:33:11 +00:00
if ( pc )
2012-04-23 17:43:56 +00:00
* pc = tmp_pc ;
2012-10-18 02:33:11 +00:00
if ( tag )
2012-04-23 17:43:56 +00:00
* tag = tmp_tag ;
return offset ;
2004-02-20 10:04:10 +00:00
}
2010-05-23 23:42:58 +00:00
/** Try to get the length octets of the BER TLV.
* Only ( TAGs and ) LENGTHs that fit inside 32 bit integers are supported .
*
* @ return TRUE if we have the entire length , FALSE if we ' re in the middle of
* an indefinite length and haven ' t reached EOC .
2004-02-20 10:04:10 +00:00
*/
2004-03-25 09:18:03 +00:00
/* 8.1.3 Length octets */
2010-07-09 17:07:34 +00:00
2010-07-13 22:41:34 +00:00
static int
try_get_ber_length ( tvbuff_t * tvb , int offset , guint32 * length , gboolean * ind , gint nest_level ) {
2012-10-18 02:33:11 +00:00
guint8 oct , len ;
guint32 indef_len ;
guint32 tmp_length ;
2012-04-23 17:43:56 +00:00
gboolean tmp_ind ;
2012-10-18 02:33:11 +00:00
int tmp_offset , s_offset ;
gint8 tclass ;
2012-04-23 17:43:56 +00:00
gboolean tpc ;
2012-10-18 02:33:11 +00:00
gint32 ttag ;
2012-04-23 17:43:56 +00:00
tmp_length = 0 ;
2012-10-18 02:33:11 +00:00
tmp_ind = FALSE ;
2012-04-23 17:43:56 +00:00
if ( nest_level > BER_MAX_NESTING ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
oct = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
2012-10-18 02:33:11 +00:00
if ( ! ( oct & 0x80 ) ) {
2012-04-23 17:43:56 +00:00
/* 8.1.3.4 */
tmp_length = oct ;
} else {
len = oct & 0x7F ;
2012-10-18 02:33:11 +00:00
if ( len ) {
2012-04-23 17:43:56 +00:00
/* 8.1.3.5 */
while ( len - - ) {
oct = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
tmp_length = ( tmp_length < < 8 ) + oct ;
}
} else {
/* 8.1.3.6 */
tmp_offset = offset ;
/* ok in here we can traverse the BER to find the length, this will fix most indefinite length issues */
/* Assumption here is that indefinite length is always used on constructed types*/
/* check for EOC */
while ( tvb_get_guint8 ( tvb , offset ) | | tvb_get_guint8 ( tvb , offset + 1 ) ) {
/* not an EOC at offset */
2012-10-18 02:33:11 +00:00
s_offset = offset ;
2012-04-23 17:43:56 +00:00
offset = get_ber_identifier ( tvb , offset , & tclass , & tpc , & ttag ) ;
2012-10-18 02:33:11 +00:00
offset = try_get_ber_length ( tvb , offset , & indef_len , NULL , nest_level + 1 ) ;
2012-04-23 17:43:56 +00:00
tmp_length + = indef_len + ( offset - s_offset ) ; /* length + tag and length */
offset + = indef_len ;
2010-07-13 22:41:34 +00:00
/* Make sure we've moved forward in the packet */
2012-04-23 17:43:56 +00:00
if ( offset < = s_offset )
THROW ( ReportedBoundsError ) ;
}
tmp_length + = 2 ;
tmp_ind = TRUE ;
offset = tmp_offset ;
}
}
if ( length )
* length = tmp_length ;
if ( ind )
* ind = tmp_ind ;
2004-02-20 10:04:10 +00:00
2008-01-09 17:06:25 +00:00
# ifdef DEBUG_BER
2014-10-31 09:48:47 +00:00
printf ( " get BER length %d, offset %d (remaining %d) \n " , tmp_length , offset , tvb_reported_length_remaining ( tvb , offset ) ) ;
2008-01-09 17:06:25 +00:00
# endif
2012-04-23 17:43:56 +00:00
return offset ;
2010-05-23 23:42:58 +00:00
}
2010-07-07 15:52:09 +00:00
2010-05-23 23:42:58 +00:00
int
2010-07-07 15:52:09 +00:00
get_ber_length ( tvbuff_t * tvb , int offset , guint32 * length , gboolean * ind )
2010-06-02 13:33:37 +00:00
{
2012-04-23 17:43:56 +00:00
return try_get_ber_length ( tvb , offset , length , ind , 1 ) ;
2004-02-20 10:04:10 +00:00
}
2012-10-18 02:33:11 +00:00
static void
get_last_ber_length ( guint32 * length , gboolean * ind )
2010-06-02 14:42:57 +00:00
{
2012-04-23 17:43:56 +00:00
if ( length )
* length = last_length ;
if ( ind )
* ind = last_ind ;
2010-06-02 14:42:57 +00:00
}
2004-03-25 09:18:03 +00:00
/* this function dissects the length octets of the BER TLV.
* We only handle ( TAGs and ) LENGTHs that fit inside 32 bit integers .
2004-02-20 10:04:10 +00:00
*/
2004-03-25 09:18:03 +00:00
int
dissect_ber_length ( packet_info * pinfo _U_ , proto_tree * tree , tvbuff_t * tvb , int offset , guint32 * length , gboolean * ind )
2004-02-20 10:04:10 +00:00
{
2012-10-18 02:33:11 +00:00
int old_offset = offset ;
guint32 tmp_length ;
2012-04-23 17:43:56 +00:00
gboolean tmp_ind ;
offset = get_ber_length ( tvb , offset , & tmp_length , & tmp_ind ) ;
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
if ( tmp_ind ) {
2014-11-01 20:55:25 +00:00
proto_tree_add_uint_format_value ( tree , hf_ber_length , tvb , old_offset , 1 , tmp_length , " Indefinite length %d " , tmp_length ) ;
2012-04-23 17:43:56 +00:00
} else {
proto_tree_add_uint ( tree , hf_ber_length , tvb , old_offset , offset - old_offset , tmp_length ) ;
}
}
2012-10-18 02:33:11 +00:00
if ( length )
2012-04-23 17:43:56 +00:00
* length = tmp_length ;
2012-10-18 02:33:11 +00:00
if ( ind )
2012-04-23 17:43:56 +00:00
* ind = tmp_ind ;
2008-01-09 17:06:25 +00:00
# ifdef DEBUG_BER
2014-10-31 09:48:47 +00:00
printf ( " dissect BER length %d, offset %d (remaining %d) \n " , tmp_length , offset , tvb_reported_length_remaining ( tvb , offset ) ) ;
2008-01-09 17:06:25 +00:00
# endif
2012-04-23 17:43:56 +00:00
last_length = tmp_length ;
last_ind = tmp_ind ;
2010-06-02 14:42:57 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2004-03-25 09:18:03 +00:00
}
2009-10-17 21:42:51 +00:00
2013-03-22 23:59:54 +00:00
static reassembly_table octet_segment_reassembly_table ;
2009-10-17 21:42:51 +00:00
static void ber_defragment_init ( void ) {
2013-03-22 23:59:54 +00:00
reassembly_table_init ( & octet_segment_reassembly_table ,
& addresses_reassembly_table_functions ) ;
2009-10-17 21:42:51 +00:00
}
2010-08-24 15:08:07 +00:00
static int
reassemble_octet_string ( asn1_ctx_t * actx , proto_tree * tree , gint hf_id , tvbuff_t * tvb , int offset , guint32 con_len , gboolean ind , tvbuff_t * * out_tvb )
2005-09-06 05:30:06 +00:00
{
2013-07-17 21:12:24 +00:00
fragment_head * fd_head = NULL ;
2012-10-18 02:33:11 +00:00
tvbuff_t * next_tvb = NULL ;
tvbuff_t * reassembled_tvb = NULL ;
guint16 dst_ref = 0 ;
int start_offset = offset ;
gboolean fragment = TRUE ;
gboolean firstFragment = TRUE ;
2005-09-06 05:30:06 +00:00
2012-04-23 17:43:56 +00:00
/* so we need to consume octet strings for the given length */
2005-09-06 05:30:06 +00:00
2012-10-18 02:33:11 +00:00
if ( out_tvb )
* out_tvb = NULL ;
2010-06-28 17:26:07 +00:00
2012-04-23 17:43:56 +00:00
if ( con_len = = 0 ) /* Zero encodings (8.7.3) */
return offset ;
2010-09-30 06:19:32 +00:00
2012-04-23 17:43:56 +00:00
/* not sure we need this */
actx - > pinfo - > fragmented = TRUE ;
2010-09-30 06:19:32 +00:00
2012-04-23 17:43:56 +00:00
while ( ! fd_head ) {
2005-09-06 05:30:06 +00:00
2012-04-23 17:43:56 +00:00
offset = dissect_ber_octet_string ( FALSE , actx , NULL , tvb , offset , hf_id , & next_tvb ) ;
2005-09-06 05:30:06 +00:00
2012-04-23 17:43:56 +00:00
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
2005-09-07 15:40:59 +00:00
2012-10-18 02:33:11 +00:00
if ( ind ) {
2012-04-23 17:43:56 +00:00
/* this was indefinite length - so check for EOC */
2006-03-09 16:00:33 +00:00
2012-10-18 02:33:11 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
2012-04-23 17:43:56 +00:00
fragment = FALSE ;
/* skip past EOC */
offset + = 2 ;
}
} else {
2006-03-09 16:00:33 +00:00
2012-10-18 02:33:11 +00:00
if ( ( guint32 ) ( offset - start_offset ) > = con_len )
2012-04-23 17:43:56 +00:00
fragment = FALSE ;
}
2005-09-06 05:30:06 +00:00
2012-10-18 02:33:11 +00:00
if ( ! fragment & & firstFragment ) {
2012-04-23 17:43:56 +00:00
/* there is only one fragment (I'm sure there's a reason it was constructed) */
/* anyway, we can get out of here */
gboolean pc ;
get_ber_identifier ( tvb , start_offset , NULL , & pc , NULL ) ;
if ( ! pc & & tree ) {
/* Only display here if not constructed */
dissect_ber_octet_string ( FALSE , actx , tree , tvb , start_offset , hf_id , NULL ) ;
}
reassembled_tvb = next_tvb ;
break ;
}
2005-09-06 05:30:06 +00:00
2005-09-20 17:23:19 +00:00
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length ( next_tvb ) < 1 ) {
2012-04-23 17:43:56 +00:00
/* Don't cause an assertion in the reassembly code. */
THROW ( ReportedBoundsError ) ;
}
2013-03-22 23:59:54 +00:00
fd_head = fragment_add_seq_next ( & octet_segment_reassembly_table ,
next_tvb , 0 , actx - > pinfo , dst_ref , NULL ,
2014-10-31 09:48:47 +00:00
tvb_reported_length ( next_tvb ) ,
2012-04-23 17:43:56 +00:00
fragment ) ;
2005-09-06 05:30:06 +00:00
2012-04-23 17:43:56 +00:00
firstFragment = FALSE ;
}
2005-09-06 05:30:06 +00:00
2012-10-18 02:33:11 +00:00
if ( fd_head ) {
if ( fd_head - > next ) {
2012-04-23 17:43:56 +00:00
/* not sure I really want to do this here - should be nearer the application where we can give it a better name*/
proto_tree * next_tree ;
proto_item * frag_tree_item ;
2010-08-24 15:08:07 +00:00
2013-07-14 14:42:05 +00:00
reassembled_tvb = tvb_new_chain ( next_tvb , fd_head - > tvb_data ) ;
2005-09-06 05:30:06 +00:00
2012-04-23 17:43:56 +00:00
actx - > created_item = proto_tree_add_item ( tree , hf_id , reassembled_tvb , 0 , - 1 , ENC_BIG_ENDIAN ) ;
next_tree = proto_item_add_subtree ( actx - > created_item , ett_ber_reassembled_octet_string ) ;
2010-08-24 15:08:07 +00:00
2012-04-23 17:43:56 +00:00
add_new_data_source ( actx - > pinfo , reassembled_tvb , " Reassembled OCTET STRING " ) ;
show_fragment_seq_tree ( fd_head , & octet_string_frag_items , next_tree , actx - > pinfo , reassembled_tvb , & frag_tree_item ) ;
}
2005-09-06 05:30:06 +00:00
}
2012-10-18 02:33:11 +00:00
if ( out_tvb )
2012-04-23 17:43:56 +00:00
* out_tvb = reassembled_tvb ;
2005-09-06 05:30:06 +00:00
2012-04-23 17:43:56 +00:00
/* again - not sure we need this */
actx - > pinfo - > fragmented = FALSE ;
2006-03-09 16:00:33 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2005-09-06 05:30:06 +00:00
}
2004-03-25 09:18:03 +00:00
/* 8.7 Encoding of an octetstring value */
2006-03-09 16:00:33 +00:00
int
2009-12-18 15:18:31 +00:00
dissect_ber_constrained_octet_string ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint32 min_len , gint32 max_len , gint hf_id , tvbuff_t * * out_tvb ) {
2012-10-18 02:33:11 +00:00
gint8 ber_class ;
gboolean pc , ind ;
gint32 tag ;
guint32 len ;
Handle string types with somewhat appropriate encodings.
For various string types defined in X.680, use the appropriate encoding,
or ENC_ASCII|ENC_NA in some cases where we don't have an appropriate
encoding yet.
This most significantly fixes the handling of BMPString and
UniversalString, which are supersets of ASCII (Unicode Basic
Multilingual Plane and Unicode, respectively), but don't encode ASCII
characters as single octets. It also fixes UTF8String to, well,
properly recognize UTF-8.
This also lets us get rid of the special handling of SyntaxBMPString in
X.509sat (and, in fact, *requires* us to get rid of it, as, otherwise,
the string value appears twice).
Change-Id: I325c4e71a6110278eb23b86e0d986e6439cfc328
Reviewed-on: https://code.wireshark.org/review/994
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-04-07 22:39:55 +00:00
guint encoding ;
2012-10-18 02:33:11 +00:00
int hoffset ;
int end_offset ;
2012-04-23 17:43:56 +00:00
proto_item * it , * cause ;
2012-10-18 02:33:11 +00:00
guint32 len_remain ;
2004-02-20 10:04:10 +00:00
2004-11-14 05:10:44 +00:00
# ifdef DEBUG_BER
{
2007-05-02 20:37:25 +00:00
const char * name ;
2004-11-14 05:10:44 +00:00
header_field_info * hfinfo ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2004-11-14 05:10:44 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2004-11-14 05:10:44 +00:00
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 3 ) {
printf ( " OCTET STRING dissect_ber_octet string(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x \n " , name , implicit_tag , offset , tvb_reported_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
printf ( " OCTET STRING dissect_ber_octet_string(%s) entered \n " , name ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2004-02-20 10:04:10 +00:00
2012-10-18 02:33:11 +00:00
if ( out_tvb )
* out_tvb = NULL ;
2012-04-23 17:43:56 +00:00
if ( ! implicit_tag ) {
hoffset = offset ;
/* read header and len for the octet string */
2012-10-18 02:33:11 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , & ind ) ;
end_offset = offset + len ;
2012-04-23 17:43:56 +00:00
/* sanity check: we only handle Constructed Universal Sequences */
2012-10-18 02:33:11 +00:00
if ( ( ber_class ! = BER_CLASS_APP ) & & ( ber_class ! = BER_CLASS_PRI ) ) {
if ( ( ber_class ! = BER_CLASS_UNI )
| | ( ( tag < BER_UNI_TAG_NumericString ) & & ( tag ! = BER_UNI_TAG_OCTETSTRING ) & & ( tag ! = BER_UNI_TAG_UTF8String ) ) ) {
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " octetstring_expected " ,
2013-09-30 15:21:09 +00:00
" OctetString expected but class:%s(%d) %s tag:%d was unexpected " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class ,
pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_octet_string ) ;
2012-10-18 02:33:11 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
return end_offset ;
2012-04-23 17:43:56 +00:00
}
}
} else {
2012-10-18 02:33:11 +00:00
/* implicit tag so get from last tag/length */
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
get_last_ber_identifier ( & ber_class , & pc , & tag ) ;
get_last_ber_length ( & len , & ind ) ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
end_offset = offset + len ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
/* caller may have created new buffer for indefinite length data Verify via length */
2014-10-31 09:48:47 +00:00
len_remain = ( guint32 ) tvb_reported_length_remaining ( tvb , offset ) ;
2012-10-18 02:33:11 +00:00
if ( ind & & ( len_remain = = ( len - 2 ) ) ) {
2012-04-23 17:43:56 +00:00
/* new buffer received so adjust length and indefinite flag */
2012-10-18 02:33:11 +00:00
len - = 2 ;
2012-04-23 17:43:56 +00:00
end_offset - = 2 ;
ind = FALSE ;
2012-10-18 02:33:11 +00:00
} else if ( len_remain < len ) {
2012-04-23 17:43:56 +00:00
/*
* error - short frame , or this item runs past the
* end of the item containing it
*/
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " illegal_length " ,
2014-10-31 09:48:47 +00:00
" length:%u longer than tvb_reported_length_remaining:%d " ,
2012-10-18 02:33:11 +00:00
len ,
len_remain ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_error_length ) ;
2012-10-18 02:33:11 +00:00
return end_offset ;
}
2012-04-23 17:43:56 +00:00
}
actx - > created_item = NULL ;
if ( pc ) {
/* constructed */
end_offset = reassemble_octet_string ( actx , tree , hf_id , tvb , offset , len , ind , out_tvb ) ;
} else {
/* primitive */
gint length_remaining ;
2014-10-31 09:48:47 +00:00
length_remaining = tvb_reported_length_remaining ( tvb , offset ) ;
2007-01-14 20:54:39 +00:00
#if 0
2012-10-18 02:33:11 +00:00
if ( length_remaining < 1 ) {
2012-04-23 17:43:56 +00:00
return end_offset ;
}
2007-01-14 20:54:39 +00:00
# endif
2005-09-21 01:47:46 +00:00
2012-10-18 02:33:11 +00:00
if ( len < = ( guint32 ) length_remaining ) {
length_remaining = len ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
Handle string types with somewhat appropriate encodings.
For various string types defined in X.680, use the appropriate encoding,
or ENC_ASCII|ENC_NA in some cases where we don't have an appropriate
encoding yet.
This most significantly fixes the handling of BMPString and
UniversalString, which are supersets of ASCII (Unicode Basic
Multilingual Plane and Unicode, respectively), but don't encode ASCII
characters as single octets. It also fixes UTF8String to, well,
properly recognize UTF-8.
This also lets us get rid of the special handling of SyntaxBMPString in
X.509sat (and, in fact, *requires* us to get rid of it, as, otherwise,
the string value appears twice).
Change-Id: I325c4e71a6110278eb23b86e0d986e6439cfc328
Reviewed-on: https://code.wireshark.org/review/994
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-04-07 22:39:55 +00:00
/*
2014-08-11 09:40:17 +00:00
* Strings are special . See X .680 section 41 " Definition of
* restricted character string types " and X.690 section 8.20
* " Encoding for values of the restricted character string
* types " .
*
* Some restricted character string types are defined in X .680
* " by reference to a registration number in the ISO International
* Register of Character Sets " - or, in Table 8, by multiple
* registration numbers , or one or more registration numbers
* plus some characters such as SPACE and / or DELETE , or a
* reference to " all G sets " or " all G sets and all C sets " .
* Presumably this indicates which characters are allowed
* in strings of those character types , with " all {G,C} sets "
* meaning the only restriction is to character sets registered
* in said registry .
*
* The encodings of those types are specified in X .690 as
* containing " the octets specified in ISO/IEC 2022 for
* encodings in an 8 - bit environment , using the escape sequence
* and character codings registered in accordance with ISO / IEC
* 2375 " .
*
* ISO / IEC 2022 is also ECMA - 35 :
*
* http : //www.ecma-international.org/publications/files/ECMA-ST/Ecma-035.pdf
*
* ISO / IEC 2375 is the procedure for registering character
* codings in the ISO International Register of Character Sets .
* See
*
* http : //kikaku.itscj.ipsj.or.jp/ISO-IR/
*
* and
*
* http : //kikaku.itscj.ipsj.or.jp/ISO-IR/overview.htm
*
* for that registry .
Handle string types with somewhat appropriate encodings.
For various string types defined in X.680, use the appropriate encoding,
or ENC_ASCII|ENC_NA in some cases where we don't have an appropriate
encoding yet.
This most significantly fixes the handling of BMPString and
UniversalString, which are supersets of ASCII (Unicode Basic
Multilingual Plane and Unicode, respectively), but don't encode ASCII
characters as single octets. It also fixes UTF8String to, well,
properly recognize UTF-8.
This also lets us get rid of the special handling of SyntaxBMPString in
X.509sat (and, in fact, *requires* us to get rid of it, as, otherwise,
the string value appears twice).
Change-Id: I325c4e71a6110278eb23b86e0d986e6439cfc328
Reviewed-on: https://code.wireshark.org/review/994
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-04-07 22:39:55 +00:00
*/
switch ( tag ) {
case BER_UNI_TAG_UTF8String :
/*
* UTF - 8 , obviously .
*/
encoding = ENC_UTF_8 | ENC_NA ;
break ;
case BER_UNI_TAG_NumericString :
case BER_UNI_TAG_PrintableString :
case BER_UNI_TAG_VisibleString :
case BER_UNI_TAG_IA5String :
/*
* ( Subsets of ) Boring Old ASCII , with no ( ? ) ISO 2022
2014-08-11 09:40:17 +00:00
* escape sequences .
Handle string types with somewhat appropriate encodings.
For various string types defined in X.680, use the appropriate encoding,
or ENC_ASCII|ENC_NA in some cases where we don't have an appropriate
encoding yet.
This most significantly fixes the handling of BMPString and
UniversalString, which are supersets of ASCII (Unicode Basic
Multilingual Plane and Unicode, respectively), but don't encode ASCII
characters as single octets. It also fixes UTF8String to, well,
properly recognize UTF-8.
This also lets us get rid of the special handling of SyntaxBMPString in
X.509sat (and, in fact, *requires* us to get rid of it, as, otherwise,
the string value appears twice).
Change-Id: I325c4e71a6110278eb23b86e0d986e6439cfc328
Reviewed-on: https://code.wireshark.org/review/994
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-04-07 22:39:55 +00:00
*/
encoding = ENC_ASCII | ENC_NA ;
break ;
case BER_UNI_TAG_TeletexString :
/*
2014-08-11 09:40:17 +00:00
* XXX - the G0 part of this starts out as T .61 , not ASCII .
*
* XXX - treat as ASCII for now .
Handle string types with somewhat appropriate encodings.
For various string types defined in X.680, use the appropriate encoding,
or ENC_ASCII|ENC_NA in some cases where we don't have an appropriate
encoding yet.
This most significantly fixes the handling of BMPString and
UniversalString, which are supersets of ASCII (Unicode Basic
Multilingual Plane and Unicode, respectively), but don't encode ASCII
characters as single octets. It also fixes UTF8String to, well,
properly recognize UTF-8.
This also lets us get rid of the special handling of SyntaxBMPString in
X.509sat (and, in fact, *requires* us to get rid of it, as, otherwise,
the string value appears twice).
Change-Id: I325c4e71a6110278eb23b86e0d986e6439cfc328
Reviewed-on: https://code.wireshark.org/review/994
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-04-07 22:39:55 +00:00
*/
encoding = ENC_ASCII | ENC_NA ;
break ;
case BER_UNI_TAG_VideotexString :
/*
2014-08-11 09:40:17 +00:00
* XXX - the G0 part of this starts out as T .61 , not ASCII .
*
* XXX - treat as ASCII for now .
Handle string types with somewhat appropriate encodings.
For various string types defined in X.680, use the appropriate encoding,
or ENC_ASCII|ENC_NA in some cases where we don't have an appropriate
encoding yet.
This most significantly fixes the handling of BMPString and
UniversalString, which are supersets of ASCII (Unicode Basic
Multilingual Plane and Unicode, respectively), but don't encode ASCII
characters as single octets. It also fixes UTF8String to, well,
properly recognize UTF-8.
This also lets us get rid of the special handling of SyntaxBMPString in
X.509sat (and, in fact, *requires* us to get rid of it, as, otherwise,
the string value appears twice).
Change-Id: I325c4e71a6110278eb23b86e0d986e6439cfc328
Reviewed-on: https://code.wireshark.org/review/994
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-04-07 22:39:55 +00:00
*/
encoding = ENC_ASCII | ENC_NA ;
break ;
case BER_UNI_TAG_GraphicString :
case BER_UNI_TAG_GeneralString :
/*
2014-08-11 09:40:17 +00:00
* One of the types defined in terms of character sets
* in the ISO International Register of Character Sets ,
* with the BER encoding being ISO 2022 - based .
*
* XXX - treat as ASCII for now .
Handle string types with somewhat appropriate encodings.
For various string types defined in X.680, use the appropriate encoding,
or ENC_ASCII|ENC_NA in some cases where we don't have an appropriate
encoding yet.
This most significantly fixes the handling of BMPString and
UniversalString, which are supersets of ASCII (Unicode Basic
Multilingual Plane and Unicode, respectively), but don't encode ASCII
characters as single octets. It also fixes UTF8String to, well,
properly recognize UTF-8.
This also lets us get rid of the special handling of SyntaxBMPString in
X.509sat (and, in fact, *requires* us to get rid of it, as, otherwise,
the string value appears twice).
Change-Id: I325c4e71a6110278eb23b86e0d986e6439cfc328
Reviewed-on: https://code.wireshark.org/review/994
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-04-07 22:39:55 +00:00
*/
encoding = ENC_ASCII | ENC_NA ;
break ;
case BER_UNI_TAG_UniversalString :
/*
* UCS - 4.
*/
encoding = ENC_UCS_4 | ENC_BIG_ENDIAN ;
break ;
case BER_UNI_TAG_CHARACTERSTRING :
/*
* XXX - what ' s the transfer syntax ?
* Treat as ASCII for now .
*/
encoding = ENC_ASCII | ENC_NA ;
break ;
case BER_UNI_TAG_BMPString :
/*
* UCS - 2 , not UTF - 16 ; as it says , BMP , as in Basic
* Multilingual Plane .
*/
encoding = ENC_UCS_2 | ENC_BIG_ENDIAN ;
break ;
default :
encoding = ENC_BIG_ENDIAN ;
break ;
}
it = ber_proto_tree_add_item ( actx - > pinfo , tree , hf_id , tvb , offset , length_remaining , encoding ) ;
2012-04-23 17:43:56 +00:00
actx - > created_item = it ;
2012-10-18 02:33:11 +00:00
ber_check_length ( length_remaining , min_len , max_len , actx , it , FALSE ) ;
2012-04-23 17:43:56 +00:00
} else {
2014-11-01 20:55:25 +00:00
proto_tree_add_item ( tree , hf_ber_unknown_octetstring , tvb , offset , len , ENC_NA ) ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( out_tvb ) {
2014-09-14 00:21:56 +00:00
* out_tvb = ber_tvb_new_subset_length ( tvb , offset , len ) ;
2012-04-23 17:43:56 +00:00
}
}
return end_offset ;
2004-02-20 10:04:10 +00:00
}
2009-12-18 15:18:31 +00:00
int
dissect_ber_octet_string ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , tvbuff_t * * out_tvb ) {
return dissect_ber_constrained_octet_string ( implicit_tag , actx , tree , tvb , offset , NO_BOUND , NO_BOUND , hf_id , out_tvb ) ;
}
2012-10-18 02:33:11 +00:00
int
dissect_ber_octet_string_wcb ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , ber_callback func )
2004-03-25 09:18:03 +00:00
{
2012-04-23 17:43:56 +00:00
tvbuff_t * out_tvb = NULL ;
2012-10-18 02:33:11 +00:00
offset = dissect_ber_octet_string ( implicit_tag , actx , tree , tvb , offset , hf_id , ( func ) ? & out_tvb : NULL ) ;
2014-10-31 09:48:47 +00:00
if ( func & & out_tvb & & ( tvb_reported_length ( out_tvb ) > 0 ) ) {
2012-04-23 17:43:56 +00:00
if ( hf_id > = 0 )
tree = proto_item_add_subtree ( actx - > created_item , ett_ber_octet_string ) ;
/* TODO Should hf_id2 be pased as last parameter???*/
func ( FALSE , out_tvb , 0 , actx , tree , - 1 ) ;
}
return offset ;
2004-03-25 09:18:03 +00:00
}
2005-04-27 14:17:14 +00:00
/* 8.8 Encoding of a null value */
2006-03-09 16:00:33 +00:00
int
2007-05-15 05:49:43 +00:00
dissect_ber_null ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id ) {
2012-10-18 02:33:11 +00:00
gint8 ber_class ;
gboolean pc ;
gint32 tag ;
guint32 len ;
int offset_old ;
2012-04-23 17:43:56 +00:00
proto_item * cause ;
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
2012-04-23 17:43:56 +00:00
offset_old = offset ;
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & ber_class , & pc , & tag ) ;
2012-10-18 02:33:11 +00:00
if ( pc | |
( ! implicit_tag & & ( ( ber_class ! = BER_CLASS_UNI ) | | ( tag ! = BER_UNI_TAG_NULL ) ) ) ) {
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset_old , offset - offset_old , " null_expected " ,
2013-09-30 15:21:09 +00:00
" NULL expected but class:%s(%d) %s tag:%d was unexpected " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class ,
pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_null ) ;
2012-04-23 17:43:56 +00:00
}
offset_old = offset ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
2012-10-18 02:33:11 +00:00
if ( len ) {
2013-09-30 15:21:09 +00:00
proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset_old , offset - offset_old , " illegal_length " ,
2013-09-30 15:21:09 +00:00
" NULL expect zero length but Length=%d " ,
2012-10-18 02:33:11 +00:00
len ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " unexpected_data " ,
2013-09-30 15:21:09 +00:00
" unexpected data in NULL type " ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_null_zero_length ) ;
2012-04-23 17:43:56 +00:00
offset + = len ;
}
}
if ( hf_id > = 0 )
proto_tree_add_item ( tree , hf_id , tvb , offset , 0 , ENC_BIG_ENDIAN ) ;
return offset ;
2005-04-27 14:17:14 +00:00
}
2004-02-20 10:04:10 +00:00
int
2007-05-15 05:49:43 +00:00
dissect_ber_integer64 ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , gint64 * value )
2004-02-20 10:04:10 +00:00
{
2012-10-18 02:33:11 +00:00
gint8 ber_class ;
2012-04-23 17:43:56 +00:00
gboolean pc ;
2012-10-18 02:33:11 +00:00
gint32 tag ;
guint32 len ;
gint64 val ;
guint32 i ;
2012-04-23 17:43:56 +00:00
gboolean used_too_many_bytes = FALSE ;
2013-06-20 23:37:16 +00:00
guint8 first ;
2004-11-14 05:10:44 +00:00
# ifdef DEBUG_BER
{
2007-05-02 20:37:25 +00:00
const char * name ;
2004-11-14 05:10:44 +00:00
header_field_info * hfinfo ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2004-11-14 05:10:44 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2004-11-14 05:10:44 +00:00
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 3 ) {
printf ( " INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x \n " , name , implicit_tag , offset , tvb_reported_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
printf ( " INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d \n " , name , implicit_tag ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2012-10-18 02:33:11 +00:00
if ( value ) {
* value = 0 ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
2012-04-23 17:43:56 +00:00
} else {
2014-10-31 09:48:47 +00:00
gint32 remaining = tvb_reported_length_remaining ( tvb , offset ) ;
2012-10-18 02:33:11 +00:00
len = remaining > 0 ? remaining : 0 ;
2012-04-23 17:43:56 +00:00
}
2013-06-20 23:37:16 +00:00
first = tvb_get_guint8 ( tvb , offset ) ;
2012-10-18 02:33:11 +00:00
/* we can't handle integers > 64 bits */
2013-06-20 23:37:16 +00:00
/* take into account the use case of a 64bits unsigned integer: you will have a 9th byte set to 0 */
if ( ( len > 9 ) | | ( ( len = = 9 ) & & ( first ! = 0 ) ) ) {
2012-04-23 17:43:56 +00:00
header_field_info * hfinfo ;
2012-10-18 02:33:11 +00:00
proto_item * pi = NULL ;
2012-04-23 17:43:56 +00:00
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
pi = proto_tree_add_text ( tree , tvb , offset , len , " %s : 0x " , hfinfo - > name ) ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( pi ) {
for ( i = 0 ; i < len ; i + + ) {
proto_item_append_text ( pi , " %02x " , tvb_get_guint8 ( tvb , offset ) ) ;
2012-04-23 17:43:56 +00:00
offset + + ;
}
} else {
offset + = len ;
}
return offset ;
}
val = 0 ;
2012-10-18 02:33:11 +00:00
if ( len > 0 ) {
2013-04-26 19:23:36 +00:00
/* extend sign bit for signed fields */
2013-04-30 23:19:47 +00:00
enum ftenum type = FT_INT32 ; /* Default to signed, is this correct? */
if ( hf_id > = 0 ) {
type = proto_registrar_get_ftype ( hf_id ) ;
}
2013-04-26 19:23:36 +00:00
if ( first & 0x80 & & IS_FT_INT ( type ) ) {
2012-10-18 02:33:11 +00:00
val = - 1 ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( ( len > 1 ) & & decode_warning_leading_zero_bits ) {
2012-04-23 17:43:56 +00:00
guint8 second = tvb_get_guint8 ( tvb , offset + 1 ) ;
2012-10-18 02:33:11 +00:00
if ( ( ( first = = 0x00 ) & & ( ( second & 0x80 ) = = 0 ) ) | |
( ( first = = 0xff ) & & ( ( second & 0x80 ) ! = 0 ) ) ) {
2012-04-23 17:43:56 +00:00
used_too_many_bytes = TRUE ;
}
}
2012-10-18 02:33:11 +00:00
for ( i = 0 ; i < len ; i + + ) {
val = ( val < < 8 ) | tvb_get_guint8 ( tvb , offset ) ;
2012-04-23 17:43:56 +00:00
offset + + ;
}
}
2012-10-18 02:33:11 +00:00
actx - > created_item = NULL ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2012-04-23 17:43:56 +00:00
/* */
2013-06-20 23:37:16 +00:00
if ( ( len < 1 ) | | ( len > 9 ) | | ( ( len = = 9 ) & & ( first ! = 0 ) ) ) {
2013-09-30 15:21:09 +00:00
proto_item * pi = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset - len , len , " invalid length " ,
2013-09-30 15:21:09 +00:00
" Can't handle integer length: %u " ,
2012-10-18 02:33:11 +00:00
len ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( actx - > pinfo , pi , & ei_ber_error_length ,
2012-10-18 02:33:11 +00:00
" BER Error: Illegal integer length: %u " , len ) ;
2012-04-23 17:43:56 +00:00
} else {
header_field_info * hfi ;
hfi = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
switch ( hfi - > type ) {
2012-04-23 17:43:56 +00:00
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
2012-10-18 02:33:11 +00:00
actx - > created_item = proto_tree_add_uint ( tree , hf_id , tvb , offset - len , len , ( guint32 ) val ) ;
2012-04-23 17:43:56 +00:00
break ;
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2012-10-18 02:33:11 +00:00
actx - > created_item = proto_tree_add_int ( tree , hf_id , tvb , offset - len , len , ( gint32 ) val ) ;
2012-04-23 17:43:56 +00:00
break ;
case FT_INT64 :
2012-10-18 02:33:11 +00:00
actx - > created_item = proto_tree_add_int64 ( tree , hf_id , tvb , offset - len , len , val ) ;
2012-04-23 17:43:56 +00:00
break ;
case FT_UINT64 :
2012-10-18 02:33:11 +00:00
actx - > created_item = proto_tree_add_uint64 ( tree , hf_id , tvb , offset - len , len , ( guint64 ) val ) ;
2012-04-23 17:43:56 +00:00
break ;
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
if ( used_too_many_bytes ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , actx - > created_item , & ei_ber_value_too_many_bytes ,
2012-10-18 02:33:11 +00:00
" Value is encoded with too many bytes(9 leading zero or one bits), hf_abbr: %s " ,
hfi - > abbrev ) ;
2012-04-23 17:43:56 +00:00
}
}
}
2012-10-18 02:33:11 +00:00
if ( value ) {
* value = val ;
2012-04-23 17:43:56 +00:00
}
return offset ;
2009-12-18 15:18:31 +00:00
}
int
dissect_ber_constrained_integer64 ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint64 min_len , gint64 max_len , gint hf_id , gint64 * value )
{
2012-04-23 17:43:56 +00:00
gint64 val ;
2009-12-18 15:18:31 +00:00
2012-10-18 02:33:11 +00:00
offset = dissect_ber_integer64 ( implicit_tag , actx , tree , tvb , offset , hf_id , & val ) ;
if ( value ) {
* value = val ;
2012-04-23 17:43:56 +00:00
}
2004-02-20 10:04:10 +00:00
2012-04-23 17:43:56 +00:00
ber_check_value64 ( val , min_len , max_len , actx , actx - > created_item ) ;
2009-12-18 15:18:31 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2004-02-20 10:04:10 +00:00
}
2006-02-28 09:39:53 +00:00
int
2007-05-15 05:49:43 +00:00
dissect_ber_integer ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , guint32 * value )
2006-02-28 09:39:53 +00:00
{
2012-04-23 17:43:56 +00:00
gint64 val ;
2006-02-28 09:39:53 +00:00
2012-10-18 02:33:11 +00:00
offset = dissect_ber_integer64 ( implicit_tag , actx , tree , tvb , offset , hf_id , & val ) ;
if ( value ) {
* value = ( guint32 ) val ;
2012-04-23 17:43:56 +00:00
}
2006-02-28 09:39:53 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2006-02-28 09:39:53 +00:00
}
2009-12-18 15:18:31 +00:00
int
dissect_ber_constrained_integer ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint32 min_len , gint32 max_len , gint hf_id , guint32 * value )
{
2012-04-23 17:43:56 +00:00
gint64 val ;
2009-12-18 15:18:31 +00:00
2012-10-18 02:33:11 +00:00
offset = dissect_ber_integer64 ( implicit_tag , actx , tree , tvb , offset , hf_id , & val ) ;
if ( value ) {
* value = ( guint32 ) val ;
2012-04-23 17:43:56 +00:00
}
2009-12-18 15:18:31 +00:00
2012-04-23 17:43:56 +00:00
ber_check_value ( ( guint32 ) val , min_len , max_len , actx , actx - > created_item ) ;
2009-12-18 15:18:31 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2009-12-18 15:18:31 +00:00
}
2004-02-20 10:04:10 +00:00
int
2008-01-04 16:21:07 +00:00
dissect_ber_boolean ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , gboolean * value )
2004-02-20 10:04:10 +00:00
{
2012-10-18 02:33:11 +00:00
gint8 ber_class ;
2012-04-23 17:43:56 +00:00
gboolean pc ;
2012-10-18 02:33:11 +00:00
gint32 tag ;
guint32 len ;
guint8 val ;
2012-04-23 17:43:56 +00:00
header_field_info * hfi ;
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
/*if (ber_class != BER_CLASS_UNI)*/
2012-04-23 17:43:56 +00:00
} else {
/* nothing to do here, yet */
}
2006-03-09 16:00:33 +00:00
2012-10-18 02:33:11 +00:00
val = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
2004-02-20 10:04:10 +00:00
2012-10-18 02:33:11 +00:00
actx - > created_item = NULL ;
2004-02-20 10:04:10 +00:00
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2012-04-23 17:43:56 +00:00
hfi = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
if ( hfi - > type = = FT_BOOLEAN )
actx - > created_item = proto_tree_add_boolean ( tree , hf_id , tvb , offset - 1 , 1 , val ) ;
2012-04-23 17:43:56 +00:00
else
2012-10-18 02:33:11 +00:00
actx - > created_item = proto_tree_add_uint ( tree , hf_id , tvb , offset - 1 , 1 , val ? 1 : 0 ) ;
2012-04-23 17:43:56 +00:00
}
2004-02-20 10:04:10 +00:00
2012-10-18 02:33:11 +00:00
if ( value ) {
* value = ( val ? TRUE : FALSE ) ;
2012-04-23 17:43:56 +00:00
}
2006-06-29 21:04:37 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2004-02-20 10:04:10 +00:00
}
2012-04-23 17:43:56 +00:00
/* 8.5 Encoding of a real value */
2014-11-28 15:53:04 +00:00
/* Somewhat tested */
2007-06-12 21:29:27 +00:00
int
2007-06-13 06:22:43 +00:00
dissect_ber_real ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id _U_ , double * value )
2007-06-12 21:29:27 +00:00
{
2012-10-18 02:33:11 +00:00
gint8 ber_class ;
2012-04-23 17:43:56 +00:00
gboolean pc ;
2012-10-18 02:33:11 +00:00
gint32 tag ;
2014-11-28 15:53:04 +00:00
guint32 val_length = 0 , len_remain , end_offset ;
2012-10-18 02:33:11 +00:00
double val = 0 ;
2014-11-28 15:53:04 +00:00
proto_item * cause ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & val_length , NULL ) ;
2014-11-28 15:53:04 +00:00
end_offset = offset + val_length ;
2012-04-23 17:43:56 +00:00
} else {
2014-11-28 15:53:04 +00:00
/* implicit tag so get from last tag/length */
get_last_ber_identifier ( & ber_class , & pc , & tag ) ;
get_last_ber_length ( & val_length , NULL ) ;
end_offset = offset + val_length ;
/* Check is buffer has (at least) the expected length */
len_remain = ( guint32 ) tvb_reported_length_remaining ( tvb , offset ) ;
if ( len_remain < val_length ) {
/* error - this item runs past the end of the item containing it */
cause = proto_tree_add_string_format_value (
tree , hf_ber_error , tvb , offset , val_length , " illegal_length " ,
" length:%u longer than tvb_reported_length_remaining:%d " ,
val_length ,
len_remain ) ;
expert_add_info ( actx - > pinfo , cause , & ei_ber_error_length ) ;
return end_offset ;
}
2012-04-23 17:43:56 +00:00
}
2014-11-28 15:53:04 +00:00
/* 8.5.1 The encoding of a real value shall be primitive. */
if ( pc ) {
/* Constructed (not primitive) */
cause = proto_tree_add_string_format_value (
tree , hf_ber_error , tvb , offset - 2 , 1 , " wrong_tag " ,
" REAL class must be encoded as primitive " ) ;
expert_add_info ( actx - > pinfo , cause , & ei_ber_error_length ) ;
2012-04-23 17:43:56 +00:00
}
val = asn1_get_real ( tvb_get_ptr ( tvb , offset , val_length ) , val_length ) ;
2014-11-28 15:53:04 +00:00
actx - > created_item = proto_tree_add_double ( tree , hf_id , tvb , end_offset - val_length , val_length , val ) ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
if ( value )
* value = val ;
2012-04-23 17:43:56 +00:00
return end_offset ;
2004-02-20 10:04:10 +00:00
2007-06-12 21:29:27 +00:00
}
2006-03-09 16:00:33 +00:00
/* this function dissects a BER sequence
2004-02-20 10:04:10 +00:00
*/
2012-10-18 02:33:11 +00:00
int
dissect_ber_sequence ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_sequence_t * seq , gint hf_id , gint ett_id ) {
gint8 classx ;
gboolean pcx , ind = 0 , ind_field , imp_tag = FALSE ;
gint32 tagx ;
guint32 lenx ;
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
2012-04-23 17:43:56 +00:00
proto_item * cause ;
2012-10-18 02:33:11 +00:00
int end_offset = 0 ;
int hoffset ;
tvbuff_t * next_tvb ;
2005-11-26 04:16:40 +00:00
2004-11-14 05:10:44 +00:00
# ifdef DEBUG_BER
{
2007-05-02 20:37:25 +00:00
const char * name ;
2004-11-14 05:10:44 +00:00
header_field_info * hfinfo ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2004-11-14 05:10:44 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2004-11-14 05:10:44 +00:00
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 3 ) {
printf ( " SEQUENCE dissect_ber_sequence(%s) entered offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_reported_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
printf ( " SEQUENCE dissect_ber_sequence(%s) entered \n " , name ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2012-04-23 17:43:56 +00:00
hoffset = offset ;
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
2012-04-23 17:43:56 +00:00
offset = get_ber_identifier ( tvb , offset , NULL , NULL , NULL ) ;
offset = get_ber_length ( tvb , offset , & lenx , NULL ) ;
} else {
/* was implicit tag so just use the length of the tvb */
2014-10-31 09:48:47 +00:00
lenx = tvb_reported_length_remaining ( tvb , offset ) ;
2012-10-18 02:33:11 +00:00
end_offset = offset + lenx ;
2012-04-23 17:43:56 +00:00
}
/* create subtree */
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
if ( parent_tree ) {
2012-04-23 17:43:56 +00:00
item = proto_tree_add_item ( parent_tree , hf_id , tvb , hoffset , lenx + offset - hoffset , ENC_BIG_ENDIAN ) ;
tree = proto_item_add_subtree ( item , ett_id ) ;
}
}
offset = hoffset ;
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
2012-04-23 17:43:56 +00:00
/* first we must read the sequence header */
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & classx , & pcx , & tagx ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & lenx , & ind ) ;
2012-10-18 02:33:11 +00:00
if ( ind ) {
2012-04-23 17:43:56 +00:00
/* Fixed the length is correctly returned from dissect ber_length
2014-10-31 09:48:47 +00:00
end_offset = tvb_reported_length ( tvb ) ; */
2012-04-23 17:43:56 +00:00
end_offset = offset + lenx - 2 ;
} else {
end_offset = offset + lenx ;
}
/* sanity check: we only handle Constructed Universal Sequences */
2012-10-18 02:33:11 +00:00
if ( ( classx ! = BER_CLASS_APP ) & & ( classx ! = BER_CLASS_PRI ) ) {
if ( ! pcx
| | ( ! implicit_tag & & ( ( classx ! = BER_CLASS_UNI ) | | ( tagx ! = BER_UNI_TAG_SEQUENCE ) ) ) ) {
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , lenx , " sequence_expected " ,
2013-09-30 15:21:09 +00:00
" Sequence expected but class:%s(%d) %s tag:%d was unexpected " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( classx , ber_class_codes , " Unknown " ) ,
classx ,
pcx ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tagx ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_sequence ) ;
2012-10-18 02:33:11 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
return end_offset ;
2012-04-23 17:43:56 +00:00
}
}
2013-09-20 14:20:06 +00:00
}
2014-08-11 09:40:17 +00:00
if ( offset = = end_offset ) {
2013-09-20 14:20:06 +00:00
proto_item_append_text ( item , " [0 length] " ) ;
2012-04-23 17:43:56 +00:00
}
/* loop over all entries until we reach the end of the sequence */
2012-10-18 02:33:11 +00:00
while ( offset < end_offset ) {
gint8 ber_class ;
2012-04-23 17:43:56 +00:00
gboolean pc ;
2012-10-18 02:33:11 +00:00
gint32 tag ;
guint32 len ;
int eoffset , count ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
/*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2012-04-23 17:43:56 +00:00
but ber dissector uses this to eat the tag length then pass into here . . . EOC still on there . . . */
2012-10-18 02:33:11 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
2012-04-23 17:43:56 +00:00
/* If the first bytes is 00 00 of a indefenert length field it's a zero length field*/
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & ber_class , & pc , & tag ) ;
dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , & ind ) ;
2012-10-18 02:33:11 +00:00
proto_item_append_text ( item , " 0 items " ) ;
2012-04-23 17:43:56 +00:00
return end_offset ;
/*
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
2014-11-01 20:55:25 +00:00
proto_tree_add_expert ( tree , pinfo , & ei_ber_error_seq_eoc , tvb , s_offset , offset + 2 , " ERROR WRONG SEQ EOC " ) ;
2012-04-23 17:43:56 +00:00
}
return end_offset ;
*/
}
2012-10-18 02:33:11 +00:00
/* } */
2012-04-23 17:43:56 +00:00
hoffset = offset ;
/* read header and len for next field */
offset = get_ber_identifier ( tvb , offset , & ber_class , & pc , & tag ) ;
offset = get_ber_length ( tvb , offset , & len , & ind_field ) ;
eoffset = offset + len ;
2006-07-07 20:11:06 +00:00
/* Make sure we move forward */
2012-04-23 17:43:56 +00:00
if ( eoffset < = hoffset )
THROW ( ReportedBoundsError ) ;
2005-08-18 08:37:31 +00:00
2012-10-18 02:33:11 +00:00
/*if (ind_field && (len == 2)) {
2012-04-23 17:43:56 +00:00
/ disgusting indefinite length zero length field , what are these people doing /
offset = eoffset ;
continue ;
}
*/
2006-06-09 21:09:57 +00:00
2005-08-18 08:37:31 +00:00
ber_sequence_try_again :
2012-04-23 17:43:56 +00:00
/* have we run out of known entries in the sequence ?*/
2012-10-18 02:33:11 +00:00
if ( ! seq - > func ) {
2012-04-23 17:43:56 +00:00
/* it was not, move to the next one and try again */
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , NULL , NULL ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " unknown_field " ,
2013-09-30 15:21:09 +00:00
" This field lies beyond the end of the known sequence definition. " ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_unknown_field_sequence ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
2012-10-18 02:33:11 +00:00
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
2012-04-23 17:43:56 +00:00
}
offset = eoffset ;
continue ;
}
/* Verify that this one is the one we want.
2012-10-18 02:33:11 +00:00
* Skip check completely if ber_class = = ANY
2012-04-23 17:43:56 +00:00
* of if NOCHKTAG is set
*/
2005-08-18 08:37:31 +00:00
/* XXX Bug in asn2eth,
* for scope [ 7 ] Scope OPTIONAL ,
2006-03-09 16:00:33 +00:00
* it generates
2005-08-18 08:37:31 +00:00
* { BER_CLASS_CON , 7 , BER_FLAGS_OPTIONAL | BER_FLAGS_NOTCHKTAG , dissect_scope } ,
* and there should not be a NOTCHKTAG here
*/
2012-10-18 02:33:11 +00:00
if ( ( ( seq - > ber_class = = BER_CLASS_CON ) | | ( seq - > ber_class = = BER_CLASS_APP ) | | ( seq - > ber_class = = BER_CLASS_PRI ) )
& & ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) ) ) {
if ( ( seq - > ber_class ! = BER_CLASS_ANY )
& & ( seq - > tag ! = - 1 )
& & ( ( seq - > ber_class ! = ber_class )
| | ( seq - > tag ! = tag ) ) ) {
2012-04-23 17:43:56 +00:00
/* it was not, move to the next one and try again */
2012-10-18 02:33:11 +00:00
if ( seq - > flags & BER_FLAGS_OPTIONAL ) {
2012-04-23 17:43:56 +00:00
/* well this one was optional so just skip to the next one and try again. */
seq + + ;
goto ber_sequence_try_again ;
}
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , NULL , NULL ) ;
2012-10-18 02:33:11 +00:00
if ( seq - > ber_class = = BER_CLASS_UNI ) {
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " wrong_field " ,
2013-09-30 15:21:09 +00:00
" Wrong field in SEQUENCE expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( seq - > ber_class , ber_class_codes , " Unknown " ) ,
seq - > ber_class ,
seq - > tag ,
val_to_str_ext_const ( seq - > tag , & ber_uni_tag_codes_ext , " Unknown " ) ,
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class ,
tag ) ;
} else {
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " wrong_field " ,
2013-09-30 15:21:09 +00:00
" Wrong field in SEQUENCE expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( seq - > ber_class , ber_class_codes , " Unknown " ) ,
seq - > ber_class ,
seq - > tag ,
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class ,
tag ) ;
2012-04-23 17:43:56 +00:00
}
2014-11-06 12:21:03 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_sequence_field_wrong ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
seq + + ;
2012-10-18 02:33:11 +00:00
offset = eoffset ;
2012-04-23 17:43:56 +00:00
continue ;
}
2012-10-18 02:33:11 +00:00
} else if ( ! ( seq - > flags & BER_FLAGS_NOTCHKTAG ) ) {
if ( ( seq - > ber_class ! = BER_CLASS_ANY )
& & ( seq - > tag ! = - 1 )
& & ( ( seq - > ber_class ! = ber_class )
| | ( seq - > tag ! = tag ) ) ) {
2012-04-23 17:43:56 +00:00
/* it was not, move to the next one and try again */
2012-10-18 02:33:11 +00:00
if ( seq - > flags & BER_FLAGS_OPTIONAL ) {
2012-04-23 17:43:56 +00:00
/* well this one was optional so just skip to the next one and try again. */
seq + + ;
goto ber_sequence_try_again ;
}
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , NULL , NULL ) ;
2012-10-18 02:33:11 +00:00
if ( seq - > ber_class = = BER_CLASS_UNI ) {
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " wrong_field " ,
2014-11-06 12:21:03 +00:00
" Wrong field in SEQUENCE expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( seq - > ber_class , ber_class_codes , " Unknown " ) ,
seq - > ber_class ,
seq - > tag ,
val_to_str_ext_const ( seq - > tag , & ber_uni_tag_codes_ext , " Unknown " ) ,
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class , tag ) ;
} else {
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " wrong_field " ,
2014-11-06 12:21:03 +00:00
" Wrong field in SEQUENCE expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( seq - > ber_class , ber_class_codes , " Unknown " ) ,
seq - > ber_class ,
seq - > tag ,
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class ,
tag ) ;
2012-04-23 17:43:56 +00:00
}
2014-11-06 12:21:03 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_sequence_field_wrong ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
seq + + ;
2012-10-18 02:33:11 +00:00
offset = eoffset ;
2012-04-23 17:43:56 +00:00
continue ;
}
}
2012-10-18 02:33:11 +00:00
if ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) ) {
2012-04-23 17:43:56 +00:00
/* dissect header and len for field */
2012-10-18 02:33:11 +00:00
if ( ind_field & & ( len = = 2 ) ) {
2012-04-23 17:43:56 +00:00
/* This is a Zero length field */
2014-09-14 00:21:56 +00:00
next_tvb = ber_tvb_new_subset_length ( tvb , offset , len ) ;
2012-04-23 17:43:56 +00:00
hoffset = eoffset ;
2012-10-18 02:33:11 +00:00
} else {
2012-04-23 17:43:56 +00:00
hoffset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
hoffset = dissect_ber_length ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL ) ;
2014-09-14 00:21:56 +00:00
next_tvb = ber_tvb_new_subset_length ( tvb , hoffset , eoffset - hoffset - ( 2 * ind_field ) ) ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
} else {
2014-09-14 00:21:56 +00:00
next_tvb = ber_tvb_new_subset_length ( tvb , hoffset , eoffset - hoffset ) ;
2012-04-23 17:43:56 +00:00
}
#if 0
/* call the dissector for this field */
2012-10-18 02:33:11 +00:00
if ( ( eoffset - hoffset ) > length_remaining ) {
/* If the field is indefinite (i.e. we don't know the
2012-04-23 17:43:56 +00:00
* length ) of if the tvb is short , then just
* give it all of the tvb and hope for the best .
*/
2012-10-18 02:33:11 +00:00
next_tvb = tvb_new_subset_remaining ( tvb , hoffset ) ;
2012-04-23 17:43:56 +00:00
} else {
}
# endif
2004-10-16 12:53:09 +00:00
2005-06-22 09:58:46 +00:00
# ifdef DEBUG_BER
{
2007-05-02 20:37:25 +00:00
const char * name ;
2005-06-22 09:58:46 +00:00
header_field_info * hfinfo ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2005-06-22 09:58:46 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2005-06-22 09:58:46 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2005-06-22 09:58:46 +00:00
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( next_tvb , 0 ) > 3 ) {
printf ( " SEQUENCE dissect_ber_sequence(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_reported_length_remaining ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 1 ) , tvb_get_guint8 ( next_tvb , 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
printf ( " SEQUENCE dissect_ber_sequence(%s) calling subdissector \n " , name ) ;
2005-06-22 09:58:46 +00:00
}
}
# endif
2012-04-23 17:43:56 +00:00
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
2012-10-18 02:33:11 +00:00
imp_tag = FALSE ;
if ( seq - > flags & BER_FLAGS_IMPLTAG ) {
2012-04-23 17:43:56 +00:00
imp_tag = TRUE ;
}
2007-05-22 16:17:54 +00:00
2012-10-18 02:33:11 +00:00
count = seq - > func ( imp_tag , next_tvb , 0 , actx , tree , * seq - > p_id ) ;
2006-03-09 16:00:33 +00:00
2005-08-18 08:37:31 +00:00
# ifdef DEBUG_BER
{
2007-05-02 20:37:25 +00:00
const char * name ;
2005-08-18 08:37:31 +00:00
header_field_info * hfinfo ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2005-08-18 08:37:31 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2005-08-18 08:37:31 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2005-08-18 08:37:31 +00:00
}
2012-10-18 02:33:11 +00:00
printf ( " SEQUENCE dissect_ber_sequence(%s) subdissector ate %d bytes \n " , name , count ) ;
2005-08-18 08:37:31 +00:00
}
# endif
2012-04-23 17:43:56 +00:00
/* if it was optional and no bytes were eaten and it was */
2012-10-18 02:33:11 +00:00
/* supposed to (len <> 0), just try again. */
if ( ( len ! = 0 ) & & ( count = = 0 ) & & ( seq - > flags & BER_FLAGS_OPTIONAL ) ) {
2012-04-23 17:43:56 +00:00
seq + + ;
goto ber_sequence_try_again ;
/* move the offset to the beginning of the next sequenced item */
}
offset = eoffset ;
2012-10-18 02:33:11 +00:00
if ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) ) {
2012-04-23 17:43:56 +00:00
/* if we stripped the tag and length we should also strip the EOC is ind_len
2013-02-26 01:06:19 +00:00
* Unless it ' s a zero length field ( len = 2 )
2012-04-23 17:43:56 +00:00
*/
2012-10-18 02:33:11 +00:00
if ( ( ind_field = = 1 ) & & ( len > 2 ) )
2012-04-23 17:43:56 +00:00
{
/* skip over EOC */
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
2014-11-06 15:57:09 +00:00
proto_tree_add_item ( tree , hf_ber_seq_field_eoc , tvb , offset - 2 , 2 , ENC_NA ) ;
2012-04-23 17:43:56 +00:00
}
}
}
seq + + ;
}
2014-09-16 13:43:06 +00:00
/* if we didn't end up at exactly offset, then we ate too many bytes */
2012-10-18 02:33:11 +00:00
if ( offset ! = end_offset ) {
2012-04-23 17:43:56 +00:00
tvb_ensure_bytes_exist ( tvb , offset - 2 , 2 ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset - 2 , 2 , " illegal_length " ,
2013-09-30 15:21:09 +00:00
" Sequence ate %d too many bytes " ,
2012-10-18 02:33:11 +00:00
offset - end_offset ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( actx - > pinfo , cause , & ei_ber_error_length ,
2012-10-18 02:33:11 +00:00
" BER Error: too many bytes in Sequence " ) ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( ind ) {
2012-04-23 17:43:56 +00:00
/* need to eat this EOC
2014-10-31 09:48:47 +00:00
end_offset = tvb_reported_length ( tvb ) ; */
2012-04-23 17:43:56 +00:00
end_offset + = 2 ;
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
2014-11-01 20:55:25 +00:00
proto_tree_add_item ( tree , hf_ber_seq_eoc , tvb , end_offset - 2 , 2 , ENC_NA ) ;
2012-04-23 17:43:56 +00:00
}
}
return end_offset ;
2005-08-18 08:37:31 +00:00
}
2014-04-18 19:46:34 +00:00
/* This function dissects a BER set
*/
2012-10-18 02:33:11 +00:00
int
2014-04-18 19:46:34 +00:00
dissect_ber_set ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_sequence_t * set , gint hf_id , gint ett_id ) {
2012-10-18 02:33:11 +00:00
gint8 classx ;
2014-04-18 19:46:34 +00:00
gboolean pcx , ind = 0 , ind_field , imp_tag = FALSE ;
2012-10-18 02:33:11 +00:00
gint32 tagx ;
guint32 lenx ;
2014-04-18 19:46:34 +00:00
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
2012-04-23 17:43:56 +00:00
proto_item * cause ;
2014-04-18 19:46:34 +00:00
int end_offset , s_offset ;
2012-10-18 02:33:11 +00:00
int hoffset ;
tvbuff_t * next_tvb ;
2014-04-18 19:46:34 +00:00
guint32 mandatory_fields = 0 ;
guint8 set_idx ;
gboolean first_pass ;
const ber_sequence_t * cset = NULL ;
# define MAX_SET_ELEMENTS 32
s_offset = offset ;
2007-05-22 16:17:54 +00:00
2005-06-22 09:58:46 +00:00
# ifdef DEBUG_BER
2014-04-18 19:46:34 +00:00
{
2007-05-02 20:37:25 +00:00
const char * name ;
2005-06-22 09:58:46 +00:00
header_field_info * hfinfo ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2005-06-22 09:58:46 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2005-06-22 09:58:46 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2005-06-22 09:58:46 +00:00
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 3 ) {
printf ( " SET dissect_ber_set(%s) entered offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_reported_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
2014-04-18 19:46:34 +00:00
printf ( " SET dissect_ber_set(%s) entered \n " , name ) ;
2005-06-22 09:58:46 +00:00
}
}
# endif
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
2014-04-18 19:46:34 +00:00
hoffset = offset ;
2012-04-23 17:43:56 +00:00
/* first we must read the sequence header */
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & classx , & pcx , & tagx ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & lenx , & ind ) ;
2012-10-18 02:33:11 +00:00
if ( ind ) {
2012-04-23 17:43:56 +00:00
/* Fixed the length is correctly returned from dissect ber_length
2014-10-31 09:48:47 +00:00
end_offset = tvb_reported_length ( tvb ) ; */
2012-04-23 17:43:56 +00:00
end_offset = offset + lenx - 2 ;
} else {
end_offset = offset + lenx ;
}
2014-04-18 19:46:34 +00:00
/* sanity check: we only handle Constructed Universal Sets */
2012-10-18 02:33:11 +00:00
if ( ( classx ! = BER_CLASS_APP ) & & ( classx ! = BER_CLASS_PRI ) ) {
if ( ! pcx
2014-04-18 19:46:34 +00:00
| | ( ! implicit_tag & & ( ( classx ! = BER_CLASS_UNI )
| | ( tagx ! = BER_UNI_TAG_SET ) ) ) ) {
2012-10-18 02:33:11 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2014-04-18 19:46:34 +00:00
tree , hf_ber_error , tvb , offset , lenx , " set_expected " ,
" SET expected but class:%s(%d) %s tag:%d was found " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( classx , ber_class_codes , " Unknown " ) ,
classx ,
pcx ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tagx ) ;
2014-04-18 19:46:34 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_set ) ;
2012-10-18 02:33:11 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
return end_offset ;
2012-04-23 17:43:56 +00:00
}
}
2014-04-18 19:46:34 +00:00
} else {
/* was implicit tag so just use the length of the tvb */
2014-10-31 09:48:47 +00:00
lenx = tvb_reported_length_remaining ( tvb , offset ) ;
2014-04-18 19:46:34 +00:00
end_offset = offset + lenx ;
}
/* create subtree */
if ( hf_id > = 0 ) {
if ( parent_tree ) {
item = proto_tree_add_item ( parent_tree , hf_id , tvb , offset , lenx , ENC_BIG_ENDIAN ) ;
tree = proto_item_add_subtree ( item , ett_id ) ;
}
2012-04-23 17:43:56 +00:00
}
2014-04-18 19:46:34 +00:00
/* record the mandatory elements of the set so we can check we found everything at the end
we can only record 32 elements for now . . . */
for ( set_idx = 0 ; ( cset = & set [ set_idx ] ) - > func & & ( set_idx < MAX_SET_ELEMENTS ) ; set_idx + + ) {
if ( ! ( cset - > flags & BER_FLAGS_OPTIONAL ) )
mandatory_fields | = 1 < < set_idx ;
}
/* loop over all entries until we reach the end of the set */
2012-10-18 02:33:11 +00:00
while ( offset < end_offset ) {
gint8 ber_class ;
2012-04-23 17:43:56 +00:00
gboolean pc ;
2012-10-18 02:33:11 +00:00
gint32 tag ;
guint32 len ;
int eoffset , count ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
/*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2014-04-18 19:46:34 +00:00
but ber dissector uses this to eat the tag length then pass into here . . . EOC still on there . . . */
2012-10-18 02:33:11 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
if ( show_internal_ber_fields ) {
2014-11-01 20:55:25 +00:00
proto_tree_add_item ( tree , hf_ber_seq_eoc , tvb , s_offset , offset + 2 , ENC_NA ) ;
2012-04-23 17:43:56 +00:00
}
return end_offset ;
}
2012-10-18 02:33:11 +00:00
/* } */
2012-04-23 17:43:56 +00:00
hoffset = offset ;
/* read header and len for next field */
2014-04-18 19:46:34 +00:00
offset = get_ber_identifier ( tvb , offset , & ber_class , & pc , & tag ) ;
offset = get_ber_length ( tvb , offset , & len , & ind_field ) ;
2012-04-23 17:43:56 +00:00
eoffset = offset + len ;
2007-05-22 16:17:54 +00:00
2014-04-18 19:46:34 +00:00
/* Look through the Set to see if this class/id exists and
* hasn ' t been seen before
2012-10-18 02:33:11 +00:00
* Skip check completely if ber_class = = ANY
2012-04-23 17:43:56 +00:00
* of if NOCHKTAG is set
*/
2014-04-18 19:46:34 +00:00
for ( first_pass = TRUE , cset = set , set_idx = 0 ; cset - > func | | first_pass ; cset + + , set_idx + + ) {
2012-04-23 17:43:56 +00:00
2014-04-18 19:46:34 +00:00
/* we reset for a second pass when we will look for choices */
if ( ! cset - > func ) {
first_pass = FALSE ;
2012-04-23 17:43:56 +00:00
2014-04-18 19:46:34 +00:00
cset = set ; /* reset to the beginning */
set_idx = 0 ;
}
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
if ( ( first_pass & & ( ( cset - > ber_class = = ber_class ) & & ( cset - > tag = = tag ) ) ) | |
( ! first_pass & & ( ( cset - > ber_class = = BER_CLASS_ANY ) & & ( cset - > tag = = - 1 ) ) ) ) /* choices */
2012-04-23 17:43:56 +00:00
{
if ( ! ( cset - > flags & BER_FLAGS_NOOWNTAG ) ) {
/* dissect header and len for field */
hoffset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
hoffset = dissect_ber_length ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL ) ;
2014-09-14 00:21:56 +00:00
next_tvb = ber_tvb_new_subset_length ( tvb , hoffset , eoffset - hoffset - ( 2 * ind_field ) ) ;
2012-10-18 02:33:11 +00:00
} else {
2014-09-14 00:21:56 +00:00
next_tvb = ber_tvb_new_subset_length ( tvb , hoffset , eoffset - hoffset ) ;
2012-04-23 17:43:56 +00:00
}
#if 0
/* call the dissector for this field */
if ( ( eoffset - hoffset ) > length_remaining ) {
2012-10-18 02:33:11 +00:00
/* If the field is indefinite (i.e. we don't know the
2012-04-23 17:43:56 +00:00
* length ) of if the tvb is short , then just
* give it all of the tvb and hope for the best .
*/
next_tvb = tvb_new_subset_remaining ( tvb , hoffset ) ;
} else {
}
# endif
2007-05-22 16:17:54 +00:00
# ifdef DEBUG_BER
{
const char * name ;
header_field_info * hfinfo ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2007-05-22 16:17:54 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2007-05-22 16:17:54 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2007-05-22 16:17:54 +00:00
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( next_tvb , 0 ) > 3 ) {
printf ( " SET dissect_ber_set(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_reported_length_remaining ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 1 ) , tvb_get_guint8 ( next_tvb , 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
printf ( " SET dissect_ber_set(%s) calling subdissector \n " , name ) ;
2007-05-22 16:17:54 +00:00
}
}
# endif
2012-04-23 17:43:56 +00:00
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
imp_tag = FALSE ;
if ( ( cset - > flags & BER_FLAGS_IMPLTAG ) )
imp_tag = TRUE ;
2012-10-18 02:33:11 +00:00
count = cset - > func ( imp_tag , next_tvb , 0 , actx , tree , * cset - > p_id ) ;
2012-04-23 17:43:56 +00:00
/* if we consumed some bytes,
or we knew the length was zero ( during the first pass only ) */
2012-10-18 02:33:11 +00:00
if ( count | | ( first_pass & & ( ( len = = 0 ) | | ( ( ind_field = = 1 ) & & ( len = = 2 ) ) ) ) ) {
2012-04-23 17:43:56 +00:00
/* we found it! */
2012-10-18 02:33:11 +00:00
if ( set_idx < MAX_SET_ELEMENTS )
2012-04-23 17:43:56 +00:00
mandatory_fields & = ~ ( 1 < < set_idx ) ;
offset = eoffset ;
2012-10-18 02:33:11 +00:00
if ( ! ( cset - > flags & BER_FLAGS_NOOWNTAG ) ) {
2012-04-23 17:43:56 +00:00
/* if we stripped the tag and length we should also strip the EOC is ind_len */
2012-10-18 02:33:11 +00:00
if ( ind_field = = 1 ) {
2012-04-23 17:43:56 +00:00
/* skip over EOC */
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
2014-11-01 20:55:25 +00:00
proto_tree_add_item ( tree , hf_ber_set_field_eoc , tvb , offset , count , ENC_NA ) ;
2012-04-23 17:43:56 +00:00
}
}
}
break ;
}
}
}
2012-10-18 02:33:11 +00:00
if ( ! cset - > func ) {
2012-04-23 17:43:56 +00:00
/* we didn't find a match */
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " unknown_field " ,
2013-09-30 15:21:09 +00:00
" Unknown field in SET class:%s(%d) tag:%d " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class ,
tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_unknown_field_set ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
offset = eoffset ;
}
}
2012-10-18 02:33:11 +00:00
if ( mandatory_fields ) {
2012-04-23 17:43:56 +00:00
/* OK - we didn't find some of the elements we expected */
2012-10-18 02:33:11 +00:00
for ( set_idx = 0 ; ( cset = & set [ set_idx ] ) - > func & & ( set_idx < MAX_SET_ELEMENTS ) ; set_idx + + ) {
if ( mandatory_fields & ( 1 < < set_idx ) ) {
2012-04-23 17:43:56 +00:00
/* here is something we should have seen - but didn't! */
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , lenx , " missing_field " ,
2013-09-30 15:21:09 +00:00
" Missing field in SET class:%s(%d) tag:%d expected " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( cset - > ber_class , ber_class_codes , " Unknown " ) ,
cset - > ber_class ,
cset - > tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_missing_field_set ) ;
2012-04-23 17:43:56 +00:00
}
}
}
2014-09-16 13:43:06 +00:00
/* if we didn't end up at exactly offset, then we ate too many bytes */
2012-04-23 17:43:56 +00:00
if ( offset ! = end_offset ) {
tvb_ensure_bytes_exist ( tvb , offset - 2 , 2 ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset - 2 , 2 , " illegal_length " ,
2013-09-30 15:21:09 +00:00
" SET ate %d too many bytes " ,
2012-10-18 02:33:11 +00:00
offset - end_offset ) ;
2013-10-13 19:56:52 +00:00
expert_add_info_format ( actx - > pinfo , cause , & ei_ber_error_length ,
2012-10-18 02:33:11 +00:00
" BER Error: too many bytes in SET " ) ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( ind ) {
2012-04-23 17:43:56 +00:00
/* need to eat this EOC
2014-10-31 09:48:47 +00:00
end_offset = tvb_reported_length ( tvb ) ; */
2012-04-23 17:43:56 +00:00
end_offset + = 2 ;
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
2014-11-01 20:55:25 +00:00
proto_tree_add_item ( tree , hf_ber_set_eoc , tvb , end_offset - 2 , 2 , ENC_NA ) ;
2012-04-23 17:43:56 +00:00
}
}
return end_offset ;
2007-05-22 16:17:54 +00:00
}
2014-04-18 19:46:34 +00:00
# ifdef DEBUG_BER
# define DEBUG_BER_CHOICE
# endif
2012-10-18 02:33:11 +00:00
int
2014-04-18 19:46:34 +00:00
dissect_ber_choice ( asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_choice_t * choice , gint hf_id , gint ett_id , gint * branch_taken )
2004-02-20 10:04:10 +00:00
{
2012-10-18 02:33:11 +00:00
gint8 ber_class ;
2014-04-18 19:46:34 +00:00
gboolean pc , ind , imp_tag = FALSE ;
2012-10-18 02:33:11 +00:00
gint32 tag ;
guint32 len ;
2014-04-18 19:46:34 +00:00
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
2012-10-18 02:33:11 +00:00
int end_offset , start_offset , count ;
int hoffset = offset ;
2014-09-14 00:21:56 +00:00
gint length ;
2012-10-18 02:33:11 +00:00
tvbuff_t * next_tvb ;
gboolean first_pass ;
2014-04-18 19:46:34 +00:00
header_field_info * hfinfo ;
const ber_choice_t * ch ;
2005-09-05 16:31:24 +00:00
2007-05-02 20:37:25 +00:00
# ifdef DEBUG_BER_CHOICE
2004-11-14 05:10:44 +00:00
{
2007-05-02 20:37:25 +00:00
const char * name ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2004-11-14 05:10:44 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2004-11-14 05:10:44 +00:00
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 3 ) {
printf ( " CHOICE dissect_ber_choice(%s) entered offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_reported_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
2014-10-31 09:48:47 +00:00
printf ( " CHOICE dissect_ber_choice(%s) entered len:%d \n " , name , tvb_reported_length_remaining ( tvb , offset ) ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2014-04-18 19:46:34 +00:00
2012-10-18 02:33:11 +00:00
start_offset = offset ;
2014-04-18 19:46:34 +00:00
if ( branch_taken ) {
* branch_taken = - 1 ;
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) = = 0 ) {
2013-09-30 15:21:09 +00:00
item = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
parent_tree , hf_ber_error , tvb , offset , 0 , " empty_choice " ,
2013-09-30 15:21:09 +00:00
" Empty choice was found " ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , item , & ei_ber_empty_choice ) ;
2012-04-23 17:43:56 +00:00
return offset ;
}
2004-10-28 11:35:43 +00:00
2012-04-23 17:43:56 +00:00
/* read header and len for choice field */
2012-10-18 02:33:11 +00:00
offset = get_ber_identifier ( tvb , offset , & ber_class , & pc , & tag ) ;
offset = get_ber_length ( tvb , offset , & len , & ind ) ;
2012-04-23 17:43:56 +00:00
end_offset = offset + len ;
/* Some sanity checks.
* The hf field passed to us MUST be an integer type
*/
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
switch ( hfinfo - > type ) {
2012-04-23 17:43:56 +00:00
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
break ;
default :
2014-11-01 20:55:25 +00:00
proto_tree_add_expert_format (
tree , actx - > pinfo , & ei_hf_field_not_integer_type , tvb , offset , len ,
2014-12-24 15:44:03 +00:00
" dissect_ber_choice(): frame:%u offset:%d Was passed an HF field that was not integer type : %s " ,
actx - > pinfo - > fd - > num , offset , hfinfo - > abbrev ) ;
2012-04-23 17:43:56 +00:00
return end_offset ;
2010-07-07 15:52:09 +00:00
}
2012-04-23 17:43:56 +00:00
}
/* loop over all entries until we find the right choice or
run out of entries */
ch = choice ;
first_pass = TRUE ;
2012-10-18 02:33:11 +00:00
while ( ch - > func | | first_pass ) {
if ( branch_taken ) {
2012-04-23 17:43:56 +00:00
( * branch_taken ) + + ;
}
/* we reset for a second pass when we will look for choices */
2012-10-18 02:33:11 +00:00
if ( ! ch - > func ) {
2012-04-23 17:43:56 +00:00
first_pass = FALSE ;
ch = choice ; /* reset to the beginning */
2012-10-18 02:33:11 +00:00
if ( branch_taken ) {
* branch_taken = - 1 ;
2012-04-23 17:43:56 +00:00
}
2014-05-06 14:19:02 +00:00
continue ;
2012-04-23 17:43:56 +00:00
}
2005-08-28 19:50:36 +00:00
2007-05-02 20:37:25 +00:00
# ifdef DEBUG_BER_CHOICE
2012-10-18 02:33:11 +00:00
printf ( " CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d:(expected)%d flags:%d \n " , ch , ber_class , ch - > ber_class , tag , ch - > tag , ch - > flags ) ;
2004-12-12 22:19:00 +00:00
# endif
2012-10-18 02:33:11 +00:00
if ( ( first_pass
& & ( ( ( ch - > ber_class = = ber_class ) & & ( ch - > tag = = tag ) )
| | ( ( ch - > ber_class = = ber_class ) & & ( ch - > tag = = - 1 ) & & ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) ) )
| | ( ! first_pass & & ( ( ( ch - > ber_class = = BER_CLASS_ANY ) & & ( ch - > tag = = - 1 ) ) ) ) /* we failed on the first pass so now try any choices */
2014-04-18 19:46:34 +00:00
) {
2012-10-18 02:33:11 +00:00
if ( ! ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) {
2012-04-23 17:43:56 +00:00
/* dissect header and len for field */
hoffset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , start_offset , NULL , NULL , NULL ) ;
hoffset = dissect_ber_length ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL ) ;
2012-10-18 02:33:11 +00:00
start_offset = hoffset ;
if ( ind ) {
length = len - 2 ;
} else {
2012-04-23 17:43:56 +00:00
length = len ;
2012-10-18 02:33:11 +00:00
}
} else {
2012-04-23 17:43:56 +00:00
length = end_offset - hoffset ;
2012-10-18 02:33:11 +00:00
}
2012-04-23 17:43:56 +00:00
/* create subtree */
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
if ( parent_tree ) {
2012-04-23 17:43:56 +00:00
item = proto_tree_add_uint ( parent_tree , hf_id , tvb , hoffset , end_offset - hoffset , ch - > value ) ;
tree = proto_item_add_subtree ( item , ett_id ) ;
}
}
2006-03-09 16:00:33 +00:00
# ifdef REMOVED
2012-04-23 17:43:56 +00:00
/* This is bogus and makes the OID_1.0.9506.1.1.cap file
* in Steven J Schaeffer ' s email of 2005 - 09 - 12 fail to dissect
* properly . Maybe we should get rid of ' first_pass '
* completely .
* It was added as a qad workaround for some problem CMIP
* traces anyway .
* God , this file is a mess and it is my fault . / ronnie
*/
2012-10-18 02:33:11 +00:00
if ( first_pass )
2014-09-14 00:21:56 +00:00
next_tvb = ber_tvb_new_subset_length ( tvb , hoffset , length ) ;
2012-04-23 17:43:56 +00:00
else
2012-10-18 02:33:11 +00:00
next_tvb = tvb ; /* we didn't make selection on this class/tag so pass it on */
2006-02-02 08:34:59 +00:00
# endif
2014-09-14 00:21:56 +00:00
next_tvb = ber_tvb_new_subset_length ( tvb , hoffset , length ) ;
2006-02-02 08:34:59 +00:00
2004-11-14 05:10:44 +00:00
2007-05-02 20:37:25 +00:00
# ifdef DEBUG_BER_CHOICE
2004-11-14 05:10:44 +00:00
{
2007-05-02 20:37:25 +00:00
const char * name ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2004-11-14 05:10:44 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2004-11-14 05:10:44 +00:00
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( next_tvb , 0 ) > 3 ) {
printf ( " CHOICE dissect_ber_choice(%s) calling subdissector start_offset:%d offset:%d len:%d %02x:%02x:%02x \n " , name , start_offset , offset , tvb_reported_length_remaining ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 1 ) , tvb_get_guint8 ( next_tvb , 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
2014-10-31 09:48:47 +00:00
printf ( " CHOICE dissect_ber_choice(%s) calling subdissector len:%d \n " , name , tvb_reported_length ( next_tvb ) ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2012-04-23 17:43:56 +00:00
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
2014-04-18 19:46:34 +00:00
imp_tag = FALSE ;
if ( ( ch - > flags & BER_FLAGS_IMPLTAG ) )
imp_tag = TRUE ;
count = ch - > func ( imp_tag , next_tvb , 0 , actx , tree , * ch - > p_id ) ;
2007-05-02 20:37:25 +00:00
# ifdef DEBUG_BER_CHOICE
2004-11-14 05:10:44 +00:00
{
2007-05-02 20:37:25 +00:00
const char * name ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2004-11-14 05:10:44 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2004-11-14 05:10:44 +00:00
}
2014-04-18 19:46:34 +00:00
printf ( " CHOICE dissect_ber_choice(%s) subdissector ate %d bytes \n " , name , count ) ;
2004-11-14 05:10:44 +00:00
}
# endif
2012-10-18 02:33:11 +00:00
if ( ( count = = 0 ) & & ( ( ( ch - > ber_class = = ber_class ) & & ( ch - > tag = = - 1 ) & & ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) | | ! first_pass ) ) {
2012-04-23 17:43:56 +00:00
/* wrong one, break and try again */
ch + + ;
2007-05-02 20:37:25 +00:00
# ifdef DEBUG_BER_CHOICE
{
const char * name ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2007-05-02 20:37:25 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2007-05-02 20:37:25 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2007-05-02 20:37:25 +00:00
}
2014-04-18 19:46:34 +00:00
printf ( " CHOICE dissect_ber_choice(%s) trying again \n " , name ) ;
2007-05-02 20:37:25 +00:00
}
# endif
2014-05-06 14:19:02 +00:00
continue ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( ! ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) {
if ( ind ) {
2014-04-18 19:46:34 +00:00
/* we are traversing a indfinite length choice where we did not pass the tag length */
/* we need to eat the EOC */
2012-10-18 02:33:11 +00:00
if ( show_internal_ber_fields ) {
2014-11-10 16:43:53 +00:00
proto_tree_add_item ( tree , hf_ber_choice_eoc , tvb , end_offset - 2 , 2 , ENC_NA ) ;
2012-04-23 17:43:56 +00:00
}
}
}
return end_offset ;
}
ch + + ;
}
2012-10-18 02:33:11 +00:00
if ( branch_taken ) {
2012-04-23 17:43:56 +00:00
/* none of the branches were taken so set the param
back to - 1 */
2014-04-18 19:46:34 +00:00
* branch_taken = - 1 ;
2012-04-23 17:43:56 +00:00
}
2005-09-05 16:31:24 +00:00
2004-10-28 11:35:43 +00:00
# ifdef REMOVED
2012-04-23 17:43:56 +00:00
/*XXX here we should have another flag to the CHOICE to distinguish
* between the case when we know it is a mandatory or if the CHOICE is optional = = no arm matched */
2014-09-16 13:43:06 +00:00
/* oops no more entries and we still haven't found
2012-04-23 17:43:56 +00:00
* our guy : - (
*/
2014-04-18 19:46:34 +00:00
item = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " missing_choice_field " ,
2013-09-30 15:21:09 +00:00
" This choice field was not found. " ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , item , & ei_ber_choice_not_found ) ;
2012-04-23 17:43:56 +00:00
return end_offset ;
2004-10-28 11:35:43 +00:00
# endif
2012-04-23 17:43:56 +00:00
return start_offset ;
2004-02-20 10:04:10 +00:00
}
2004-03-25 09:18:03 +00:00
#if 0
2004-02-20 10:04:10 +00:00
/* this function dissects a BER GeneralString
*/
int
2007-05-15 05:49:43 +00:00
dissect_ber_GeneralString ( asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , char * name_string , int name_len )
2004-02-20 10:04:10 +00:00
{
2012-10-18 02:33:11 +00:00
gint8 ber_class ;
gboolean pc ;
gint32 tag ;
guint32 len ;
int end_offset ;
int hoffset ;
char str_arr [ 256 ] ;
guint32 max_len ;
char * str ;
2012-04-23 17:43:56 +00:00
proto_item * cause ;
2012-10-18 02:33:11 +00:00
str = str_arr ;
max_len = 255 ;
if ( name_string ) {
str = name_string ;
max_len = name_len ;
2012-04-23 17:43:56 +00:00
}
hoffset = offset ;
/* first we must read the GeneralString header */
2012-10-18 02:33:11 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
end_offset = offset + len ;
2012-04-23 17:43:56 +00:00
/* sanity check: we only handle Universal GeneralString*/
2012-10-18 02:33:11 +00:00
if ( ( ber_class ! = BER_CLASS_UNI )
| | ( tag ! = BER_UNI_TAG_GENSTR ) ) {
2012-04-23 17:43:56 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " generalstring_expected " ,
2013-09-30 15:21:09 +00:00
" GeneralString expected but class:%s(%d) %s tag:%d was unexpected " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class , pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_general_string ,
2012-10-18 02:33:11 +00:00
" BER Error: GeneralString expected " ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
return end_offset ;
}
2012-10-18 02:33:11 +00:00
if ( len > = ( max_len - 1 ) ) {
len = max_len - 1 ;
2012-04-23 17:43:56 +00:00
}
tvb_memcpy ( tvb , str , offset , len ) ;
str [ len ] = 0 ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2012-04-23 17:43:56 +00:00
proto_tree_add_string ( tree , hf_id , tvb , offset , len , str ) ;
}
return end_offset ;
2004-02-20 10:04:10 +00:00
}
2004-03-25 09:18:03 +00:00
# endif
2009-12-18 15:18:31 +00:00
2012-10-18 02:33:11 +00:00
int
dissect_ber_constrained_restricted_string ( gboolean implicit_tag , gint32 type , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint32 min_len , gint32 max_len , gint hf_id , tvbuff_t * * out_tvb ) {
gint8 ber_class ;
gboolean pc ;
gint32 tag ;
guint32 len ;
int eoffset ;
int hoffset = offset ;
2012-04-23 17:43:56 +00:00
proto_item * cause ;
2004-03-25 09:18:03 +00:00
2004-11-14 05:10:44 +00:00
# ifdef DEBUG_BER
{
2007-05-02 20:37:25 +00:00
const char * name ;
2004-11-14 05:10:44 +00:00
header_field_info * hfinfo ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2004-11-14 05:10:44 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2004-11-14 05:10:44 +00:00
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 3 ) {
printf ( " RESTRICTED STRING dissect_ber_octet string(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x \n " , name , implicit_tag , offset , tvb_reported_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
printf ( " RESTRICTED STRING dissect_ber_octet_string(%s) entered \n " , name ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2004-03-25 09:18:03 +00:00
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
offset = get_ber_identifier ( tvb , offset , & ber_class , & pc , & tag ) ;
offset = get_ber_length ( tvb , offset , & len , NULL ) ;
2012-04-23 17:43:56 +00:00
eoffset = offset + len ;
/* sanity check */
2012-10-18 02:33:11 +00:00
if ( ( ber_class ! = BER_CLASS_UNI )
| | ( tag ! = type ) ) {
2012-04-23 17:43:56 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " string_expected " ,
2013-09-30 15:21:09 +00:00
" String with tag=%d expected but class:%s(%d) %s tag:%d was unexpected " ,
2012-10-18 02:33:11 +00:00
type ,
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class , pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_string ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
return eoffset ;
}
}
/* 8.21.3 */
return dissect_ber_constrained_octet_string ( implicit_tag , actx , tree , tvb , hoffset , min_len , max_len , hf_id , out_tvb ) ;
2009-12-18 15:18:31 +00:00
}
2010-07-07 15:52:09 +00:00
int dissect_ber_restricted_string ( gboolean implicit_tag , gint32 type , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , tvbuff_t * * out_tvb )
2009-12-18 15:18:31 +00:00
{
2012-04-23 17:43:56 +00:00
return dissect_ber_constrained_restricted_string ( implicit_tag , type , actx , tree , tvb , offset , NO_BOUND , NO_BOUND , hf_id , out_tvb ) ;
2004-03-25 09:18:03 +00:00
}
2004-02-20 10:04:10 +00:00
int
2007-05-15 05:49:43 +00:00
dissect_ber_GeneralString ( asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , char * name_string , guint name_len )
2004-02-20 10:04:10 +00:00
{
2012-04-23 17:43:56 +00:00
tvbuff_t * out_tvb = NULL ;
2012-10-18 02:33:11 +00:00
gint tvb_len ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
offset = dissect_ber_restricted_string ( FALSE , BER_UNI_TAG_GeneralString , actx , tree , tvb , offset , hf_id , ( name_string ) ? & out_tvb : NULL ) ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
if ( name_string ) {
2012-04-23 17:43:56 +00:00
/*
* XXX - do we want to just get what ' s left in the tvbuff
* if the full length isn ' t available in the tvbuff , or
* do we want to throw an exception ?
*/
2012-10-18 02:33:11 +00:00
if ( out_tvb ) {
2014-10-31 09:48:47 +00:00
tvb_len = tvb_reported_length ( out_tvb ) ;
2012-10-18 02:33:11 +00:00
if ( ( guint ) tvb_len > = name_len ) {
2012-04-23 17:43:56 +00:00
tvb_memcpy ( out_tvb , ( guint8 * ) name_string , 0 , name_len - 1 ) ;
name_string [ name_len - 1 ] = ' \0 ' ;
} else {
tvb_memcpy ( out_tvb , ( guint8 * ) name_string , 0 , tvb_len ) ;
name_string [ tvb_len ] = ' \0 ' ;
}
}
}
return offset ;
2004-03-25 09:18:03 +00:00
}
2013-10-06 20:59:05 +00:00
/* 8.19 Encoding of a relative or absolute object identifier value.
2013-10-06 02:31:10 +00:00
*/
2013-10-06 20:59:05 +00:00
static int
dissect_ber_any_oid ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , tvbuff_t * * value_tvb , gboolean is_absolute )
2013-10-06 02:31:10 +00:00
{
gint8 ber_class ;
gboolean pc ;
gint32 tag ;
guint32 len ;
int eoffset ;
int hoffset ;
const char * str ;
proto_item * cause ;
const gchar * name ;
header_field_info * hfi ;
# ifdef DEBUG_BER
{
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 3 ) {
printf ( " OBJECT IDENTIFIER dissect_ber_any_oid(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x \n " , name , implicit_tag , offset , tvb_reported_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2013-10-06 02:31:10 +00:00
} else {
2013-10-06 20:59:05 +00:00
printf ( " OBJECT IDENTIFIER dissect_ber_any_oid(%s) entered \n " , name ) ;
2013-10-06 02:31:10 +00:00
}
}
# endif
if ( ! implicit_tag ) {
hoffset = offset ;
/* sanity check */
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
eoffset = offset + len ;
if ( ( ber_class ! = BER_CLASS_UNI )
2013-10-13 19:56:52 +00:00
| | ( is_absolute & & tag ! = BER_UNI_TAG_OID )
2013-10-06 20:59:05 +00:00
| | ( ! is_absolute & & tag ! = BER_UNI_TAG_RELATIVE_OID ) ) {
2013-10-06 02:31:10 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2013-10-06 20:59:05 +00:00
cause = proto_tree_add_string_format_value (
2013-10-06 02:31:10 +00:00
tree , hf_ber_error , tvb , offset , len , " oid_expected " ,
2013-10-06 20:59:05 +00:00
" Object Identifier expected but class:%s(%d) %s tag:%d was unexpected " ,
2013-10-06 02:31:10 +00:00
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class ,
pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tag ) ;
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_object_identifier ) ;
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
return eoffset ;
}
} else {
2014-10-31 09:48:47 +00:00
len = tvb_reported_length_remaining ( tvb , offset ) ;
2013-10-06 02:31:10 +00:00
eoffset = offset + len ;
}
actx - > created_item = NULL ;
hfi = proto_registrar_get_nth ( hf_id ) ;
2013-10-06 20:59:05 +00:00
if ( ( is_absolute & & hfi - > type = = FT_OID ) | | ( ! is_absolute & & hfi - > type = = FT_REL_OID ) ) {
2013-10-06 02:31:10 +00:00
actx - > created_item = proto_tree_add_item ( tree , hf_id , tvb , offset , len , ENC_BIG_ENDIAN ) ;
} else if ( IS_FT_STRING ( hfi - > type ) ) {
2015-01-17 19:11:29 +00:00
str = oid_encoded2string ( wmem_packet_scope ( ) , tvb_get_ptr ( tvb , offset , len ) , len ) ;
2013-10-06 02:31:10 +00:00
actx - > created_item = proto_tree_add_string ( tree , hf_id , tvb , offset , len , str ) ;
if ( actx - > created_item ) {
/* see if we know the name of this oid */
2015-01-17 19:11:29 +00:00
name = oid_resolved_from_encoded ( wmem_packet_scope ( ) , tvb_get_ptr ( tvb , offset , len ) , len ) ;
2013-10-06 02:31:10 +00:00
if ( name ) {
proto_item_append_text ( actx - > created_item , " (%s) " , name ) ;
}
}
} else {
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
if ( value_tvb )
2014-09-14 00:21:56 +00:00
* value_tvb = ber_tvb_new_subset_length ( tvb , offset , len ) ;
2013-10-06 02:31:10 +00:00
return eoffset ;
}
2013-10-06 20:59:05 +00:00
static int
dissect_ber_any_oid_str ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , const char * * value_stringx , gboolean is_absolute )
2013-10-06 02:31:10 +00:00
{
tvbuff_t * value_tvb = NULL ;
guint length ;
2013-10-06 20:59:05 +00:00
offset = dissect_ber_any_oid ( implicit_tag , actx , tree , tvb , offset , hf_id , ( value_stringx ) ? & value_tvb : NULL , is_absolute ) ;
2013-10-06 02:31:10 +00:00
if ( value_stringx ) {
2014-10-31 09:48:47 +00:00
if ( value_tvb & & ( length = tvb_reported_length ( value_tvb ) ) ) {
2015-01-17 19:11:29 +00:00
* value_stringx = oid_encoded2string ( wmem_packet_scope ( ) , tvb_get_ptr ( value_tvb , 0 , length ) , length ) ;
2013-10-06 02:31:10 +00:00
} else {
* value_stringx = " " ;
}
}
return offset ;
}
2013-10-06 20:59:05 +00:00
/* 8.19 Encoding of a relative object identifier value.
2005-10-16 00:36:43 +00:00
*/
2012-10-18 02:33:11 +00:00
int
2013-10-06 20:59:05 +00:00
dissect_ber_relative_oid ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , tvbuff_t * * value_tvb )
2005-11-14 10:02:31 +00:00
{
2013-10-06 20:59:05 +00:00
return dissect_ber_any_oid ( implicit_tag , actx , tree , tvb , offset , hf_id , value_tvb , FALSE ) ;
}
2005-12-05 17:24:19 +00:00
2013-10-06 20:59:05 +00:00
int
dissect_ber_relative_oid_str ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , const char * * value_stringx )
2004-11-14 09:45:04 +00:00
{
2013-10-06 20:59:05 +00:00
return dissect_ber_any_oid_str ( implicit_tag , actx , tree , tvb , offset , hf_id , value_stringx , FALSE ) ;
2004-11-14 09:45:04 +00:00
}
2012-04-23 17:43:56 +00:00
2013-10-06 20:59:05 +00:00
/* 8.19 Encoding of an object identifier value.
*/
int
dissect_ber_object_identifier ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , tvbuff_t * * value_tvb )
{
return dissect_ber_any_oid ( implicit_tag , actx , tree , tvb , offset , hf_id , value_tvb , TRUE ) ;
2004-03-25 09:18:03 +00:00
}
2012-10-18 02:33:11 +00:00
int
dissect_ber_object_identifier_str ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , const char * * value_stringx )
2005-11-14 10:02:31 +00:00
{
2013-10-06 20:59:05 +00:00
return dissect_ber_any_oid_str ( implicit_tag , actx , tree , tvb , offset , hf_id , value_stringx , TRUE ) ;
2005-11-14 10:02:31 +00:00
}
2007-05-02 20:37:25 +00:00
# ifdef DEBUG_BER
# define DEBUG_BER_SQ_OF
# endif
2005-11-14 10:02:31 +00:00
2012-10-18 02:33:11 +00:00
static int
dissect_ber_sq_of ( gboolean implicit_tag , gint32 type , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , gint32 min_len , gint32 max_len , const ber_sequence_t * seq , gint hf_id , gint ett_id ) {
gint8 classx ;
gboolean pcx , ind = FALSE , ind_field ;
gint32 tagx ;
guint32 lenx ;
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
proto_item * causex ;
int cnt , hoffsetx , end_offset ;
2014-09-14 00:21:56 +00:00
gboolean have_cnt ;
2012-04-23 17:43:56 +00:00
header_field_info * hfi ;
2012-10-18 02:33:11 +00:00
tvbuff_t * next_tvb ;
2004-02-20 10:04:10 +00:00
2007-05-02 20:37:25 +00:00
# ifdef DEBUG_BER_SQ_OF
2004-11-14 05:10:44 +00:00
{
2007-05-02 20:37:25 +00:00
const char * name ;
2004-11-14 05:10:44 +00:00
header_field_info * hfinfo ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
name = hfinfo - > name ;
2004-11-14 05:10:44 +00:00
} else {
2012-10-18 02:33:11 +00:00
name = " unnamed " ;
2004-11-14 05:10:44 +00:00
}
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 3 ) {
printf ( " SQ OF dissect_ber_sq_of(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x \n " , name , implicit_tag , offset , tvb_reported_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2012-10-18 02:33:11 +00:00
} else {
printf ( " SQ OF dissect_ber_sq_of(%s) entered \n " , name ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2004-10-24 03:51:27 +00:00
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
2012-04-23 17:43:56 +00:00
hoffsetx = offset ;
/* first we must read the sequence header */
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & classx , & pcx , & tagx ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & lenx , & ind ) ;
2012-10-18 02:33:11 +00:00
if ( ind ) {
/* if the length is indefinite we don't really know (yet) where the
2012-04-23 17:43:56 +00:00
* object ends so assume it spans the rest of the tvb for now .
*/
end_offset = offset + lenx ;
} else {
end_offset = offset + lenx ;
}
/* sanity check: we only handle Constructed Universal Sequences */
2012-10-18 02:33:11 +00:00
if ( ( classx ! = BER_CLASS_APP ) & & ( classx ! = BER_CLASS_PRI ) ) {
if ( ! pcx
| | ( ! implicit_tag & & ( ( classx ! = BER_CLASS_UNI )
| | ( tagx ! = type ) ) ) ) {
tvb_ensure_bytes_exist ( tvb , hoffsetx , 2 ) ;
2013-09-30 15:21:09 +00:00
causex = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , lenx ,
( type = = BER_UNI_TAG_SEQUENCE ) ? " set_of_expected " : " sequence_of_expected " ,
2013-09-30 15:21:09 +00:00
" %s Of expected but class:%s(%d) %s tag:%d was unexpected " ,
2012-10-18 02:33:11 +00:00
( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " ,
val_to_str_const ( classx , ber_class_codes , " Unknown " ) ,
classx , pcx ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tagx ) ;
2013-07-02 21:16:10 +00:00
if ( type = = BER_UNI_TAG_SEQUENCE ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , causex , & ei_ber_expected_set ,
" BER Error: Set Of expected " ) ;
} else {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , causex , & ei_ber_expected_sequence ,
" BER Error: Sequence Of expected " ) ;
}
2012-10-18 02:33:11 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( causex , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffsetx , unknown_tree ) ;
}
return end_offset ;
2012-04-23 17:43:56 +00:00
}
}
} else {
2013-02-26 04:42:26 +00:00
/* the tvb length should be correct now nope we could be coming from an implicit choice or sequence, thus we
2012-04-23 17:43:56 +00:00
read the items we match and return the length */
2014-10-31 09:48:47 +00:00
lenx = tvb_reported_length_remaining ( tvb , offset ) ;
2012-04-23 17:43:56 +00:00
end_offset = offset + lenx ;
}
/* count number of items */
cnt = 0 ;
2014-09-14 00:21:56 +00:00
have_cnt = FALSE ;
2012-04-23 17:43:56 +00:00
hoffsetx = offset ;
/* only count the number of items IFF we have the full blob,
* else this will just generate a [ short frame ] before we even start
* dissecting a single item .
*/
/* XXX Do we really need to count them at all ? ronnie */
2014-10-31 09:48:47 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) = = tvb_reported_length_remaining ( tvb , offset ) ) {
2014-09-14 00:21:56 +00:00
have_cnt = TRUE ;
2012-10-18 02:33:11 +00:00
while ( offset < end_offset ) {
2012-04-23 17:43:56 +00:00
guint32 len ;
2012-10-18 02:33:11 +00:00
gint s_offset ;
2012-04-23 17:43:56 +00:00
s_offset = offset ;
2012-10-18 02:33:11 +00:00
/*if (ind) { this sequence of was of indefinite length, if this is implicit indefinite impossible maybe
2012-04-23 17:43:56 +00:00
but ber dissector uses this to eat the tag length then pass into here . . . EOC still on there . . . */
2012-10-18 02:33:11 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
2012-04-23 17:43:56 +00:00
break ;
}
2012-10-18 02:33:11 +00:00
/* } */
2012-04-23 17:43:56 +00:00
/* read header and len for next field */
offset = get_ber_identifier ( tvb , offset , NULL , NULL , NULL ) ;
offset = get_ber_length ( tvb , offset , & len , & ind ) ;
/* best place to get real length of implicit sequence of or set of is here... */
2014-09-16 13:43:06 +00:00
/* adjust end_offset if we find somthing that doesn't match */
2012-04-23 17:43:56 +00:00
offset + = len ;
cnt + + ;
2014-09-14 00:21:56 +00:00
if ( offset < = s_offset ) {
/* Underflow - give up; this can happen with a very large
* length .
*/
have_cnt = FALSE ;
cnt = 0 ;
break ;
}
2012-04-23 17:43:56 +00:00
}
}
offset = hoffsetx ;
/* create subtree */
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2012-04-23 17:43:56 +00:00
hfi = proto_registrar_get_nth ( hf_id ) ;
2012-10-18 02:33:11 +00:00
if ( parent_tree ) {
if ( hfi - > type = = FT_NONE ) {
2012-04-23 17:43:56 +00:00
item = proto_tree_add_item ( parent_tree , hf_id , tvb , offset , lenx , ENC_BIG_ENDIAN ) ;
proto_item_append_text ( item , " : " ) ;
} else {
2014-09-14 00:21:56 +00:00
if ( have_cnt ) {
item = proto_tree_add_uint ( parent_tree , hf_id , tvb , offset , lenx , cnt ) ;
proto_item_append_text ( item , ( cnt = = 1 ) ? " item " : " items " ) ;
} else
item = proto_tree_add_uint_format_value ( parent_tree , hf_id , tvb , offset , lenx , cnt , " unknown number of items " ) ;
2012-04-23 17:43:56 +00:00
}
tree = proto_item_add_subtree ( item , ett_id ) ;
ber_check_items ( cnt , min_len , max_len , actx , item ) ;
}
}
/* loop over all entries until we reach the end of the sequence */
2012-10-18 02:33:11 +00:00
while ( offset < end_offset ) {
gint8 ber_class ;
gboolean pc ;
gint32 tag ;
guint32 len ;
int eoffset ;
int hoffset ;
2012-04-23 17:43:56 +00:00
proto_item * cause ;
2012-10-18 02:33:11 +00:00
gboolean imp_tag ;
2012-04-23 17:43:56 +00:00
hoffset = offset ;
2012-10-18 02:33:11 +00:00
/*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2012-04-23 17:43:56 +00:00
but ber dissector uses this to eat the tag length then pass into here . . . EOC still on there . . . */
2012-10-18 02:33:11 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
if ( show_internal_ber_fields ) {
2014-11-01 20:55:25 +00:00
proto_tree_add_item ( tree , hf_ber_seq_of_eoc , tvb , hoffset , end_offset - hoffset , ENC_NA ) ;
2012-04-23 17:43:56 +00:00
}
return offset + 2 ;
}
/*}*/
/* read header and len for next field */
2012-10-18 02:33:11 +00:00
offset = get_ber_identifier ( tvb , offset , & ber_class , & pc , & tag ) ;
offset = get_ber_length ( tvb , offset , & len , & ind_field ) ;
2012-04-23 17:43:56 +00:00
eoffset = offset + len ;
2007-05-22 16:17:54 +00:00
/* Make sure we move forward */
2012-04-23 17:43:56 +00:00
if ( eoffset < = hoffset )
THROW ( ReportedBoundsError ) ;
2012-10-18 02:33:11 +00:00
if ( ( ber_class = = BER_CLASS_UNI ) & & ( tag = = BER_UNI_TAG_EOC ) ) {
2012-04-23 17:43:56 +00:00
/* This is a zero length sequence of*/
hoffset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
dissect_ber_length ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL ) ;
return eoffset ;
}
/* verify that this one is the one we want */
2012-10-18 02:33:11 +00:00
/* ahup if we are implicit then we return to the upper layer how much we have used */
if ( seq - > ber_class ! = BER_CLASS_ANY ) {
if ( ( seq - > ber_class ! = ber_class )
| | ( seq - > tag ! = tag ) ) {
if ( ! ( seq - > flags & BER_FLAGS_NOTCHKTAG ) ) {
2014-11-06 12:21:03 +00:00
if ( seq - > ber_class = = BER_CLASS_UNI ) {
cause = proto_tree_add_string_format_value (
tree , hf_ber_error , tvb , offset , len , " wrong_field " ,
" Wrong field in SQ OF expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d " ,
val_to_str_const ( seq - > ber_class , ber_class_codes , " Unknown " ) ,
seq - > ber_class ,
seq - > tag ,
val_to_str_ext_const ( seq - > tag , & ber_uni_tag_codes_ext , " Unknown " ) ,
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class , tag ) ;
} else {
cause = proto_tree_add_string_format_value (
tree , hf_ber_error , tvb , offset , len , " wrong_field " ,
" Wrong field in SQ OF expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d " ,
val_to_str_const ( seq - > ber_class , ber_class_codes , " Unknown " ) ,
seq - > ber_class ,
seq - > tag ,
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class ,
tag ) ;
}
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , cause , & ei_ber_sequence_field_wrong ,
2014-11-06 12:21:03 +00:00
" BER Error: Wrong field in SEQUENCE OF " ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
offset = eoffset ;
continue ;
/* wrong.... */
}
}
}
2012-10-18 02:33:11 +00:00
if ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) & & ! ( seq - > flags & BER_FLAGS_IMPLTAG ) ) {
2012-04-23 17:43:56 +00:00
/* dissect header and len for field */
hoffset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
hoffset = dissect_ber_length ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL ) ;
}
2012-10-18 02:33:11 +00:00
if ( ( seq - > flags = = BER_FLAGS_IMPLTAG ) & & ( seq - > ber_class = = BER_CLASS_CON ) ) {
2012-04-23 17:43:56 +00:00
/* Constructed sequence of with a tag */
/* dissect header and len for field */
hoffset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
hoffset = dissect_ber_length ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL ) ;
/* Function has IMPLICIT TAG */
}
2014-09-14 00:21:56 +00:00
next_tvb = ber_tvb_new_subset_length ( tvb , hoffset , eoffset - hoffset ) ;
2012-04-23 17:43:56 +00:00
imp_tag = FALSE ;
2012-10-18 02:33:11 +00:00
if ( seq - > flags = = BER_FLAGS_IMPLTAG )
2012-04-23 17:43:56 +00:00
imp_tag = TRUE ;
/* call the dissector for this field */
seq - > func ( imp_tag , next_tvb , 0 , actx , tree , * seq - > p_id ) ;
/* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
2014-09-16 13:43:06 +00:00
doesn ' t match the next item , thus this implicit sequence is over , return the number of bytes
2012-04-23 17:43:56 +00:00
we have eaten to allow the possible upper sequence continue . . . */
cnt + + ; /* rubbish*/
offset = eoffset ;
}
2014-09-16 13:43:06 +00:00
/* if we didn't end up at exactly offset, then we ate too many bytes */
2012-10-18 02:33:11 +00:00
if ( offset ! = end_offset ) {
2012-04-23 17:43:56 +00:00
tvb_ensure_bytes_exist ( tvb , offset - 2 , 2 ) ;
2013-09-30 15:21:09 +00:00
causex = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset - 2 , 2 , " illegal_length " ,
2013-09-30 15:21:09 +00:00
" %s Of ate %d too many bytes " ,
2012-10-18 02:33:11 +00:00
( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " ,
offset - end_offset ) ;
2013-10-13 19:56:52 +00:00
expert_add_info_format ( actx - > pinfo , causex , & ei_ber_error_length ,
2012-10-18 02:33:11 +00:00
" BER Error:too many byte in %s " ,
( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " ) ;
2012-04-23 17:43:56 +00:00
}
return end_offset ;
2007-05-22 16:17:54 +00:00
}
2012-10-18 02:33:11 +00:00
int
dissect_ber_constrained_sequence_of ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , gint32 min_len , gint32 max_len , const ber_sequence_t * seq , gint hf_id , gint ett_id ) {
2012-04-23 17:43:56 +00:00
return dissect_ber_sq_of ( implicit_tag , BER_UNI_TAG_SEQUENCE , actx , parent_tree , tvb , offset , min_len , max_len , seq , hf_id , ett_id ) ;
2009-12-18 15:18:31 +00:00
}
2012-10-18 02:33:11 +00:00
int
dissect_ber_sequence_of ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_sequence_t * seq , gint hf_id , gint ett_id ) {
2012-04-23 17:43:56 +00:00
return dissect_ber_sq_of ( implicit_tag , BER_UNI_TAG_SEQUENCE , actx , parent_tree , tvb , offset , NO_BOUND , NO_BOUND , seq , hf_id , ett_id ) ;
2009-12-18 15:18:31 +00:00
}
2012-10-18 02:33:11 +00:00
int
dissect_ber_constrained_set_of ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , gint32 min_len , gint32 max_len , const ber_sequence_t * seq , gint hf_id , gint ett_id ) {
2012-04-23 17:43:56 +00:00
return dissect_ber_sq_of ( implicit_tag , BER_UNI_TAG_SET , actx , parent_tree , tvb , offset , min_len , max_len , seq , hf_id , ett_id ) ;
2004-03-25 09:18:03 +00:00
}
2012-10-18 02:33:11 +00:00
int
dissect_ber_set_of ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_sequence_t * seq , gint hf_id , gint ett_id ) {
2012-04-23 17:43:56 +00:00
return dissect_ber_sq_of ( implicit_tag , BER_UNI_TAG_SET , actx , parent_tree , tvb , offset , NO_BOUND , NO_BOUND , seq , hf_id , ett_id ) ;
2004-03-25 09:18:03 +00:00
}
2004-02-20 10:04:10 +00:00
2006-03-09 16:00:33 +00:00
int
2007-05-15 05:49:43 +00:00
dissect_ber_GeneralizedTime ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id )
2004-02-20 10:04:10 +00:00
{
2012-10-18 02:33:11 +00:00
char str [ 35 ] ;
int tmp_int ;
2012-04-23 17:43:56 +00:00
const guint8 * tmpstr ;
2012-10-18 02:33:11 +00:00
char * strptr ;
char first_delim [ 2 ] ;
int first_digits ;
char second_delim [ 2 ] ;
int second_digits ;
int ret ;
gint8 ber_class ;
gboolean pc ;
gint32 tag ;
guint32 len ;
int end_offset ;
int hoffset ;
proto_item * cause ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
2012-04-23 17:43:56 +00:00
hoffset = offset ;
2012-10-18 02:33:11 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
end_offset = offset + len ;
2012-04-23 17:43:56 +00:00
/* sanity check. we only handle universal/generalized time */
2012-10-18 02:33:11 +00:00
if ( ( ber_class ! = BER_CLASS_UNI )
| | ( tag ! = BER_UNI_TAG_GeneralizedTime ) ) {
2012-04-23 17:43:56 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " generalized_time_expected " ,
2013-09-30 15:21:09 +00:00
" GeneralizedTime expected but class:%s(%d) %s tag:%d was unexpected " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class ,
pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_generalized_time ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
return end_offset ;
}
} else {
2014-10-31 09:48:47 +00:00
len = tvb_reported_length_remaining ( tvb , offset ) ;
2012-10-18 02:33:11 +00:00
end_offset = offset + len ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( ( len < 14 ) | | ( len > 23 ) ) {
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " illegal_length " ,
2013-09-30 15:21:09 +00:00
" GeneralizedTime invalid length: %u " ,
2012-10-18 02:33:11 +00:00
len ) ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( actx - > pinfo , cause , & ei_ber_error_length ,
2012-10-18 02:33:11 +00:00
" BER Error: GeneralizedTime invalid length " ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , offset , unknown_tree ) ;
}
return end_offset ;
}
2014-06-17 15:30:58 +00:00
tmpstr = tvb_get_string_enc ( wmem_packet_scope ( ) , tvb , offset , len , ENC_ASCII ) ;
2012-04-23 17:43:56 +00:00
strptr = str ;
/* those fields are allways present */
strptr + = g_snprintf ( str , 20 , " %.4s-%.2s-%.2s %.2s:%.2s:%.2s " ,
tmpstr , tmpstr + 4 , tmpstr + 6 , tmpstr + 8 ,
tmpstr + 10 , tmpstr + 12 ) ;
2012-10-18 02:33:11 +00:00
first_delim [ 0 ] = 0 ;
second_delim [ 0 ] = 0 ;
2012-04-23 17:43:56 +00:00
ret = sscanf ( tmpstr , " %14d%1[.,+-Z]%4d%1[+-Z]%4d " , & tmp_int , first_delim , & first_digits , second_delim , & second_digits ) ;
/* tmp_int does not contain valid value bacause of overflow but we use it just for format checking */
if ( ret < 1 ) {
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " invalid_generalized_time " ,
2013-09-30 15:21:09 +00:00
" GeneralizedTime invalid format: %s " ,
2012-10-18 02:33:11 +00:00
tmpstr ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_invalid_format_generalized_time ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , offset , unknown_tree ) ;
}
return end_offset ;
}
switch ( first_delim [ 0 ] ) {
case ' . ' :
case ' , ' :
strptr + = g_snprintf ( strptr , 5 , " %c%.3d " , first_delim [ 0 ] , first_digits ) ;
switch ( second_delim [ 0 ] ) {
case ' + ' :
case ' - ' :
g_snprintf ( strptr , 12 , " (UTC%c%.4d) " , second_delim [ 0 ] , second_digits ) ;
break ;
case ' Z ' :
g_snprintf ( strptr , 7 , " (UTC) " ) ;
break ;
case 0 :
break ;
default :
/* handle the malformed field */
break ;
}
break ;
case ' + ' :
case ' - ' :
g_snprintf ( strptr , 12 , " (UTC%c%.4d) " , first_delim [ 0 ] , first_digits ) ;
break ;
case ' Z ' :
g_snprintf ( strptr , 7 , " (UTC) " ) ;
break ;
case 0 :
break ;
default :
/* handle the malformed field */
break ;
}
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2012-04-23 17:43:56 +00:00
proto_tree_add_string ( tree , hf_id , tvb , offset , len , str ) ;
}
offset + = len ;
return offset ;
2004-02-20 10:04:10 +00:00
}
2008-08-01 16:44:06 +00:00
int
dissect_ber_UTCTime ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id )
{
2012-10-18 02:33:11 +00:00
char outstr [ 33 ] ;
char * outstrptr = outstr ;
2012-04-23 17:43:56 +00:00
const guint8 * instr ;
2012-10-18 02:33:11 +00:00
gint8 ber_class ;
gboolean pc ;
gint32 tag ;
guint32 len , i , n ;
int hoffset ;
proto_item * cause ;
proto_tree * error_tree ;
2012-12-21 05:34:38 +00:00
const gchar * error_str = NULL ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
2012-04-23 17:43:56 +00:00
hoffset = offset ;
2012-10-18 02:33:11 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
2012-04-23 17:43:56 +00:00
/* sanity check: we only handle UTCTime */
2012-10-18 02:33:11 +00:00
if ( ( ber_class ! = BER_CLASS_UNI ) | | ( tag ! = BER_UNI_TAG_UTCTime ) ) {
2012-04-23 17:43:56 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
tree , hf_ber_error , tvb , offset , len , " utctime_expected " ,
2013-09-30 15:21:09 +00:00
" UTCTime expected but class:%s(%d) %s tag:%d was unexpected " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class ,
pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_utc_time ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
return offset + len ;
}
} else {
2014-10-31 09:48:47 +00:00
len = tvb_reported_length_remaining ( tvb , offset ) ;
2012-04-23 17:43:56 +00:00
}
2012-10-18 02:33:11 +00:00
if ( ( len < 10 ) | | ( len > 19 ) ) {
2013-09-12 22:03:31 +00:00
error_str = wmem_strdup_printf ( wmem_packet_scope ( ) , " BER Error: UTCTime invalid length: %u " , len ) ;
2014-06-17 15:30:58 +00:00
instr = tvb_get_string_enc ( wmem_packet_scope ( ) , tvb , offset , len > 19 ? 19 : len , ENC_ASCII ) ;
2012-04-23 17:43:56 +00:00
goto malformed ;
}
2014-06-17 15:30:58 +00:00
instr = tvb_get_string_enc ( wmem_packet_scope ( ) , tvb , offset , len , ENC_ASCII ) ;
2012-04-23 17:43:56 +00:00
/* YYMMDDhhmm */
2012-10-18 02:33:11 +00:00
for ( i = 0 ; i < 10 ; i + + ) {
if ( ( instr [ i ] < ' 0 ' ) | | ( instr [ i ] > ' 9 ' ) ) {
2012-08-14 17:58:41 +00:00
error_str = " BER Error: malformed UTCTime encoding, "
" first 10 octets have to contain YYMMDDhhmm in digits " ;
2012-04-23 17:43:56 +00:00
goto malformed ;
}
}
g_snprintf ( outstrptr , 15 , " %.2s-%.2s-%.2s %.2s:%.2s " , instr , instr + 2 , instr + 4 , instr + 6 , instr + 8 ) ;
outstrptr + = 14 ;
/* (ss)? */
2012-10-18 02:33:11 +00:00
if ( len > = 12 ) {
if ( ( instr [ i ] > = ' 0 ' ) & & ( instr [ i ] < = ' 9 ' ) ) {
2012-04-23 17:43:56 +00:00
i + + ;
2012-10-18 02:33:11 +00:00
if ( ( instr [ i ] > = ' 0 ' ) & & ( instr [ i ] < = ' 9 ' ) ) {
2012-04-23 17:43:56 +00:00
i + + ;
g_snprintf ( outstrptr , 4 , " :%.2s " , instr + 10 ) ;
outstrptr + = 3 ;
} else {
2012-08-14 17:58:41 +00:00
error_str = " BER Error: malformed UTCTime encoding, "
2012-04-23 17:43:56 +00:00
" if 11th octet is a digit for seconds, "
2012-08-14 17:58:41 +00:00
" the 12th octet has to be a digit, too " ;
2012-04-23 17:43:56 +00:00
goto malformed ;
}
}
}
/* Z|([+-]hhmm) */
switch ( instr [ i ] ) {
case ' Z ' :
2012-10-18 02:33:11 +00:00
if ( len ! = ( i + 1 ) ) {
2012-08-14 17:58:41 +00:00
error_str = " BER Error: malformed UTCTime encoding, "
" there must be no further octets after \' Z \' " ;
2012-04-23 17:43:56 +00:00
goto malformed ;
}
g_snprintf ( outstrptr , 7 , " (UTC) " ) ;
i + + ;
break ;
case ' - ' :
case ' + ' :
2012-10-18 02:33:11 +00:00
if ( len ! = ( i + 5 ) ) {
2012-08-14 17:58:41 +00:00
error_str = " BER Error: malformed UTCTime encoding, "
" 4 digits must follow on \' + \' resp. \' - \' " ;
2012-04-23 17:43:56 +00:00
goto malformed ;
}
2012-10-18 02:33:11 +00:00
for ( n = i + 1 ; n < i + 5 ; n + + ) {
if ( ( instr [ n ] < ' 0 ' ) | | ( instr [ n ] > ' 9 ' ) ) {
2012-08-14 17:58:41 +00:00
error_str = " BER Error: malformed UTCTime encoding, "
" 4 digits must follow on \' + \' resp. \' - \' " ;
2012-04-23 17:43:56 +00:00
goto malformed ;
}
}
g_snprintf ( outstrptr , 12 , " (UTC%c%.4s) " , instr [ i ] , instr + i + 1 ) ;
i + = 5 ;
break ;
default :
2013-09-12 22:03:31 +00:00
error_str = wmem_strdup_printf ( wmem_packet_scope ( ) ,
" BER Error: malformed UTCTime encoding, "
" unexpected character in %dth octet, "
" must be \' Z \' , \' + \' or \' - \' " , i + 1 ) ;
2012-04-23 17:43:56 +00:00
goto malformed ;
break ;
}
2012-10-18 02:33:11 +00:00
if ( len ! = i ) {
2013-09-12 22:03:31 +00:00
error_str = wmem_strdup_printf ( wmem_packet_scope ( ) ,
2012-10-18 02:33:11 +00:00
" BER Error: malformed UTCTime encoding, %d unexpected character%s after %dth octet " ,
len - i ,
( len = = ( i - 1 ) ? " s " : " " ) ,
i ) ;
2012-04-23 17:43:56 +00:00
goto malformed ;
}
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2012-04-23 17:43:56 +00:00
proto_tree_add_string ( tree , hf_id , tvb , offset , len , outstr ) ;
}
return offset + len ;
2008-08-01 16:44:06 +00:00
malformed :
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2012-04-23 17:43:56 +00:00
cause = proto_tree_add_string ( tree , hf_id , tvb , offset , len , instr ) ;
error_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
} else {
error_tree = tree ;
}
2012-04-03 17:37:27 +00:00
2012-10-18 02:33:11 +00:00
cause = proto_tree_add_string_format (
error_tree , hf_ber_error , tvb , offset , len , " invalid_utctime " ,
" %s " ,
error_str ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_invalid_format_utctime ) ;
2011-02-14 10:18:03 +00:00
2012-04-23 17:43:56 +00:00
return offset + len ;
2008-08-01 16:44:06 +00:00
}
2004-03-25 09:18:03 +00:00
/* 8.6 Encoding of a bitstring value */
2012-10-18 02:33:11 +00:00
int
dissect_ber_constrained_bitstring ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , gint32 min_len , gint32 max_len , const asn_namedbit * named_bits , gint hf_id , gint ett_id , tvbuff_t * * out_tvb )
2004-02-20 10:04:10 +00:00
{
2012-10-18 02:33:11 +00:00
gint8 ber_class ;
gboolean pc , ind ;
gint32 tag ;
guint32 len , byteno ;
guint8 pad = 0 , b0 , b1 , val , * bitstring ;
int end_offset ;
int hoffset ;
2012-04-23 17:43:56 +00:00
proto_item * item = NULL ;
proto_item * cause ;
proto_tree * tree = NULL ;
const char * sep ;
2012-10-18 02:33:11 +00:00
gboolean term ;
const asn_namedbit * nb ;
2012-04-23 17:43:56 +00:00
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag ) {
2012-04-23 17:43:56 +00:00
hoffset = offset ;
/* read header and len for the octet string */
offset = dissect_ber_identifier ( actx - > pinfo , parent_tree , tvb , offset , & ber_class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , parent_tree , tvb , offset , & len , & ind ) ;
end_offset = offset + len ;
/* sanity check: we only handle Universal BitStrings */
/* for an IMPLICIT APPLICATION tag asn2eth seems to call this
function with implicit_tag = FALSE . BER_FLAGS_NOOWNTAG was
set so the APPLICATION tag was still present .
So here we relax it for APPLICATION tags . CONTEXT tags may
still cause a problem . */
2012-10-18 02:33:11 +00:00
if ( ! implicit_tag & & ( ber_class ! = BER_CLASS_APP ) ) {
if ( ( ber_class ! = BER_CLASS_UNI )
| | ( tag ! = BER_UNI_TAG_BITSTRING ) ) {
2012-04-23 17:43:56 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2013-09-30 15:21:09 +00:00
cause = proto_tree_add_string_format_value (
2012-10-18 02:33:11 +00:00
parent_tree , hf_ber_error , tvb , offset , len , " bitstring_expected " ,
2013-09-30 15:21:09 +00:00
" BitString expected but class:%s(%d) %s tag:%d was unexpected " ,
2012-10-18 02:33:11 +00:00
val_to_str_const ( ber_class , ber_class_codes , " Unknown " ) ,
ber_class , pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string ,
tag ) ;
2013-07-02 21:16:10 +00:00
expert_add_info ( actx - > pinfo , cause , & ei_ber_expected_bitstring ) ;
2012-04-23 17:43:56 +00:00
if ( decode_unexpected ) {
proto_tree * unknown_tree = proto_item_add_subtree ( cause , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffset , unknown_tree ) ;
}
return end_offset ;
}
}
} else {
pc = 0 ;
2014-10-31 09:48:47 +00:00
len = tvb_reported_length_remaining ( tvb , offset ) ;
2012-10-18 02:33:11 +00:00
end_offset = offset + len ;
2012-04-23 17:43:56 +00:00
}
actx - > created_item = NULL ;
2012-10-18 02:33:11 +00:00
if ( pc ) {
2012-04-23 17:43:56 +00:00
/* constructed */
/* TO DO */
} else {
/* primitive */
pad = tvb_get_guint8 ( tvb , offset ) ;
2012-10-18 02:33:11 +00:00
if ( ( pad = = 0 ) & & ( len = = 1 ) ) {
2012-04-23 17:43:56 +00:00
/* empty */
proto_tree_add_item ( parent_tree , hf_ber_bitstring_empty , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
} else {
/* padding */
proto_item * pad_item = proto_tree_add_item ( parent_tree , hf_ber_bitstring_padding , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
if ( pad > 7 ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , pad_item , & ei_ber_illegal_padding ,
2012-10-18 02:33:11 +00:00
" Illegal padding (0 .. 7): %d " , pad ) ;
2012-04-23 17:43:56 +00:00
}
}
offset + + ;
len - - ;
2012-10-18 02:33:11 +00:00
if ( hf_id > = 0 ) {
2012-04-23 17:43:56 +00:00
item = proto_tree_add_item ( parent_tree , hf_id , tvb , offset , len , ENC_BIG_ENDIAN ) ;
actx - > created_item = item ;
2012-10-18 02:33:11 +00:00
if ( ett_id ! = - 1 ) {
2012-04-23 17:43:56 +00:00
tree = proto_item_add_subtree ( item , ett_id ) ;
}
}
2012-10-18 02:33:11 +00:00
if ( out_tvb ) {
2014-09-14 00:21:56 +00:00
* out_tvb = ber_tvb_new_subset_length ( tvb , offset , len ) ;
2012-04-23 17:43:56 +00:00
}
}
2012-10-18 02:33:11 +00:00
if ( named_bits ) {
sep = " ( " ;
2012-04-23 17:43:56 +00:00
term = FALSE ;
nb = named_bits ;
2014-01-27 13:12:59 +00:00
bitstring = ( guint8 * ) tvb_memdup ( wmem_packet_scope ( ) , tvb , offset , len ) ;
2012-04-23 17:43:56 +00:00
while ( nb - > p_id ) {
2014-06-17 18:13:51 +00:00
if ( ( len > 0 ) & & ( pad < 8 * len ) & & ( nb - > bit < ( 8 * len - pad ) ) ) {
2012-04-23 17:43:56 +00:00
val = tvb_get_guint8 ( tvb , offset + nb - > bit / 8 ) ;
bitstring [ ( nb - > bit / 8 ) ] & = ~ ( 0x80 > > ( nb - > bit % 8 ) ) ;
val & = 0x80 > > ( nb - > bit % 8 ) ;
b0 = ( nb - > gb0 = = - 1 ) ? nb - > bit / 8 :
( ( guint32 ) nb - > gb0 ) / 8 ;
b1 = ( nb - > gb1 = = - 1 ) ? nb - > bit / 8 :
( ( guint32 ) nb - > gb1 ) / 8 ;
proto_tree_add_item ( tree , * ( nb - > p_id ) , tvb , offset + b0 , b1 - b0 + 1 , ENC_BIG_ENDIAN ) ;
} else { /* 8.6.2.4 */
val = 0 ;
proto_tree_add_boolean ( tree , * ( nb - > p_id ) , tvb , offset + len , 0 , 0x00 ) ;
}
2012-10-18 02:33:11 +00:00
if ( val ) {
if ( item & & nb - > tstr ) {
2012-04-23 17:43:56 +00:00
proto_item_append_text ( item , " %s%s " , sep , nb - > tstr ) ;
2012-10-18 02:33:11 +00:00
sep = " , " ;
2012-04-23 17:43:56 +00:00
term = TRUE ;
}
} else {
2012-10-18 02:33:11 +00:00
if ( item & & nb - > fstr ) {
2012-04-23 17:43:56 +00:00
proto_item_append_text ( item , " %s%s " , sep , nb - > fstr ) ;
2012-10-18 02:33:11 +00:00
sep = " , " ;
2012-04-23 17:43:56 +00:00
term = TRUE ;
}
}
nb + + ;
}
2012-10-18 02:33:11 +00:00
if ( term )
2012-04-23 17:43:56 +00:00
proto_item_append_text ( item , " ) " ) ;
for ( byteno = 0 ; byteno < len ; byteno + + ) {
if ( bitstring [ byteno ] ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , item , & ei_ber_bits_unknown ,
2015-01-07 23:13:23 +00:00
" Unknown bit(s): 0x%s " , bytes_to_str ( wmem_packet_scope ( ) , bitstring , len ) ) ;
2012-04-23 17:43:56 +00:00
break ;
}
}
}
2012-10-18 02:33:11 +00:00
if ( ( pad > 0 ) & & ( pad < 8 ) & & ( len > 0 ) ) {
2012-04-23 17:43:56 +00:00
guint8 bits_in_pad = tvb_get_guint8 ( tvb , offset + len - 1 ) & ( 0xFF > > ( 8 - pad ) ) ;
if ( bits_in_pad ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format (
2013-07-02 21:16:10 +00:00
actx - > pinfo , item , & ei_ber_bits_set_padded ,
2012-10-18 02:33:11 +00:00
" Bits set in padded area: 0x%02x " , bits_in_pad ) ;
2012-04-23 17:43:56 +00:00
}
}
ber_check_length ( 8 * len - pad , min_len , max_len , actx , item , TRUE ) ;
return end_offset ;
2004-02-20 10:04:10 +00:00
}
2012-10-18 02:33:11 +00:00
int
dissect_ber_bitstring ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const asn_namedbit * named_bits , gint hf_id , gint ett_id , tvbuff_t * * out_tvb )
2010-01-05 11:38:33 +00:00
{
return dissect_ber_constrained_bitstring ( implicit_tag , actx , parent_tree , tvb , offset , - 1 , - 1 , named_bits , hf_id , ett_id , out_tvb ) ;
}
2012-10-18 02:33:11 +00:00
int
dissect_ber_bitstring32 ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , int * * bit_fields , gint hf_id , gint ett_id , tvbuff_t * * out_tvb )
2004-03-25 09:18:03 +00:00
{
2012-10-18 02:33:11 +00:00
tvbuff_t * tmp_tvb = NULL ;
proto_tree * tree ;
guint32 val ;
int * * bf ;
header_field_info * hfi ;
const char * sep ;
gboolean term ;
unsigned int i , tvb_len ;
2012-04-23 17:43:56 +00:00
offset = dissect_ber_bitstring ( implicit_tag , actx , parent_tree , tvb , offset , NULL , hf_id , ett_id , & tmp_tvb ) ;
tree = proto_item_get_subtree ( actx - > created_item ) ;
2012-10-18 02:33:11 +00:00
if ( bit_fields & & tree & & tmp_tvb ) {
2012-04-23 17:43:56 +00:00
/* tmp_tvb points to the actual bitstring (including any pad bits at the end.
* note that this bitstring is not neccessarily always encoded as 4 bytes
* so we have to read it byte by byte .
*/
2012-10-18 02:33:11 +00:00
val = 0 ;
2014-10-31 09:48:47 +00:00
tvb_len = tvb_reported_length ( tmp_tvb ) ;
2012-10-18 02:33:11 +00:00
for ( i = 0 ; i < 4 ; i + + ) {
val < < = 8 ;
if ( i < tvb_len ) {
val | = tvb_get_guint8 ( tmp_tvb , i ) ;
2012-04-23 17:43:56 +00:00
}
}
2012-10-18 02:33:11 +00:00
bf = bit_fields ;
sep = " ( " ;
2012-04-23 17:43:56 +00:00
term = FALSE ;
while ( * bf ) {
if ( * * bf > = 0 ) {
proto_tree_add_boolean ( tree , * * bf , tmp_tvb , 0 , tvb_len , val ) ;
hfi = proto_registrar_get_nth ( * * bf ) ;
2012-10-18 02:33:11 +00:00
if ( val & hfi - > bitmask ) {
2012-04-23 17:43:56 +00:00
proto_item_append_text ( actx - > created_item , " %s%s " , sep , hfi - > name ) ;
sep = " , " ;
term = TRUE ;
}
}
bf + + ;
}
2012-10-18 02:33:11 +00:00
if ( term )
2012-04-23 17:43:56 +00:00
proto_item_append_text ( actx - > created_item , " ) " ) ;
}
2012-10-18 02:33:11 +00:00
if ( out_tvb )
2012-04-23 17:43:56 +00:00
* out_tvb = tmp_tvb ;
return offset ;
2004-03-25 09:18:03 +00:00
}
2004-02-20 10:04:10 +00:00
2010-07-07 15:52:09 +00:00
/*
2012-04-23 17:43:56 +00:00
* 8.18 Encoding of a value of the external type
* 8.18 .1 The encoding of a value of the external type shall be the BER encoding of the following
* sequence type , assumed to be defined in an environment of EXPLICIT TAGS ,
* with a value as specified in the subclauses below :
2010-07-07 15:52:09 +00:00
*
2012-04-23 17:43:56 +00:00
* [ UNIVERSAL 8 ] IMPLICIT SEQUENCE {
* direct - reference OBJECT IDENTIFIER OPTIONAL ,
* indirect - reference INTEGER OPTIONAL ,
* data - value - descriptor ObjectDescriptor OPTIONAL ,
* encoding CHOICE {
* single - ASN1 - type [ 0 ] ABSTRACT - SYNTAX . & Type ,
* octet - aligned [ 1 ] IMPLICIT OCTET STRING ,
* arbitrary [ 2 ] IMPLICIT BIT STRING } }
2010-07-07 15:52:09 +00:00
*
2007-05-03 21:52:57 +00:00
*/
2007-05-15 05:49:43 +00:00
2007-05-22 21:15:00 +00:00
static int
2012-05-02 21:55:59 +00:00
dissect_ber_INTEGER ( gboolean implicit_tag , tvbuff_t * tvb , int offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index ) {
2007-05-22 21:15:00 +00:00
offset = dissect_ber_integer ( implicit_tag , actx , tree , tvb , offset , hf_index ,
2007-06-14 05:17:07 +00:00
& actx - > external . indirect_reference ) ;
2007-11-14 20:57:55 +00:00
actx - > external . indirect_ref_present = TRUE ;
2007-05-22 21:15:00 +00:00
2007-05-15 05:49:43 +00:00
return offset ;
}
2007-05-22 21:15:00 +00:00
static int
2010-07-07 15:52:09 +00:00
dissect_ber_T_octet_aligned ( gboolean implicit_tag _U_ , tvbuff_t * tvb _U_ , int offset _U_ , asn1_ctx_t * actx _U_ , proto_tree * tree _U_ , int hf_index _U_ )
2007-11-21 23:33:13 +00:00
{
2012-04-23 17:43:56 +00:00
if ( actx - > external . u . ber . ber_callback ) {
offset = actx - > external . u . ber . ber_callback ( FALSE , tvb , offset , actx , tree , hf_index ) ;
} else if ( actx - > external . direct_ref_present & &
dissector_get_string_handle ( ber_oid_dissector_table , actx - > external . direct_reference ) ) {
2013-10-31 00:57:03 +00:00
offset = call_ber_oid_callback ( actx - > external . direct_reference , tvb , offset , actx - > pinfo , tree , NULL ) ;
2012-04-23 17:43:56 +00:00
} else {
offset = dissect_ber_octet_string ( implicit_tag , actx , tree , tvb , offset , hf_index , & actx - > external . octet_aligned ) ;
}
2007-05-03 21:52:57 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2007-05-03 21:52:57 +00:00
}
2007-05-22 21:15:00 +00:00
static int
2012-05-02 21:55:59 +00:00
dissect_ber_OBJECT_IDENTIFIER ( gboolean implicit_tag , tvbuff_t * tvb , int offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index )
2007-11-21 23:33:13 +00:00
{
2012-04-23 17:43:56 +00:00
offset = dissect_ber_object_identifier_str ( implicit_tag , actx , tree , tvb , offset , hf_index , & actx - > external . direct_reference ) ;
actx - > external . direct_ref_present = TRUE ;
2007-11-14 20:57:55 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2007-05-03 21:52:57 +00:00
}
2007-05-22 21:15:00 +00:00
static int
2010-07-07 15:52:09 +00:00
dissect_ber_ObjectDescriptor ( gboolean implicit_tag _U_ , tvbuff_t * tvb _U_ , int offset _U_ , asn1_ctx_t * actx _U_ , proto_tree * tree _U_ , int hf_index _U_ )
2007-11-21 23:33:13 +00:00
{
2012-04-23 17:43:56 +00:00
offset = dissect_ber_restricted_string ( implicit_tag , BER_UNI_TAG_ObjectDescriptor ,
actx , tree , tvb , offset , hf_index ,
& actx - > external . data_value_descriptor ) ;
2007-05-03 21:52:57 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2007-05-03 21:52:57 +00:00
}
2007-05-22 21:15:00 +00:00
static int
2010-07-07 15:52:09 +00:00
dissect_ber_T_single_ASN1_type ( gboolean implicit_tag _U_ , tvbuff_t * tvb _U_ , int offset _U_ , asn1_ctx_t * actx _U_ , proto_tree * tree _U_ , int hf_index _U_ )
2007-11-21 23:33:13 +00:00
{
2012-04-23 17:43:56 +00:00
if ( actx - > external . u . ber . ber_callback ) {
offset = actx - > external . u . ber . ber_callback ( FALSE , tvb , offset , actx , tree , hf_index ) ;
} else {
2013-10-31 00:57:03 +00:00
offset = call_ber_oid_callback ( actx - > external . direct_reference , tvb , offset , actx - > pinfo , tree , NULL ) ;
2012-04-23 17:43:56 +00:00
}
2007-06-14 05:17:07 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2007-05-03 21:52:57 +00:00
}
2007-05-22 21:15:00 +00:00
static int
2010-07-07 15:52:09 +00:00
dissect_ber_T_arbitrary ( gboolean implicit_tag _U_ , tvbuff_t * tvb _U_ , int offset _U_ , asn1_ctx_t * actx _U_ , proto_tree * tree _U_ , int hf_index _U_ )
2007-11-21 23:33:13 +00:00
{
2012-04-23 17:43:56 +00:00
if ( actx - > external . u . ber . ber_callback ) {
offset = actx - > external . u . ber . ber_callback ( FALSE , tvb , offset , actx , tree , hf_index ) ;
} else {
offset = dissect_ber_bitstring ( implicit_tag , actx , tree , tvb , offset ,
NULL , hf_index , - 1 , & actx - > external . arbitrary ) ;
}
2007-05-03 21:52:57 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2007-05-03 21:52:57 +00:00
}
2007-05-22 21:15:00 +00:00
2007-05-03 21:52:57 +00:00
static const value_string ber_T_encoding_vals [ ] = {
2012-04-23 17:43:56 +00:00
{ 0 , " single-ASN1-type " } ,
{ 1 , " octet-aligned " } ,
{ 2 , " arbitrary " } ,
{ 0 , NULL }
2007-05-03 21:52:57 +00:00
} ;
2007-05-22 21:15:00 +00:00
static const ber_choice_t T_encoding_choice [ ] = {
2012-04-23 17:43:56 +00:00
{ 0 , & hf_ber_single_ASN1_type , BER_CLASS_CON , 0 , 0 , dissect_ber_T_single_ASN1_type } ,
2012-10-18 02:33:11 +00:00
{ 1 , & hf_ber_octet_aligned , BER_CLASS_CON , 1 , BER_FLAGS_IMPLTAG , dissect_ber_T_octet_aligned } ,
{ 2 , & hf_ber_arbitrary , BER_CLASS_CON , 2 , BER_FLAGS_IMPLTAG , dissect_ber_T_arbitrary } ,
2012-04-23 17:43:56 +00:00
{ 0 , NULL , 0 , 0 , 0 , NULL }
2007-05-03 21:52:57 +00:00
} ;
2007-05-22 21:15:00 +00:00
static int
2012-05-02 21:55:59 +00:00
dissect_ber_T_encoding ( gboolean implicit_tag _U_ , tvbuff_t * tvb , int offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index ) {
2012-04-23 17:43:56 +00:00
offset = dissect_ber_choice ( actx , tree , tvb , offset ,
T_encoding_choice , hf_index , ett_ber_T_encoding ,
& actx - > external . encoding ) ;
2007-05-03 21:52:57 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2007-05-03 21:52:57 +00:00
}
2007-05-22 21:15:00 +00:00
static const ber_sequence_t external_U_sequence [ ] = {
2012-10-18 02:33:11 +00:00
{ & hf_ber_direct_reference , BER_CLASS_UNI , BER_UNI_TAG_OID , BER_FLAGS_OPTIONAL | BER_FLAGS_NOOWNTAG , dissect_ber_OBJECT_IDENTIFIER } ,
{ & hf_ber_indirect_reference , BER_CLASS_UNI , BER_UNI_TAG_INTEGER , BER_FLAGS_OPTIONAL | BER_FLAGS_NOOWNTAG , dissect_ber_INTEGER } ,
2012-04-23 17:43:56 +00:00
{ & hf_ber_data_value_descriptor , BER_CLASS_UNI , BER_UNI_TAG_ObjectDescriptor , BER_FLAGS_OPTIONAL | BER_FLAGS_NOOWNTAG , dissect_ber_ObjectDescriptor } ,
2012-10-18 02:33:11 +00:00
{ & hf_ber_encoding , BER_CLASS_ANY /*choice*/ , - 1 /*choice*/ , BER_FLAGS_NOOWNTAG | BER_FLAGS_NOTCHKTAG , dissect_ber_T_encoding } ,
2012-04-23 17:43:56 +00:00
{ NULL , 0 , 0 , 0 , NULL }
2007-05-03 21:52:57 +00:00
} ;
static int
2007-07-05 13:14:25 +00:00
dissect_ber_external_U ( gboolean implicit_tag , tvbuff_t * tvb , int offset , asn1_ctx_t * actx _U_ , proto_tree * tree , int hf_index _U_ )
2007-05-03 21:52:57 +00:00
{
2012-04-23 17:43:56 +00:00
offset = dissect_ber_sequence ( implicit_tag , actx , tree , tvb , offset ,
external_U_sequence , hf_index , ett_ber_EXTERNAL ) ;
return offset ;
2007-05-03 21:52:57 +00:00
}
int
2012-10-18 02:33:11 +00:00
dissect_ber_external_type ( gboolean implicit_tag , proto_tree * tree , tvbuff_t * tvb , int offset , asn1_ctx_t * actx , gint hf_id , ber_callback func ) {
2007-05-03 21:52:57 +00:00
2012-04-23 17:43:56 +00:00
actx - > external . u . ber . ber_callback = func ;
2007-05-06 22:34:05 +00:00
2012-04-23 17:43:56 +00:00
offset = dissect_ber_tagged_type ( implicit_tag , actx , tree , tvb , offset ,
hf_id , BER_CLASS_UNI , BER_UNI_TAG_EXTERNAL , TRUE , dissect_ber_external_U ) ;
2007-05-03 21:52:57 +00:00
2012-04-23 17:43:56 +00:00
asn1_ctx_clean_external ( actx ) ;
2007-05-03 21:52:57 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2007-05-03 21:52:57 +00:00
}
2007-06-03 19:58:59 +00:00
/* Experimental */
int
2012-10-18 02:33:11 +00:00
dissect_ber_EmbeddedPDV_Type ( gboolean implicit_tag , proto_tree * tree , tvbuff_t * tvb , int offset , asn1_ctx_t * actx , gint hf_id , ber_callback func _U_ ) {
2007-06-03 19:58:59 +00:00
2012-04-23 17:43:56 +00:00
offset = dissect_ber_tagged_type ( implicit_tag , actx , tree , tvb , offset ,
hf_id , BER_CLASS_UNI , BER_UNI_TAG_EMBEDDED_PDV , TRUE , dissect_ber_external_U ) ;
2007-06-03 19:58:59 +00:00
2012-04-23 17:43:56 +00:00
return offset ;
2007-06-03 19:58:59 +00:00
}
2007-05-06 22:34:05 +00:00
2010-06-23 11:28:59 +00:00
static void
dissect_ber_syntax ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
{
2012-04-23 17:43:56 +00:00
( void ) dissect_unknown_ber ( pinfo , tvb , 0 , tree ) ;
2010-06-23 11:28:59 +00:00
}
2014-06-15 20:02:16 +00:00
static int
dissect_ber ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
2006-05-08 19:56:36 +00:00
{
2012-04-23 17:43:56 +00:00
const char * name ;
2014-06-15 20:02:16 +00:00
int offset ;
2006-05-08 19:56:36 +00:00
2012-04-23 17:43:56 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " BER " ) ;
2006-05-08 19:56:36 +00:00
2012-04-23 17:43:56 +00:00
col_set_str ( pinfo - > cinfo , COL_DEF_SRC , " BER encoded file " ) ;
2006-05-08 19:56:36 +00:00
2012-10-18 02:33:11 +00:00
if ( ! decode_as_syntax ) {
2010-07-07 15:52:09 +00:00
2012-04-23 17:43:56 +00:00
/* if we got here we couldn't find anything better */
col_set_str ( pinfo - > cinfo , COL_INFO , " Unknown BER " ) ;
2007-01-13 12:59:27 +00:00
2014-06-15 20:02:16 +00:00
offset = dissect_unknown_ber ( pinfo , tvb , 0 , tree ) ;
2007-01-13 12:59:27 +00:00
2012-04-23 17:43:56 +00:00
} else {
2007-01-13 12:59:27 +00:00
2014-06-15 20:02:16 +00:00
offset = call_ber_syntax_callback ( decode_as_syntax , tvb , 0 , pinfo , tree ) ;
2007-01-13 12:59:27 +00:00
2012-04-23 17:43:56 +00:00
/* see if we have a better name */
name = get_ber_oid_syntax ( decode_as_syntax ) ;
col_add_fstr ( pinfo - > cinfo , COL_INFO , " Decoded as %s " , name ? name : decode_as_syntax ) ;
}
2014-06-15 20:02:16 +00:00
return offset ;
2007-01-13 12:59:27 +00:00
}
2006-05-08 19:56:36 +00:00
2012-10-18 02:33:11 +00:00
gboolean
oid_has_dissector ( const char * oid ) {
2012-08-10 22:55:02 +00:00
return ( dissector_get_string_handle ( ber_oid_dissector_table , oid ) ! = NULL ) ;
}
2004-02-20 10:04:10 +00:00
void
proto_register_ber ( void )
{
static hf_register_info hf [ ] = {
2012-04-23 17:43:56 +00:00
{ & hf_ber_id_class , {
" Class " , " ber.id.class " , FT_UINT8 , BASE_DEC ,
VALS ( ber_class_codes ) , 0xc0 , " Class of BER TLV Identifier " , HFILL } } ,
{ & hf_ber_bitstring_padding , {
" Padding " , " ber.bitstring.padding " , FT_UINT8 , BASE_DEC ,
NULL , 0x0 , " Number of unused bits in the last octet of the bitstring " , HFILL } } ,
{ & hf_ber_bitstring_empty , {
" Empty " , " ber.bitstring.empty " , FT_UINT8 , BASE_DEC ,
NULL , 0x0 , " This is an empty bitstring " , HFILL } } ,
{ & hf_ber_id_pc , {
" P/C " , " ber.id.pc " , FT_BOOLEAN , 8 ,
TFS ( & ber_pc_codes ) , 0x20 , " Primitive or Constructed BER encoding " , HFILL } } ,
{ & hf_ber_id_uni_tag , {
" Tag " , " ber.id.uni_tag " , FT_UINT8 , BASE_DEC | BASE_EXT_STRING ,
& ber_uni_tag_codes_ext , 0x1f , " Universal tag type " , HFILL } } ,
{ & hf_ber_id_uni_tag_ext , {
" Tag " , " ber.id.uni_tag " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Universal tag type " , HFILL } } ,
{ & hf_ber_id_tag , {
" Tag " , " ber.id.tag " , FT_UINT8 , BASE_DEC ,
NULL , 0x1f , " Tag value for non-Universal classes " , HFILL } } ,
{ & hf_ber_id_tag_ext , {
" Tag " , " ber.id.tag " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Tag value for non-Universal classes " , HFILL } } ,
{ & hf_ber_length , {
" Length " , " ber.length " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Length of contents " , HFILL } } ,
{ & hf_ber_unknown_OCTETSTRING , {
" OCTETSTRING " , " ber.unknown.OCTETSTRING " , FT_BYTES , BASE_NONE ,
NULL , 0 , " This is an unknown OCTETSTRING " , HFILL } } ,
{ & hf_ber_unknown_BER_OCTETSTRING , {
" OCTETSTRING [BER encoded] " , " ber.unknown.OCTETSTRING " , FT_NONE , BASE_NONE ,
NULL , 0 , " This is an BER encoded OCTETSTRING " , HFILL } } ,
{ & hf_ber_unknown_BER_primitive , {
" Primitive [BER encoded] " , " ber.unknown.primitive " , FT_NONE , BASE_NONE ,
NULL , 0 , " This is a BER encoded Primitive " , HFILL } } ,
{ & hf_ber_unknown_OID , {
" OID " , " ber.unknown.OID " , FT_OID , BASE_NONE ,
NULL , 0 , " This is an unknown Object Identifier " , HFILL } } ,
2014-04-07 23:41:25 +00:00
{ & hf_ber_unknown_relative_OID , {
" OID " , " ber.unknown.relative_OID " , FT_REL_OID , BASE_NONE ,
NULL , 0 , " This is an unknown relative Object Identifier " , HFILL } } ,
2012-04-23 17:43:56 +00:00
{ & hf_ber_unknown_GraphicString , {
" GRAPHICSTRING " , " ber.unknown.GRAPHICSTRING " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown GRAPHICSTRING " , HFILL } } ,
{ & hf_ber_unknown_NumericString , {
" NumericString " , " ber.unknown.NumericString " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown NumericString " , HFILL } } ,
{ & hf_ber_unknown_PrintableString , {
" PrintableString " , " ber.unknown.PrintableString " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown PrintableString " , HFILL } } ,
{ & hf_ber_unknown_TeletexString , {
" TeletexString " , " ber.unknown.TeletexString " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown TeletexString " , HFILL } } ,
{ & hf_ber_unknown_VisibleString , {
" VisibleString " , " ber.unknown.VisibleString " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown VisibleString " , HFILL } } ,
{ & hf_ber_unknown_GeneralString , {
" GeneralString " , " ber.unknown.GeneralString " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown GeneralString " , HFILL } } ,
{ & hf_ber_unknown_UniversalString , {
" UniversalString " , " ber.unknown.UniversalString " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown UniversalString " , HFILL } } ,
{ & hf_ber_unknown_BMPString , {
" BMPString " , " ber.unknown.BMPString " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown BMPString " , HFILL } } ,
{ & hf_ber_unknown_IA5String , {
" IA5String " , " ber.unknown.IA5String " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown IA5String " , HFILL } } ,
{ & hf_ber_unknown_UTCTime , {
" UTCTime " , " ber.unknown.UTCTime " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown UTCTime " , HFILL } } ,
{ & hf_ber_unknown_UTF8String , {
" UTF8String " , " ber.unknown.UTF8String " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown UTF8String " , HFILL } } ,
{ & hf_ber_unknown_GeneralizedTime , {
" GeneralizedTime " , " ber.unknown.GeneralizedTime " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown GeneralizedTime " , HFILL } } ,
{ & hf_ber_unknown_INTEGER , {
" INTEGER " , " ber.unknown.INTEGER " , FT_INT64 , BASE_DEC ,
NULL , 0 , " This is an unknown INTEGER " , HFILL } } ,
2014-11-28 15:53:04 +00:00
{ & hf_ber_unknown_REAL , {
" REAL " , " ber.unknown.REAL " , FT_DOUBLE , BASE_NONE ,
NULL , 0 , " This is an unknown REAL " , HFILL } } ,
2012-04-23 17:43:56 +00:00
{ & hf_ber_unknown_BITSTRING , {
" BITSTRING " , " ber.unknown.BITSTRING " , FT_BYTES , BASE_NONE ,
NULL , 0 , " This is an unknown BITSTRING " , HFILL } } ,
{ & hf_ber_unknown_BOOLEAN , {
" BOOLEAN " , " ber.unknown.BOOLEAN " , FT_UINT8 , BASE_HEX ,
NULL , 0 , " This is an unknown BOOLEAN " , HFILL } } ,
{ & hf_ber_unknown_ENUMERATED , {
" ENUMERATED " , " ber.unknown.ENUMERATED " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " This is an unknown ENUMERATED " , HFILL } } ,
{ & hf_ber_error , {
" BER Error " , " ber.error " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL } } ,
{ & hf_ber_direct_reference ,
{ " direct-reference " , " ber.direct_reference " ,
FT_OID , BASE_NONE , NULL , 0 ,
" ber.OBJECT_IDENTIFIER " , HFILL } } ,
{ & hf_ber_indirect_reference ,
{ " indirect-reference " , " ber.indirect_reference " ,
FT_INT32 , BASE_DEC , NULL , 0 ,
" ber.INTEGER " , HFILL } } ,
{ & hf_ber_data_value_descriptor ,
{ " data-value-descriptor " , " ber.data_value_descriptor " ,
FT_STRING , BASE_NONE , NULL , 0 ,
" ber.ObjectDescriptor " , HFILL } } ,
{ & hf_ber_encoding ,
{ " encoding " , " ber.encoding " ,
FT_UINT32 , BASE_DEC , VALS ( ber_T_encoding_vals ) , 0 ,
" ber.T_encoding " , HFILL } } ,
{ & hf_ber_octet_aligned ,
{ " octet-aligned " , " ber.octet_aligned " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" ber.T_octet_aligned " , HFILL } } ,
{ & hf_ber_arbitrary ,
{ " arbitrary " , " ber.arbitrary " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" ber.T_arbitrary " , HFILL } } ,
{ & hf_ber_single_ASN1_type ,
{ " single-ASN1-type " , " ber.single_ASN1_type " ,
FT_NONE , BASE_NONE , NULL , 0 ,
" ber.T_single_ASN1_type " , HFILL } } ,
/* Fragment entries */
{ & hf_ber_fragments ,
{ " OCTET STRING fragments " , " ber.octet_string.fragments " , FT_NONE , BASE_NONE ,
NULL , 0x00 , NULL , HFILL } } ,
{ & hf_ber_fragment ,
{ " OCTET STRING fragment " , " ber.octet_string.fragment " , FT_FRAMENUM , BASE_NONE ,
NULL , 0x00 , NULL , HFILL } } ,
{ & hf_ber_fragment_overlap ,
{ " OCTET STRING fragment overlap " , " ber.octet_string.fragment.overlap " , FT_BOOLEAN ,
BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ber_fragment_overlap_conflicts ,
{ " OCTET STRING fragment overlapping with conflicting data " ,
" ber.octet_string.fragment.overlap.conflicts " , FT_BOOLEAN , BASE_NONE , NULL ,
0x0 , NULL , HFILL } } ,
{ & hf_ber_fragment_multiple_tails ,
{ " OCTET STRING has multiple tail fragments " ,
" ber.octet_string.fragment.multiple_tails " , FT_BOOLEAN , BASE_NONE ,
NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ber_fragment_too_long_fragment ,
{ " OCTET STRING fragment too long " , " ber.octet_string.fragment.too_long_fragment " ,
FT_BOOLEAN , BASE_NONE , NULL , 0x0 , NULL ,
HFILL } } ,
{ & hf_ber_fragment_error ,
{ " OCTET STRING defragmentation error " , " ber.octet_string.fragment.error " , FT_FRAMENUM ,
BASE_NONE , NULL , 0x00 , NULL , HFILL } } ,
{ & hf_ber_fragment_count ,
{ " OCTET STRING fragment count " , " ber.octet_string.fragment.count " , FT_UINT32 , BASE_DEC ,
NULL , 0x00 , NULL , HFILL } } ,
{ & hf_ber_reassembled_in ,
{ " Reassembled in " , " ber.octet_string.reassembled.in " , FT_FRAMENUM , BASE_NONE ,
NULL , 0x00 , NULL , HFILL } } ,
{ & hf_ber_reassembled_length ,
{ " Reassembled OCTET STRING length " , " ber.octet_string.reassembled.length " , FT_UINT32 , BASE_DEC ,
2014-11-01 20:55:25 +00:00
NULL , 0x00 , NULL , HFILL } } ,
/* Generated from convert_proto_tree_add_text.pl */
{ & hf_ber_null_tag , { " NULL tag " , " ber.null_tag " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ber_unknown_data , { " Unknown Data " , " ber.unknown_data " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ber_unknown_octetstring , { " Unknown OctetString " , " ber.unknown_octetstring " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ber_seq_field_eoc , { " SEQ FIELD EOC " , " ber.seq_field_eoc " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ber_seq_eoc , { " SEQ EOC " , " ber.seq_eoc " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ber_set_field_eoc , { " SET FIELD EOC " , " ber.set_field_eoc " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ber_set_eoc , { " SET EOC " , " ber.set_eoc " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ber_choice_eoc , { " CHOICE EOC " , " ber.choice_eoc " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ber_seq_of_eoc , { " SEQ OF EOC " , " ber.seq_of_eoc " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
2004-02-20 10:04:10 +00:00
} ;
2007-06-12 21:29:27 +00:00
2004-02-20 10:04:10 +00:00
static gint * ett [ ] = {
2012-04-23 17:43:56 +00:00
& ett_ber_octet_string ,
& ett_ber_reassembled_octet_string ,
& ett_ber_primitive ,
& ett_ber_unknown ,
& ett_ber_SEQUENCE ,
& ett_ber_EXTERNAL ,
& ett_ber_T_encoding ,
& ett_ber_fragment ,
& ett_ber_fragments
2004-02-20 10:04:10 +00:00
} ;
2013-07-02 21:16:10 +00:00
static ei_register_info ei [ ] = {
{ & ei_ber_size_constraint_string , { " ber.size_constraint.string " , PI_PROTOCOL , PI_WARN , " Size constraint: string " , EXPFILL } } ,
{ & ei_ber_size_constraint_value , { " ber.size_constraint.value " , PI_PROTOCOL , PI_WARN , " Size constraint: values " , EXPFILL } } ,
{ & ei_ber_size_constraint_items , { " ber.size_constraint.items " , PI_PROTOCOL , PI_WARN , " Size constraint: items " , EXPFILL } } ,
{ & ei_ber_sequence_field_wrong , { " ber.error.sequence.field_wrong " , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in SEQUENCE " , EXPFILL } } ,
{ & ei_ber_expected_octet_string , { " ber.error.expected.octet_string " , PI_MALFORMED , PI_WARN , " BER Error: OctetString expected " , EXPFILL } } ,
{ & ei_ber_expected_null , { " ber.error.expected.null " , PI_MALFORMED , PI_WARN , " BER Error: NULL expected " , EXPFILL } } ,
{ & ei_ber_expected_null_zero_length , { " ber.error.expected.null_zero_length " , PI_MALFORMED , PI_WARN , " BER Error: NULL expect zero length " , EXPFILL } } ,
{ & ei_ber_expected_sequence , { " ber.error.expected.sequence " , PI_MALFORMED , PI_WARN , " BER Error: Sequence expected " , EXPFILL } } ,
{ & ei_ber_expected_set , { " ber.error.expected.set " , PI_MALFORMED , PI_WARN , " BER Error: SET expected " , EXPFILL } } ,
{ & ei_ber_expected_string , { " ber.error.expected.string " , PI_MALFORMED , PI_WARN , " BER Error: String expected " , EXPFILL } } ,
{ & ei_ber_expected_object_identifier , { " ber.error.expected.object_identifier " , PI_MALFORMED , PI_WARN , " BER Error: Object Identifier expected " , EXPFILL } } ,
{ & ei_ber_expected_generalized_time , { " ber.error.expected.generalized_time " , PI_MALFORMED , PI_WARN , " BER Error: GeneralizedTime expected " , EXPFILL } } ,
{ & ei_ber_expected_utc_time , { " ber.error.expected.utc_time " , PI_MALFORMED , PI_WARN , " BER Error: UTCTime expected " , EXPFILL } } ,
{ & ei_ber_expected_bitstring , { " ber.error.expected.bitstring " , PI_MALFORMED , PI_WARN , " BER Error: BitString expected " , EXPFILL } } ,
{ & ei_ber_error_length , { " ber.error.length " , PI_MALFORMED , PI_WARN , " BER Error length " , EXPFILL } } ,
{ & ei_ber_wrong_tag_in_tagged_type , { " ber.error.wrong_tag_in_tagged_type " , PI_MALFORMED , PI_WARN , " BER Error: Wrong tag in tagged type " , EXPFILL } } ,
{ & ei_ber_universal_tag_unknown , { " ber.error.universal_tag_unknown " , PI_MALFORMED , PI_WARN , " BER Error: can not handle universal " , EXPFILL } } ,
{ & ei_ber_no_oid , { " ber.error.no_oid " , PI_MALFORMED , PI_WARN , " BER Error: No OID supplied to call_ber_oid_callback " , EXPFILL } } ,
{ & ei_ber_oid_not_implemented , { " ber.error.oid_not_implemented " , PI_UNDECODED , PI_WARN , " BER: Dissector for OID not implemented. Contact Wireshark developers if you want this supported " , EXPFILL } } ,
{ & ei_ber_syntax_not_implemented , { " ber.error.syntax_not_implemented " , PI_UNDECODED , PI_WARN , " BER: Syntax not implemented " , EXPFILL } } ,
{ & ei_ber_value_too_many_bytes , { " ber.error.value_too_many_bytes " , PI_MALFORMED , PI_WARN , " Value is encoded with too many bytes " , EXPFILL } } ,
{ & ei_ber_unknown_field_sequence , { " ber.error.unknown_field.sequence " , PI_MALFORMED , PI_WARN , " BER Error: Unknown field in Sequence " , EXPFILL } } ,
{ & ei_ber_unknown_field_set , { " ber.error.unknown_field.set " , PI_MALFORMED , PI_WARN , " BER Error: Unknown field in SET " , EXPFILL } } ,
{ & ei_ber_missing_field_set , { " ber.error.missing_field.set " , PI_MALFORMED , PI_WARN , " BER Error: Missing field in SET " , EXPFILL } } ,
{ & ei_ber_empty_choice , { " ber.error.empty_choice " , PI_MALFORMED , PI_WARN , " BER Error: Empty choice was found " , EXPFILL } } ,
{ & ei_ber_choice_not_found , { " ber.error.choice_not_found " , PI_MALFORMED , PI_WARN , " BER Error: This choice field was not found " , EXPFILL } } ,
{ & ei_ber_bits_unknown , { " ber.error.bits_unknown " , PI_UNDECODED , PI_WARN , " BER Error: Bits unknown " , EXPFILL } } ,
{ & ei_ber_bits_set_padded , { " ber.error.bits_set_padded " , PI_UNDECODED , PI_WARN , " BER Error: Bits set in padded area " , EXPFILL } } ,
{ & ei_ber_illegal_padding , { " ber.error.illegal_padding " , PI_UNDECODED , PI_WARN , " Illegal padding " , EXPFILL } } ,
{ & ei_ber_invalid_format_generalized_time , { " ber.error.invalid_format.generalized_time " , PI_MALFORMED , PI_WARN , " BER Error: GeneralizedTime invalid format " , EXPFILL } } ,
{ & ei_ber_invalid_format_utctime , { " ber.error.invalid_format.utctime " , PI_MALFORMED , PI_WARN , " BER Error: malformed UTCTime encoding " , EXPFILL } } ,
2014-11-01 20:55:25 +00:00
{ & ei_hf_field_not_integer_type , { " ber.error.hf_field_not_integer_type " , PI_PROTOCOL , PI_ERROR , " Was passed a HF field that was not integer type " , EXPFILL } } ,
2013-07-02 21:16:10 +00:00
} ;
2013-11-20 19:17:08 +00:00
/* Decode As handling */
static build_valid_func ber_da_build_value [ 1 ] = { ber_value } ;
static decode_as_value_t ber_da_values = { ber_prompt , 1 , ber_da_build_value } ;
static decode_as_t ber_da = { " ber " , " ASN.1 " , " ber.syntax " , 1 , 0 , & ber_da_values , NULL , NULL ,
ber_populate_list , ber_decode_as_reset , ber_decode_as_change , NULL } ;
2004-02-20 10:04:10 +00:00
module_t * ber_module ;
2013-07-02 21:16:10 +00:00
expert_module_t * expert_ber ;
2010-06-28 09:33:04 +00:00
uat_t * users_uat = uat_new ( " OID Tables " ,
2012-04-23 17:43:56 +00:00
sizeof ( oid_user_t ) ,
" oid " ,
FALSE ,
2014-01-30 17:43:52 +00:00
& oid_users ,
2012-04-23 17:43:56 +00:00
& num_oid_users ,
UATs could be put into "categories". The categories were defined only
implicitly by the #define name and string they were defined to; not all
UATs neatly fit into any of the categories, so some of them were put
into categories that weren't obviously correct for them, and one - the
display filter macro UAT - wasn't put into any category at all (which
caused crashes when editing them, as the GUI code that handled UAT
changes from a dialog assumed the category field was non-null).
The category was, in practice, used only to decide, in the
aforementioned GUI code, whether the packet summary pane needed to be
updated or not. It also offered no option of "don't update the packet
summary pane *and* don't redissect anything", which is what would be
appropriate for the display filter macro UAT.
Replace the category with a set of fields indicating what the UAT
affects; we currently offer "dissection", which applies to most UATs
(any UAT in libwireshark presumably affects dissection at a minimum) and
"the set of named fields that exist". Changing any UAT that affects
dissection requires a redissection; changing any UAT that affects the
set of named fields that exist requires a redissection *and* rebuilding
the packet summary pane.
Perhaps we also need "filtering", so that if you change a display filter
macro, we re-filter, in case the display is currently filtered with a
display filter that uses a macro that changed.
svn path=/trunk/; revision=43603
2012-07-08 01:00:46 +00:00
UAT_AFFECTS_DISSECTION , /* affects dissection of packets, but not set of named fields */
2012-04-23 17:43:56 +00:00
" ChObjectIdentifiers " ,
oid_copy_cb ,
NULL ,
oid_free_cb ,
ber_update_oids ,
users_flds ) ;
2004-02-20 10:04:10 +00:00
2004-03-25 23:57:10 +00:00
proto_ber = proto_register_protocol ( " Basic Encoding Rules (ASN.1 X.690) " , " BER " , " ber " ) ;
2013-08-05 19:09:44 +00:00
2014-06-15 20:02:16 +00:00
ber_handle = new_register_dissector ( " ber " , dissect_ber , proto_ber ) ;
2013-08-05 19:09:44 +00:00
2004-02-20 10:04:10 +00:00
proto_register_field_array ( proto_ber , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2013-07-02 21:16:10 +00:00
expert_ber = expert_register_protocol ( proto_ber ) ;
expert_register_field_array ( expert_ber , ei , array_length ( ei ) ) ;
2004-02-20 10:04:10 +00:00
2010-01-30 17:44:45 +00:00
proto_set_cant_toggle ( proto_ber ) ;
2004-03-25 09:18:03 +00:00
2004-02-20 10:04:10 +00:00
/* Register preferences */
2010-06-23 14:26:19 +00:00
ber_module = prefs_register_protocol ( proto_ber , NULL ) ;
2004-02-20 10:04:10 +00:00
prefs_register_bool_preference ( ber_module , " show_internals " ,
2012-04-23 17:43:56 +00:00
" Show internal BER encapsulation tokens " ,
" Whether the dissector should also display internal "
" ASN.1 BER details such as Identifier and Length fields " , & show_internal_ber_fields ) ;
2007-07-05 13:14:25 +00:00
prefs_register_bool_preference ( ber_module , " decode_unexpected " ,
2012-04-23 17:43:56 +00:00
" Decode unexpected tags as BER encoded data " ,
" Whether the dissector should decode unexpected tags as "
" ASN.1 BER encoded data " , & decode_unexpected ) ;
2007-02-17 11:10:02 +00:00
prefs_register_bool_preference ( ber_module , " decode_octetstring " ,
2012-04-23 17:43:56 +00:00
" Decode OCTET STRING as BER encoded data " ,
" Whether the dissector should try decoding OCTET STRINGs as "
" constructed ASN.1 BER encoded data " , & decode_octetstring_as_ber ) ;
2010-06-23 11:28:59 +00:00
2010-01-30 17:44:45 +00:00
prefs_register_bool_preference ( ber_module , " decode_primitive " ,
2012-04-23 17:43:56 +00:00
" Decode Primitive as BER encoded data " ,
" Whether the dissector should try decoding unknown primitive as "
" constructed ASN.1 BER encoded data " , & decode_primitive_as_ber ) ;
2004-07-21 11:13:03 +00:00
2012-06-05 05:16:06 +00:00
prefs_register_bool_preference ( ber_module , " warn_too_many_bytes " ,
" Warn if too many leading zero bits in encoded data " ,
" Whether the dissector should warn if excessive leading zero (0) bits " ,
& decode_warning_leading_zero_bits ) ;
2010-06-28 09:33:04 +00:00
prefs_register_uat_preference ( ber_module , " oid_table " , " Object Identifiers " ,
2012-04-23 17:43:56 +00:00
" A table that provides names for object identifiers "
" and the syntax of any associated values " ,
users_uat ) ;
2010-06-23 14:26:19 +00:00
2004-07-21 11:13:03 +00:00
ber_oid_dissector_table = register_dissector_table ( " ber.oid " , " BER OID Dissectors " , FT_STRING , BASE_NONE ) ;
2013-12-10 19:23:26 +00:00
ber_syntax_dissector_table = register_dissector_table ( " ber.syntax " , " BER syntax " , FT_STRING , BASE_NONE ) ;
2012-10-18 02:33:11 +00:00
syntax_table = g_hash_table_new ( g_str_hash , g_str_equal ) ; /* oid to syntax */
2009-10-17 21:42:51 +00:00
2010-06-23 11:28:59 +00:00
register_ber_syntax_dissector ( " ASN.1 " , proto_ber , dissect_ber_syntax ) ;
2009-10-17 21:42:51 +00:00
register_init_routine ( ber_defragment_init ) ;
2013-11-20 19:17:08 +00:00
register_decode_as ( & ber_da ) ;
2004-02-20 10:04:10 +00:00
}
void
proto_reg_handoff_ber ( void )
{
2012-04-23 17:43:56 +00:00
guint i = 1 ;
2006-05-08 19:56:36 +00:00
2012-10-18 02:33:11 +00:00
oid_add_from_string ( " asn1 " , " 2.1 " ) ;
oid_add_from_string ( " basic-encoding " , " 2.1.1 " ) ;
2006-05-08 19:56:36 +00:00
2012-04-23 17:43:56 +00:00
dissector_add_uint ( " wtap_encap " , WTAP_ENCAP_BER , ber_handle ) ;
2010-06-28 09:33:04 +00:00
2012-04-23 17:43:56 +00:00
ber_decode_as_foreach ( ber_add_syntax_name , & i ) ;
2010-07-07 15:52:09 +00:00
2012-10-18 02:33:11 +00:00
if ( i > 1 )
2012-04-23 17:43:56 +00:00
qsort ( & syntax_names [ 1 ] , i - 1 , sizeof ( value_string ) , cmp_value_string ) ;
syntax_names [ i ] . value = 0 ;
syntax_names [ i ] . strptr = NULL ;
2010-06-28 09:33:04 +00:00
2012-04-23 17:43:56 +00:00
/* allow the dissection of BER/DER carried over a TCP transport
by using " Decode As... " */
2014-06-20 16:43:28 +00:00
dissector_add_for_decode_as ( " tcp.port " , ber_handle ) ;
2010-06-28 09:33:04 +00:00
2012-04-23 17:43:56 +00:00
ber_update_oids ( ) ;
2006-11-04 09:14:54 +00:00
}
2014-09-28 23:25:09 +00:00
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 4
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* vi : set shiftwidth = 4 tabstop = 8 expandtab :
* : indentSize = 4 : tabSize = 8 : noTabs = true :
*/