2007-05-02 20:37:25 +00:00
/*#define DEBUG_BER 1*/
2004-10-30 01:54:40 +00:00
/* TODO: change #.REGISTER signature to new_dissector_t and
* update call_ber_oid_callback ( ) accordingly .
2005-06-22 09:58:46 +00:00
*
2005-11-26 04:16:40 +00:00
* Since we don ' t pass the TAG / LENGTH from the CHOICE / SEQUENCE / SEQUENCE OF /
2005-06-22 09:58:46 +00:00
* 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 .
2005-11-26 04:16:40 +00:00
*
2005-06-22 09:58:46 +00:00
* 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 .
2005-11-26 04:16:40 +00:00
*
2006-03-09 16:00:33 +00:00
* Originally we used a kludge - we set a global variable in the
2005-06-22 09:58:46 +00:00
* CHOICE / SEQUENCE [ OF ] / SET [ OF ] helpers to indicate to the next helper
* whether the length is indefinite or not .
2005-11-26 04:16:40 +00:00
* That had currently only been implemented for { SEQUENCE | SET } [ OF ] but not
2005-06-22 09:58:46 +00:00
* CHOICE .
2005-08-18 08:37:31 +00:00
*
2005-11-26 04:16:40 +00:00
* 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 .
2004-10-30 01:54:40 +00:00
*/
2005-08-18 08:37:31 +00:00
2004-02-20 10:04:10 +00:00
/* packet-ber.c
* Helpers for ASN .1 / BER dissection
* Ronnie Sahlberg ( C ) 2004
*
2004-07-18 00:24:25 +00:00
* $ Id $
2004-02-20 10:04:10 +00:00
*
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
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
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
*
*/
2004-03-25 09:18:03 +00:00
2004-02-20 10:04:10 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <string.h>
# include <ctype.h>
# include <glib.h>
# include <epan/packet.h>
# include <epan/strutil.h>
2005-04-28 09:54:03 +00:00
# include <epan/to_str.h>
2004-09-27 22:55:15 +00:00
# include <epan/prefs.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>
2007-05-03 19:56:13 +00:00
# include <epan/asn1.h>
2004-02-20 10:04:10 +00:00
# include "packet-ber.h"
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 ;
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 ;
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 ;
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 ;
2007-05-06 08:18:44 +00:00
static gint hf_ber_constructed_OCTETSTRING = - 1 ;
2008-11-29 11:17:34 +00:00
static gint hf_ber_no_oid = - 1 ;
static gint hf_ber_oid_not_implemented = - 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
static gint ett_ber_octet_string = - 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 ;
2004-02-20 10:04:10 +00:00
static gboolean show_internal_ber_fields = FALSE ;
2007-02-17 11:10:02 +00:00
static gboolean decode_octetstring_as_ber = FALSE ;
2007-07-05 13:14:25 +00:00
static gboolean decode_unexpected = FALSE ;
2004-02-20 10:04:10 +00:00
2007-01-13 12:59:27 +00:00
static gchar * decode_as_syntax = NULL ;
static gchar * ber_filename = NULL ;
2004-07-21 11:13:03 +00:00
static dissector_table_t ber_oid_dissector_table = NULL ;
2007-01-13 12:59:27 +00:00
static dissector_table_t ber_syntax_dissector_table = NULL ;
static GHashTable * syntax_table = NULL ;
2004-02-20 10:04:10 +00:00
static const value_string ber_class_codes [ ] = {
2005-12-14 20:45:15 +00:00
{ BER_CLASS_UNI , " UNIVERSAL " } ,
{ BER_CLASS_APP , " APPLICATION " } ,
{ BER_CLASS_CON , " CONTEXT " } ,
{ BER_CLASS_PRI , " PRIVATE " } ,
2004-02-20 10:04:10 +00:00
{ 0 , NULL }
} ;
static const true_false_string ber_pc_codes = {
" Constructed Encoding " ,
" Primitive Encoding "
} ;
2007-11-19 20:23:49 +00:00
static const true_false_string ber_pc_codes_short = {
" constructed " ,
" primitive "
} ;
2004-02-20 10:04:10 +00:00
static const value_string ber_uni_tag_codes [ ] = {
2007-07-05 13:14:25 +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 " } ,
2007-04-20 13:54:56 +00:00
/* UNIVERSAL 14-15
* Reserved for future editions of this
* Recommendation | International Standard
*/
2007-07-05 13:14:25 +00:00
{ 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 " } ,
2004-02-20 10:04:10 +00:00
{ 0 , NULL }
} ;
2007-06-12 21:29:27 +00:00
static const true_false_string ber_real_binary_vals = {
" Binary encoding " ,
" Decimal encoding "
} ;
static const true_false_string ber_real_decimal_vals = {
" SpecialRealValue " ,
" Decimal encoding "
} ;
2007-01-13 12:59:27 +00:00
typedef struct _da_data {
GHFunc func ;
gpointer user_data ;
} da_data ;
2004-02-20 10:04:10 +00:00
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_ )
{
return ;
}
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
{
dissector_add_string ( " ber.oid " , oid , dissector ) ;
2007-10-31 23:11:15 +00:00
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
{
dissector_handle_t dissector_handle ;
dissector_handle = create_dissector_handle ( dissector , proto ) ;
dissector_add_string ( " ber.oid " , oid , dissector_handle ) ;
2007-10-31 23:11:15 +00:00
oid_add_from_string ( name , oid ) ;
2004-07-23 07:08:14 +00:00
}
2005-06-07 05:49:06 +00:00
2007-01-13 12:59:27 +00:00
void
register_ber_syntax_dissector ( const char * syntax , int proto , dissector_t dissector )
{
dissector_handle_t dissector_handle ;
dissector_handle = create_dissector_handle ( dissector , proto ) ;
dissector_add_string ( " ber.syntax " , syntax , dissector_handle ) ;
}
void
register_ber_oid_syntax ( const char * oid , const char * name , const char * syntax )
{
if ( syntax & & * syntax )
2007-04-23 10:59:26 +00:00
g_hash_table_insert ( syntax_table , ( const gpointer ) oid , ( const gpointer ) syntax ) ;
2007-01-13 12:59:27 +00:00
if ( name & & * name )
register_ber_oid_name ( oid , name ) ;
}
/* Register the oid name to get translation in proto dissection */
void
register_ber_oid_name ( const char * oid , const char * name )
{
2007-10-31 23:11:15 +00:00
oid_add_from_string ( name , oid ) ;
2007-01-13 12:59:27 +00:00
}
2007-04-23 16:49:24 +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
{
da_data * decode_as_data ;
decode_as_data = ( da_data * ) user_data ;
decode_as_data - > func ( key , value , decode_as_data - > user_data ) ;
}
void ber_decode_as_foreach ( GHFunc func , gpointer user_data )
{
da_data decode_as_data ;
decode_as_data . func = func ;
decode_as_data . user_data = user_data ;
dissector_table_foreach ( " ber.syntax " , ber_decode_as_dt , & decode_as_data ) ;
}
2007-04-23 10:59:26 +00:00
void ber_decode_as ( const gchar * syntax )
2007-01-13 12:59:27 +00:00
{
if ( decode_as_syntax ) {
g_free ( decode_as_syntax ) ;
decode_as_syntax = NULL ;
}
if ( syntax )
decode_as_syntax = g_strdup ( syntax ) ;
}
/* Get oid syntax from hash table to get translation in proto dissection(packet-per.c) */
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 )
{
return g_hash_table_lookup ( syntax_table , oid ) ;
}
void ber_set_filename ( gchar * filename )
{
gchar * ptr ;
if ( ber_filename ) {
g_free ( ber_filename ) ;
ber_filename = NULL ;
}
if ( filename ) {
ber_filename = g_strdup ( filename ) ;
if ( ( ptr = strrchr ( ber_filename , ' . ' ) ) ! = NULL ) {
2007-04-23 10:59:26 +00:00
ber_decode_as ( get_ber_oid_syntax ( ptr ) ) ;
2007-01-13 12:59:27 +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
{
if ( min_len ! = - 1 & & length < ( guint32 ) min_len ) {
2010-01-05 11:38:33 +00:00
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: %sstring too short: %d (%d .. %d) " , bit ? " bit " : " " , length , min_len , max_len ) ;
2009-12-18 15:18:31 +00:00
} else if ( max_len ! = - 1 & & length > ( guint32 ) max_len ) {
2010-01-05 11:38:33 +00:00
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: %sstring too long: %d (%d .. %d) " , bit ? " bit " : " " , length , min_len , max_len ) ;
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 )
{
if ( min_len ! = - 1 & & value < min_len ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " 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 ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: value too big: % " G_GINT64_MODIFIER " d (% " G_GINT64_MODIFIER " d .. % " G_GINT64_MODIFIER " d) " , value , min_len , max_len ) ;
}
}
static void
ber_check_value ( guint32 value , gint32 min_len , gint32 max_len , asn1_ctx_t * actx , proto_item * item )
{
if ( min_len ! = - 1 & & value < ( guint32 ) min_len ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: value too small: %d (%d .. %d) " , value , min_len , max_len ) ;
} else if ( max_len ! = - 1 & & value > ( guint32 ) max_len ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: value too big: %d (%d .. %d) " , value , min_len , max_len ) ;
}
}
static void
ber_check_items ( int cnt , gint32 min_len , gint32 max_len , asn1_ctx_t * actx , proto_item * item )
{
if ( min_len ! = - 1 & & cnt < min_len ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: too few items: %d (%d .. %d) " , cnt , min_len , max_len ) ;
} else if ( max_len ! = - 1 & & cnt > max_len ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: too many items: %d (%d .. %d) " , cnt , min_len , max_len ) ;
}
}
2007-05-13 20:58:29 +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
{
gint8 tmp_cls ;
gint32 tmp_tag ;
guint32 tmp_len ;
tvbuff_t * next_tvb = tvb ;
2006-12-19 22:04:22 +00:00
proto_item * cause ;
2006-06-15 07:46:07 +00:00
2007-11-13 21:59:53 +00:00
# ifdef DEBUG_BER
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_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_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
} else {
printf ( " dissect_ber_tagged_type(%s) entered \n " , name ) ;
}
}
# endif
2006-06-15 07:46:07 +00:00
if ( implicit_tag ) {
2007-05-13 20:58:29 +00:00
offset = type ( tag_impl , tvb , offset , actx , tree , hf_id ) ;
2006-06-15 07:46:07 +00:00
return offset ;
}
2007-05-13 20:58:29 +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
2006-06-15 07:46:07 +00:00
if ( ( tmp_cls ! = tag_cls ) | | ( tmp_tag ! = tag_tag ) ) {
2006-12-19 22:04:22 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , tmp_len ,
2007-11-19 20:23:49 +00:00
" BER Error: Wrong tag in tagged type - expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d " ,
val_to_str ( tag_cls , ber_class_codes , " Unknown " ) , tag_cls , tag_tag , val_to_str ( tag_tag , ber_uni_tag_codes , " Unknown " ) ,
val_to_str ( tmp_cls , ber_class_codes , " Unknown " ) , tmp_cls , tmp_tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong tag in tagged type " ) ;
2006-06-15 07:46:07 +00:00
}
if ( tag_impl ) {
next_tvb = tvb_new_subset ( tvb , offset , tvb_length_remaining ( tvb , offset ) , tmp_len ) ;
2007-05-13 20:58:29 +00:00
type ( tag_impl , next_tvb , 0 , actx , tree , hf_id ) ;
2006-06-15 07:46:07 +00:00
offset + = tmp_len ;
} else {
2007-05-13 20:58:29 +00:00
offset = type ( tag_impl , tvb , offset , actx , tree , hf_id ) ;
2006-06-15 07:46:07 +00:00
}
return offset ;
}
2005-06-07 05:49:06 +00:00
int dissect_unknown_ber ( packet_info * pinfo , tvbuff_t * tvb , int offset , proto_tree * tree )
2004-11-18 10:46:27 +00:00
{
int start_offset ;
2005-07-09 02:58:07 +00:00
gint8 class ;
2004-11-18 10:46:27 +00:00
gboolean pc , ind ;
2005-07-09 02:58:07 +00:00
gint32 tag ;
2004-11-18 10:46:27 +00:00
guint32 len ;
2007-03-06 21:03:27 +00:00
int hdr_len ;
2004-11-25 22:27:52 +00:00
proto_item * item = NULL ;
proto_tree * next_tree = NULL ;
2005-12-14 20:45:15 +00:00
guint8 c ;
guint32 i ;
gboolean is_printable ;
2006-12-19 22:04:22 +00:00
proto_item * pi , * cause ;
2007-05-15 05:49:43 +00:00
asn1_ctx_t asn1_ctx ;
2004-11-18 10:46:27 +00:00
start_offset = offset ;
2007-05-15 05:49:43 +00:00
asn1_ctx_init ( & asn1_ctx , ASN1_ENC_BER , TRUE , pinfo ) ;
2004-11-18 10:46:27 +00:00
2005-11-26 04:16:40 +00:00
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind ) ;
2004-11-18 10:46:27 +00:00
2004-12-13 08:15:34 +00:00
if ( len > ( guint32 ) tvb_length_remaining ( tvb , offset ) ) {
2004-11-25 21:30:38 +00:00
/* hmm maybe something bad happened or the frame is short,
2006-03-09 16:00:33 +00:00
since these are not vital outputs just return instead of
2005-11-26 04:16:40 +00:00
throwing an exception .
2004-11-25 21:30:38 +00:00
*/
2005-12-14 20:45:15 +00:00
2006-09-22 17:39:02 +00:00
if ( show_internal_ber_fields ) {
offset = dissect_ber_identifier ( pinfo , tree , tvb , start_offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( pinfo , tree , tvb , offset , & len , NULL ) ;
}
2007-07-05 13:14:25 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: length:%u longer than tvb_length_ramaining:%d " , len , tvb_length_remaining ( tvb , offset ) ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error length " ) ;
2004-11-25 21:30:38 +00:00
return tvb_length ( tvb ) ;
}
2005-08-18 08:37:31 +00:00
/* we dont care about the class only on the constructor flag */
switch ( pc ) {
2005-12-14 20:45:15 +00:00
case FALSE : /* this is not constructed */
switch ( class ) { /* we do care about the class */
case BER_CLASS_UNI : /* it a Universal tag - we can decode it */
2004-11-25 22:27:52 +00:00
switch ( tag ) {
2005-12-14 20:45:15 +00:00
case BER_UNI_TAG_EOC :
/* XXX: shouldn't really get here */
break ;
2004-11-25 22:27:52 +00:00
case BER_UNI_TAG_INTEGER :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_integer ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_INTEGER , NULL ) ;
2004-11-25 22:27:52 +00:00
break ;
2005-12-14 20:45:15 +00:00
case BER_UNI_TAG_BITSTRING :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_bitstring ( FALSE , & asn1_ctx , tree , tvb , start_offset , NULL , hf_ber_unknown_BITSTRING , - 1 , NULL ) ;
2005-12-14 20:45:15 +00:00
break ;
2004-12-12 22:59:43 +00:00
case BER_UNI_TAG_ENUMERATED :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_integer ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_ENUMERATED , NULL ) ;
2004-12-12 22:59:43 +00:00
break ;
2005-06-24 10:03:20 +00:00
case BER_UNI_TAG_GraphicString :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_GraphicString , NULL ) ;
2005-06-24 10:03:20 +00:00
break ;
2004-11-25 22:27:52 +00:00
case BER_UNI_TAG_OCTETSTRING :
2007-02-17 11:10:02 +00:00
if ( decode_octetstring_as_ber ) {
int ber_offset ;
guint32 ber_len ;
ber_offset = get_ber_identifier ( tvb , offset , NULL , & pc , NULL ) ;
2007-08-24 07:12:04 +00:00
ber_offset = get_ber_length ( tvb , ber_offset , & ber_len , NULL ) ;
2010-01-20 12:47:26 +00:00
if ( pc & & ( ber_len > 0 ) & & ( ber_len + ( ber_offset - offset ) = = len ) ) {
2007-02-17 11:10:02 +00:00
/* Decoded a constructed ASN.1 tag with a length indicating this
* could be BER encoded data . Try dissecting as unknown BER .
*/
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 = proto_tree_add_item ( tree , hf_ber_unknown_BER_OCTETSTRING , tvb , offset , len , FALSE ) ;
next_tree = proto_item_add_subtree ( item , ett_ber_octet_string ) ;
offset = dissect_unknown_ber ( pinfo , tvb , offset , next_tree ) ;
} else {
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_OCTETSTRING , NULL ) ;
2007-02-17 11:10:02 +00:00
}
} else {
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_OCTETSTRING , NULL ) ;
2007-02-17 11:10:02 +00:00
}
2004-11-25 22:27:52 +00:00
break ;
case BER_UNI_TAG_OID :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_object_identifier_str ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_OID , NULL ) ;
2004-11-25 22:27:52 +00:00
break ;
2004-12-12 22:59:43 +00:00
case BER_UNI_TAG_NumericString :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_NumericString , NULL ) ;
2004-12-12 22:59:43 +00:00
break ;
2004-11-25 22:27:52 +00:00
case BER_UNI_TAG_PrintableString :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_PrintableString , NULL ) ;
2004-11-25 22:27:52 +00:00
break ;
2005-12-14 20:45:15 +00:00
case BER_UNI_TAG_TeletexString :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_TeletexString , NULL ) ;
2005-12-14 20:45:15 +00:00
break ;
2007-02-17 11:10:02 +00:00
case BER_UNI_TAG_VisibleString :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_VisibleString , NULL ) ;
2007-02-17 11:10:02 +00:00
break ;
case BER_UNI_TAG_GeneralString :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_GeneralString ( & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_GeneralString , NULL , 0 ) ;
2007-02-17 11:10:02 +00:00
break ;
2007-08-18 17:39:44 +00:00
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 ;
2004-11-25 22:27:52 +00:00
case BER_UNI_TAG_IA5String :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_IA5String , NULL ) ;
2004-11-25 22:27:52 +00:00
break ;
2005-12-14 20:45:15 +00:00
case BER_UNI_TAG_UTCTime :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_UTCTime , NULL ) ;
2005-12-14 20:45:15 +00:00
break ;
2005-10-27 11:27:40 +00:00
case BER_UNI_TAG_NULL :
proto_tree_add_text ( tree , tvb , offset , len , " NULL tag " ) ;
break ;
case BER_UNI_TAG_UTF8String :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_UTF8String , NULL ) ;
2005-10-27 11:27:40 +00:00
break ;
case BER_UNI_TAG_GeneralizedTime :
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_GeneralizedTime , NULL ) ;
2005-10-27 11:27:40 +00:00
break ;
case BER_UNI_TAG_BOOLEAN :
2008-01-04 16:21:07 +00:00
offset = dissect_ber_boolean ( FALSE , & asn1_ctx , tree , tvb , start_offset , hf_ber_unknown_BOOLEAN , NULL ) ;
2005-10-27 11:27:40 +00:00
break ;
2004-11-25 22:27:52 +00:00
default :
2005-11-26 04:16:40 +00:00
offset = dissect_ber_identifier ( pinfo , tree , tvb , start_offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( pinfo , tree , tvb , offset , & len , NULL ) ;
2007-07-05 13:14:25 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: can not handle universal tag:%d " , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: can not handle universal " ) ;
2004-11-25 22:27:52 +00:00
offset + = len ;
}
break ;
2005-12-14 20:45:15 +00:00
case BER_CLASS_APP :
case BER_CLASS_CON :
case BER_CLASS_PRI :
default :
/* we can't dissect this directly as it is specific */
2006-09-22 17:39:02 +00:00
/* we dissect again if show_internal_ber_fields is set */
if ( show_internal_ber_fields ) {
offset = dissect_ber_identifier ( pinfo , tree , tvb , start_offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( pinfo , tree , tvb , offset , & len , NULL ) ;
}
2005-12-14 20:45:15 +00:00
pi = proto_tree_add_text ( tree , tvb , offset , len , " [%s %d] " , val_to_str ( class , ber_class_codes , " Unknown " ) , tag ) ;
/* we may want to do better and show the bytes */
is_printable = TRUE ;
for ( i = 0 ; i < len ; i + + ) {
c = tvb_get_guint8 ( tvb , offset + i ) ;
if ( is_printable & & ! g_ascii_isprint ( c ) )
2006-03-09 16:00:33 +00:00
is_printable = FALSE ;
2005-12-14 20:45:15 +00:00
proto_item_append_text ( pi , " %02x " , c ) ;
}
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 ) ) ;
}
proto_item_append_text ( pi , " ) " ) ;
}
offset + = len ;
break ;
}
break ;
case TRUE : /* this is constructed */
2006-09-22 17:39:02 +00:00
/* we dissect again if show_internal_ber_fields is set */
if ( show_internal_ber_fields ) {
offset = dissect_ber_identifier ( pinfo , tree , tvb , start_offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( pinfo , tree , tvb , offset , & len , NULL ) ;
}
2007-03-06 21:03:27 +00:00
hdr_len = offset - start_offset ;
2005-12-14 20:45:15 +00:00
switch ( class ) {
case BER_CLASS_UNI :
item = proto_tree_add_text ( tree , tvb , offset , len , " %s " , val_to_str ( tag , ber_uni_tag_codes , " Unknown " ) ) ;
if ( item ) {
next_tree = proto_item_add_subtree ( item , ett_ber_SEQUENCE ) ;
}
2007-03-06 21:03:27 +00:00
while ( offset < ( int ) ( start_offset + len + hdr_len ) )
2005-12-14 20:45:15 +00:00
offset = dissect_unknown_ber ( pinfo , tvb , offset , next_tree ) ;
break ;
case BER_CLASS_APP :
case BER_CLASS_CON :
case BER_CLASS_PRI :
default :
item = proto_tree_add_text ( tree , tvb , offset , len , " [%s %d] " , val_to_str ( class , ber_class_codes , " Unknown " ) , tag ) ;
2004-11-25 22:27:52 +00:00
if ( item ) {
next_tree = proto_item_add_subtree ( item , ett_ber_SEQUENCE ) ;
}
2007-03-06 21:03:27 +00:00
while ( offset < ( int ) ( start_offset + len + hdr_len ) )
2005-12-14 20:45:15 +00:00
offset = dissect_unknown_ber ( pinfo , tvb , offset , next_tree ) ;
2004-11-25 22:27:52 +00:00
break ;
2004-11-18 10:46:27 +00:00
2005-12-14 20:45:15 +00:00
}
break ;
2004-11-18 10:46:27 +00:00
}
2004-11-25 22:27:52 +00:00
2004-11-18 10:46:27 +00:00
return offset ;
}
2004-07-20 09:11:40 +00:00
int
2005-08-05 13:10:58 +00:00
call_ber_oid_callback ( const char * oid , tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree )
2004-07-20 09:11:40 +00:00
{
2004-07-21 11:13:03 +00:00
tvbuff_t * next_tvb ;
2009-08-16 12:36:22 +00:00
next_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
2005-11-18 10:06:47 +00:00
if ( oid = = NULL | |
! dissector_try_string ( ber_oid_dissector_table , oid , next_tvb , pinfo , tree ) ) {
2004-11-25 21:30:38 +00:00
proto_item * item = NULL ;
proto_tree * next_tree = NULL ;
2007-08-15 22:34:56 +00:00
gint length_remaining ;
length_remaining = tvb_length_remaining ( tvb , offset ) ;
2004-11-25 21:30:38 +00:00
2006-12-19 22:04:22 +00:00
if ( oid = = NULL ) {
2008-11-29 11:17:34 +00:00
item = proto_tree_add_none_format ( tree , hf_ber_no_oid , next_tvb , 0 , length_remaining , " BER: No OID supplied to call_ber_oid_callback " ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( item , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( pinfo , item , PI_MALFORMED , PI_WARN , " BER Error: No OID supplied " ) ;
} else {
2008-11-29 11:17:34 +00:00
item = proto_tree_add_none_format ( tree , hf_ber_oid_not_implemented , next_tvb , 0 , length_remaining , " BER: Dissector for OID:%s not implemented. Contact Wireshark developers if you want this supported " , oid ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( item , PI_MALFORMED , PI_WARN ) ;
2009-02-06 13:48:32 +00:00
expert_add_info_format ( pinfo , item , PI_UNDECODED , PI_WARN , " BER: Dissector for OID %s not implemented " , oid ) ;
2006-12-19 22:04:22 +00:00
}
2007-08-15 22:34:56 +00:00
if ( decode_unexpected ) {
int ber_offset ;
gint32 ber_len ;
if ( item ) {
2004-11-25 21:30:38 +00:00
next_tree = proto_item_add_subtree ( item , ett_ber_unknown ) ;
2007-08-15 22:34:56 +00:00
}
ber_offset = get_ber_identifier ( next_tvb , 0 , NULL , NULL , NULL ) ;
2007-08-24 07:12:04 +00:00
ber_offset = get_ber_length ( next_tvb , ber_offset , & ber_len , NULL ) ;
2007-08-15 22:34:56 +00:00
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 .
*/
dissect_unknown_ber ( pinfo , next_tvb , 0 , next_tree ) ;
} else {
proto_tree_add_text ( next_tree , next_tvb , 0 , length_remaining ,
" Unknown Data (%d byte%s) " , length_remaining ,
plurality ( length_remaining , " " , " s " ) ) ;
}
2004-11-25 21:30:38 +00:00
}
2007-08-15 22:34:56 +00:00
2004-07-23 23:12:31 +00:00
}
2004-07-20 09:11:40 +00:00
2006-03-09 16:00:33 +00:00
/*XXX until we change the #.REGISTER signature for _PDU()s
2004-10-30 01:54:40 +00:00
* into new_dissector_t we have to do this kludge with
* manually step past the content in the ANY type .
*/
offset + = tvb_length_remaining ( tvb , offset ) ;
2004-07-20 09:11:40 +00:00
return offset ;
}
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 )
{
tvbuff_t * next_tvb ;
2009-08-16 12:36:22 +00:00
next_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
2007-01-13 12:59:27 +00:00
if ( syntax = = NULL | |
! dissector_try_string ( ber_syntax_dissector_table , syntax , next_tvb , pinfo , tree ) ) {
proto_item * item = NULL ;
proto_tree * next_tree = NULL ;
if ( syntax = = NULL )
2008-11-29 11:17:34 +00:00
item = proto_tree_add_none_format ( tree , hf_ber_no_oid , next_tvb , 0 , tvb_length_remaining ( tvb , offset ) , " BER: No syntax supplied to call_ber_syntax_callback " ) ;
2007-01-13 12:59:27 +00:00
else
2008-11-29 11:17:34 +00:00
item = proto_tree_add_none_format ( tree , hf_ber_oid_not_implemented , next_tvb , 0 , tvb_length_remaining ( tvb , offset ) , " BER: Dissector for syntax: %s not implemented. Contact Wireshark developers if you want this supported " , syntax ) ;
2007-01-13 12:59:27 +00:00
if ( item ) {
next_tree = proto_item_add_subtree ( item , ett_ber_unknown ) ;
}
dissect_unknown_ber ( pinfo , next_tvb , 0 , next_tree ) ;
}
/*XXX until we change the #.REGISTER signature for _PDU()s
* into new_dissector_t we have to do this kludge with
* manually step past the content in the ANY type .
*/
offset + = tvb_length_remaining ( tvb , offset ) ;
return offset ;
}
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 */
2004-12-13 08:15:34 +00:00
int get_ber_identifier ( tvbuff_t * tvb , int offset , gint8 * class , gboolean * pc , gint32 * tag ) {
2004-03-25 09:18:03 +00:00
guint8 id , t ;
2004-12-13 08:15:34 +00:00
gint8 tmp_class ;
2004-03-25 09:18:03 +00:00
gboolean tmp_pc ;
2004-12-13 08:15:34 +00:00
gint32 tmp_tag ;
2004-03-25 09:18:03 +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
2004-03-25 09:18:03 +00:00
/* 8.1.2.2 */
tmp_class = ( id > > 6 ) & 0x03 ;
tmp_pc = ( id > > 5 ) & 0x01 ;
tmp_tag = id & 0x1F ;
/* 8.1.2.4 */
if ( tmp_tag = = 0x1F ) {
tmp_tag = 0 ;
while ( tvb_length_remaining ( tvb , offset ) > 0 ) {
t = tvb_get_guint8 ( tvb , offset ) ;
2005-03-24 14:21:30 +00:00
# ifdef DEBUG_BER
printf ( " %02x " , t ) ;
# endif
2004-03-25 09:18:03 +00:00
offset + = 1 ;
2006-03-09 16:00:33 +00:00
tmp_tag < < = 7 ;
2004-03-25 09:18:03 +00:00
tmp_tag | = t & 0x7F ;
2005-03-24 14:21:30 +00:00
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
2004-03-25 09:18:03 +00:00
if ( class )
* class = tmp_class ;
if ( pc )
* pc = tmp_pc ;
if ( tag )
* tag = tmp_tag ;
return offset ;
}
2004-02-20 10:04:10 +00:00
2006-03-09 16:00:33 +00:00
int dissect_ber_identifier ( packet_info * pinfo _U_ , proto_tree * tree , tvbuff_t * tvb , int offset , gint8 * class , gboolean * pc , gint32 * tag )
2004-03-25 09:18:03 +00:00
{
int old_offset = offset ;
2004-12-13 08:15:34 +00:00
gint8 tmp_class ;
2004-03-25 09:18:03 +00:00
gboolean tmp_pc ;
2004-12-13 08:15:34 +00:00
gint32 tmp_tag ;
2004-03-25 09:18:03 +00:00
offset = get_ber_identifier ( tvb , offset , & tmp_class , & tmp_pc , & tmp_tag ) ;
2006-03-09 16:00:33 +00:00
2004-02-20 10:04:10 +00:00
if ( show_internal_ber_fields ) {
2004-03-25 09:18:03 +00:00
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 ) ;
2007-01-06 20:21:30 +00:00
if ( tmp_tag > 0x1F ) {
2005-09-18 16:54:00 +00:00
if ( tmp_class = = BER_CLASS_UNI ) {
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 ) ;
}
2004-02-20 10:04:10 +00:00
} else {
2005-09-18 16:54:00 +00:00
if ( tmp_class = = BER_CLASS_UNI ) {
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 ) ;
}
2004-02-20 10:04:10 +00:00
}
}
2005-08-18 08:37:31 +00:00
if ( class )
2004-03-25 09:18:03 +00:00
* class = tmp_class ;
2005-08-18 08:37:31 +00:00
if ( pc )
2004-03-25 09:18:03 +00:00
* pc = tmp_pc ;
2005-08-18 08:37:31 +00:00
if ( tag )
2004-03-25 09:18:03 +00:00
* tag = tmp_tag ;
2004-02-20 10:04:10 +00:00
return offset ;
}
2004-03-25 09:18:03 +00:00
/* this function gets the length octets of the BER TLV.
2004-02-20 10:04:10 +00:00
* We only handle ( TAGs and ) LENGTHs that fit inside 32 bit integers .
*/
2004-03-25 09:18:03 +00:00
/* 8.1.3 Length octets */
2004-02-20 10:04:10 +00:00
int
2007-08-24 07:12:04 +00:00
get_ber_length ( tvbuff_t * tvb , int offset , guint32 * length , gboolean * ind ) {
2004-03-25 09:18:03 +00:00
guint8 oct , len ;
2005-08-18 08:37:31 +00:00
guint32 tmp_len ;
2004-03-25 09:18:03 +00:00
guint32 tmp_length ;
gboolean tmp_ind ;
2005-08-18 08:37:31 +00:00
int tmp_offset , s_offset ;
gint8 tclass ;
gboolean tpc ;
gint32 ttag ;
2004-03-25 09:18:03 +00:00
tmp_length = 0 ;
tmp_ind = FALSE ;
2004-02-20 10:04:10 +00:00
2004-03-25 09:18:03 +00:00
oct = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
2006-03-09 16:00:33 +00:00
2005-08-18 08:37:31 +00:00
if ( ! ( oct & 0x80 ) ) {
2004-03-25 09:18:03 +00:00
/* 8.1.3.4 */
tmp_length = oct ;
} else {
len = oct & 0x7F ;
2005-08-18 08:37:31 +00:00
if ( len ) {
2004-03-25 09:18:03 +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 */
2006-03-09 16:00:33 +00:00
2005-08-18 08:37:31 +00:00
tmp_offset = offset ;
/* ok in here we can traverse the BER to find the length, this will fix most indefinite length issues */
2006-03-09 16:00:33 +00:00
/* Assumption here is that indefinite length is always used on constructed types*/
2005-08-18 08:37:31 +00:00
/* check for EOC */
2008-01-09 17:06:25 +00:00
while ( tvb_get_guint8 ( tvb , offset ) | | tvb_get_guint8 ( tvb , offset + 1 ) ) {
2005-08-23 08:01:46 +00:00
/* not an EOC at offset */
2005-08-18 08:37:31 +00:00
s_offset = offset ;
offset = get_ber_identifier ( tvb , offset , & tclass , & tpc , & ttag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & tmp_len , NULL ) ;
2005-08-18 08:37:31 +00:00
tmp_length + = tmp_len + ( offset - s_offset ) ; /* length + tag and length */
offset + = tmp_len ;
2006-07-05 21:33:01 +00:00
/* Make sure we've moved forward in the packet */
2006-07-09 22:12:02 +00:00
if ( offset < = s_offset )
THROW ( ReportedBoundsError ) ;
2008-01-09 17:06:25 +00:00
}
2006-03-09 16:00:33 +00:00
tmp_length + = 2 ;
2004-03-25 09:18:03 +00:00
tmp_ind = TRUE ;
2005-08-18 08:37:31 +00:00
offset = tmp_offset ;
2004-02-20 10:04:10 +00:00
}
}
2004-03-25 09:18:03 +00:00
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
printf ( " get BER length %d, offset %d (remaining %d) \n " , tmp_length , offset , tvb_length_remaining ( tvb , offset ) ) ;
# endif
2004-02-20 10:04:10 +00:00
return offset ;
}
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
{
2004-03-25 09:18:03 +00:00
int old_offset = offset ;
guint32 tmp_length ;
gboolean tmp_ind ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & tmp_length , & tmp_ind ) ;
2006-03-09 16:00:33 +00:00
2004-03-25 09:18:03 +00:00
if ( show_internal_ber_fields ) {
2004-10-16 12:53:09 +00:00
if ( tmp_ind ) {
2005-08-18 08:37:31 +00:00
proto_tree_add_text ( tree , tvb , old_offset , 1 , " Length: Indefinite length %d " , tmp_length ) ;
2004-10-16 12:53:09 +00:00
} else {
proto_tree_add_uint ( tree , hf_ber_length , tvb , old_offset , offset - old_offset , tmp_length ) ;
}
2004-03-25 09:18:03 +00:00
}
2005-08-18 08:37:31 +00:00
if ( length )
2004-03-25 09:18:03 +00:00
* length = tmp_length ;
2005-08-18 08:37:31 +00:00
if ( ind )
2004-03-25 09:18:03 +00:00
* ind = tmp_ind ;
2008-01-09 17:06:25 +00:00
# ifdef DEBUG_BER
printf ( " dissect BER length %d, offset %d (remaining %d) \n " , tmp_length , offset , tvb_length_remaining ( tvb , offset ) ) ;
# endif
2004-03-25 09:18:03 +00:00
return offset ;
}
2009-10-17 21:42:51 +00:00
static GHashTable * octet_segment_table = NULL ;
static GHashTable * octet_reassembled_table = NULL ;
static void ber_defragment_init ( void ) {
fragment_table_init ( & octet_segment_table ) ;
reassembled_table_init ( & octet_reassembled_table ) ;
}
2006-03-09 16:00:33 +00:00
static int
2007-05-15 05:49:43 +00:00
reassemble_octet_string ( asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , guint32 con_len , gboolean ind , tvbuff_t * * out_tvb )
2005-09-06 05:30:06 +00:00
{
fragment_data * fd_head = NULL ;
2005-09-20 17:23:19 +00:00
tvbuff_t * next_tvb = NULL ;
2005-09-06 05:30:06 +00:00
tvbuff_t * reassembled_tvb = NULL ;
guint16 dst_ref = 0 ;
int start_offset = offset ;
gboolean fragment = TRUE ;
gboolean firstFragment = TRUE ;
/* so we need to consume octet strings for the given length */
/* not sure we need this */
2007-05-15 05:49:43 +00:00
actx - > pinfo - > fragmented = TRUE ;
2005-09-06 05:30:06 +00:00
while ( ! fd_head ) {
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( FALSE , actx , tree , tvb , offset , hf_ber_constructed_OCTETSTRING , & next_tvb ) ;
2005-09-06 05:30:06 +00:00
2005-09-07 15:40:59 +00:00
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
2005-09-06 05:30:06 +00:00
if ( ind ) {
/* this was indefinite length - so check for EOC */
2006-03-09 16:00:33 +00:00
2005-09-06 05:30:06 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
fragment = FALSE ;
/* skip past EOC */
offset + = 2 ;
}
} else {
2006-03-09 16:00:33 +00:00
2005-09-21 01:47:46 +00:00
if ( ( guint32 ) ( offset - start_offset ) > = con_len )
2005-09-06 05:30:06 +00:00
fragment = FALSE ;
}
if ( ! fragment & & firstFragment ) {
/* there is only one fragment (I'm sure there's a reason it was constructed) */
/* anyway, we can get out of here */
reassembled_tvb = next_tvb ;
break ;
}
2005-09-20 17:23:19 +00:00
if ( tvb_length ( next_tvb ) < 1 ) {
/* Don't cause an assertion in the reassembly code. */
THROW ( ReportedBoundsError ) ;
}
2007-05-15 05:49:43 +00:00
fd_head = fragment_add_seq_next ( next_tvb , 0 , actx - > pinfo , dst_ref ,
2005-09-06 05:30:06 +00:00
octet_segment_table ,
octet_reassembled_table ,
tvb_length ( next_tvb ) ,
fragment ) ;
firstFragment = FALSE ;
}
if ( fd_head ) {
if ( fd_head - > next ) {
2009-05-13 19:46:11 +00:00
reassembled_tvb = tvb_new_child_real_data ( next_tvb , fd_head - > data ,
2005-09-06 05:30:06 +00:00
fd_head - > len ,
fd_head - > len ) ;
/* not sure I really want to do this here - should be nearer the application where we can give it a better name*/
2007-05-15 05:49:43 +00:00
add_new_data_source ( actx - > pinfo , reassembled_tvb , " Reassembled OCTET STRING " ) ;
2005-09-06 05:30:06 +00:00
}
}
if ( out_tvb )
* out_tvb = reassembled_tvb ;
/* again - not sure we need this */
2007-05-15 05:49:43 +00:00
actx - > pinfo - > fragmented = FALSE ;
2006-03-09 16:00:33 +00:00
2005-09-06 05:30:06 +00:00
return offset ;
}
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 ) {
2005-07-09 02:58:07 +00:00
gint8 class ;
2004-03-25 09:18:03 +00:00
gboolean pc , ind ;
2005-07-09 02:58:07 +00:00
gint32 tag ;
2004-02-20 10:04:10 +00:00
guint32 len ;
2007-07-05 13:14:25 +00:00
int hoffset ;
2004-02-20 10:04:10 +00:00
int end_offset ;
2006-12-19 22:04:22 +00:00
proto_item * it , * cause ;
2005-03-24 14:21:30 +00:00
guint32 i ;
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 ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_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_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
} else {
printf ( " OCTET STRING dissect_ber_octet_string(%s) entered \n " , name ) ;
}
}
# endif
2004-02-20 10:04:10 +00:00
2004-03-25 09:18:03 +00:00
if ( ! implicit_tag ) {
2007-07-05 13:14:25 +00:00
hoffset = offset ;
2004-11-14 05:10:44 +00:00
/* read header and len for the octet string */
2007-05-15 05:49:43 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , & ind ) ;
2004-11-14 05:10:44 +00:00
end_offset = offset + len ;
2005-09-14 16:04:59 +00:00
2004-11-14 05:10:44 +00:00
/* sanity check: we only handle Constructed Universal Sequences */
2005-06-07 05:49:06 +00:00
if ( ( class ! = BER_CLASS_APP ) & & ( class ! = BER_CLASS_PRI ) )
2006-03-09 16:00:33 +00:00
if ( ( class ! = BER_CLASS_UNI )
2004-11-14 08:50:37 +00:00
| | ( ( tag < BER_UNI_TAG_NumericString ) & & ( tag ! = BER_UNI_TAG_OCTETSTRING ) & & ( tag ! = BER_UNI_TAG_UTF8String ) ) ) {
2007-07-05 13:14:25 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: OctetString expected but class:%s(%d) %s tag:%d was unexpected " , val_to_str ( class , ber_class_codes , " Unknown " ) , class , pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-15 05:49:43 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: OctetString expected " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2005-03-30 09:18:25 +00:00
if ( out_tvb )
2005-01-30 17:48:18 +00:00
* out_tvb = NULL ;
2004-03-25 09:18:03 +00:00
return end_offset ;
}
2004-11-14 05:10:44 +00:00
} else {
/* implicit tag so just trust the length of the tvb */
pc = FALSE ;
len = tvb_length_remaining ( tvb , offset ) ;
end_offset = offset + len ;
2006-03-09 16:00:33 +00:00
}
2004-02-20 10:04:10 +00:00
2008-01-04 13:39:24 +00:00
actx - > created_item = NULL ;
2007-05-30 19:00:50 +00:00
2004-03-25 09:18:03 +00:00
if ( pc ) {
/* constructed */
2007-05-15 05:49:43 +00:00
end_offset = reassemble_octet_string ( actx , tree , tvb , offset , len , ind , out_tvb ) ;
2004-03-25 09:18:03 +00:00
} else {
/* primitive */
2006-03-14 07:47:19 +00:00
gint length_remaining ;
length_remaining = tvb_length_remaining ( tvb , offset ) ;
2007-01-14 20:54:39 +00:00
#if 0
2006-03-14 07:47:19 +00:00
if ( length_remaining < 1 ) {
2006-03-17 11:46:07 +00:00
if ( out_tvb )
* out_tvb = NULL ;
2006-03-14 07:47:19 +00:00
return end_offset ;
}
2007-01-14 20:54:39 +00:00
# endif
2005-09-21 01:47:46 +00:00
if ( len < = ( guint32 ) length_remaining ) {
length_remaining = len ;
}
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2005-09-21 01:47:46 +00:00
it = proto_tree_add_item ( tree , hf_id , tvb , offset , length_remaining , FALSE ) ;
2008-01-04 13:39:24 +00:00
actx - > created_item = it ;
2010-01-05 11:38:33 +00:00
ber_check_length ( length_remaining , min_len , max_len , actx , it , FALSE ) ;
2005-03-24 14:21:30 +00:00
} else {
2005-09-21 01:47:46 +00:00
proto_item * pi ;
2006-03-09 16:00:33 +00:00
2005-09-21 01:47:46 +00:00
pi = proto_tree_add_text ( tree , tvb , offset , len , " Unknown OctetString: Length: 0x%02x, Value: 0x " , len ) ;
if ( pi ) {
for ( i = 0 ; i < len ; i + + ) {
proto_item_append_text ( pi , " %02x " , tvb_get_guint8 ( tvb , offset ) ) ;
offset + + ;
}
}
}
2005-09-14 16:04:59 +00:00
2005-08-18 08:37:31 +00:00
if ( out_tvb ) {
2005-09-21 01:47:46 +00:00
* out_tvb = tvb_new_subset ( tvb , offset , length_remaining , len ) ;
2004-03-25 09:18:03 +00:00
}
2004-02-20 10:04:10 +00:00
}
return end_offset ;
}
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 ) ;
}
2007-05-15 05:49:43 +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
{
2005-04-13 21:20:23 +00:00
tvbuff_t * out_tvb = NULL ;
2004-03-25 09:18:03 +00:00
2007-05-15 05:49:43 +00:00
offset = dissect_ber_octet_string ( implicit_tag , actx , tree , tvb , offset , hf_id , ( func ) ? & out_tvb : NULL ) ;
2005-04-13 21:20:23 +00:00
if ( func & & out_tvb & & ( tvb_length ( out_tvb ) > 0 ) ) {
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 )
2008-01-04 13:39:24 +00:00
tree = proto_item_add_subtree ( actx - > created_item , ett_ber_octet_string ) ;
2007-05-22 16:17:54 +00:00
/* TODO Should hf_id2 be pased as last parameter???*/
func ( FALSE , out_tvb , 0 , actx , tree , - 1 ) ;
2004-03-25 09:18:03 +00:00
}
return offset ;
}
2007-05-22 16:17:54 +00:00
int dissect_ber_old_octet_string_wcb ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * tree , tvbuff_t * tvb , int offset , gint hf_id , ber_old_callback func )
{
tvbuff_t * out_tvb = NULL ;
offset = dissect_ber_octet_string ( implicit_tag , actx , tree , tvb , offset , hf_id , ( func ) ? & out_tvb : NULL ) ;
if ( func & & out_tvb & & ( tvb_length ( out_tvb ) > 0 ) ) {
if ( hf_id > = 0 )
2008-01-04 13:39:24 +00:00
tree = proto_item_add_subtree ( actx - > created_item , ett_ber_octet_string ) ;
2007-05-22 16:17:54 +00:00
/* TODO Should hf_id2 be pased as last parameter???*/
func ( tree , out_tvb , 0 , actx ) ;
}
return offset ;
}
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 ) {
2005-07-09 02:58:07 +00:00
gint8 class ;
2005-04-27 14:17:14 +00:00
gboolean pc ;
2005-07-09 02:58:07 +00:00
gint32 tag ;
guint32 len ;
2005-04-27 14:17:14 +00:00
int offset_old ;
2006-12-19 22:04:22 +00:00
proto_item * cause ;
2005-08-18 08:37:31 +00:00
if ( ! implicit_tag )
{
2006-03-09 16:00:33 +00:00
offset_old = offset ;
2007-05-15 05:49:43 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & class , & pc , & tag ) ;
2005-08-18 08:37:31 +00:00
if ( ( pc ) | |
( ! implicit_tag & & ( ( class ! = BER_CLASS_UNI ) | | ( tag ! = BER_UNI_TAG_NULL ) ) ) ) {
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset_old , offset - offset_old , " BER Error: NULL expected but class:%s(%d) %s tag:%d was unexpected " , val_to_str ( class , ber_class_codes , " Unknown " ) , class , pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-15 05:49:43 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: NULL expected " ) ;
2005-04-27 14:17:14 +00:00
}
2006-03-09 16:00:33 +00:00
offset_old = offset ;
2007-05-15 05:49:43 +00:00
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
2005-08-18 08:37:31 +00:00
if ( len ) {
proto_tree_add_text ( tree , tvb , offset_old , offset - offset_old , " BER Error: NULL expect zero length but Length=%d " , len ) ;
2006-12-19 22:04:22 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: unexpected data in NULL type " ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-15 05:49:43 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: NULL expect zero length " ) ;
2005-08-18 08:37:31 +00:00
offset + = len ;
}
}
2005-09-14 17:04:36 +00:00
if ( hf_id > = 0 )
proto_tree_add_item ( tree , hf_id , tvb , offset , 0 , FALSE ) ;
2005-04-27 14:17:14 +00:00
return offset ;
}
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
{
2005-11-26 04:16:40 +00:00
gint8 class ;
2004-02-20 10:04:10 +00:00
gboolean pc ;
2005-11-26 04:16:40 +00:00
gint32 tag ;
2004-02-20 10:04:10 +00:00
guint32 len ;
2006-02-28 09:39:53 +00:00
gint64 val ;
2004-02-20 10:04:10 +00:00
guint32 i ;
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 ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( tvb , offset ) > 3 ) {
2004-12-12 01:14:03 +00:00
printf ( " INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x \n " , name , implicit_tag , offset , tvb_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2004-11-14 05:10:44 +00:00
} else {
2005-06-07 05:49:06 +00:00
printf ( " INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d \n " , name , implicit_tag ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2004-11-13 14:16:06 +00:00
if ( ! implicit_tag ) {
2007-05-15 05:49:43 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
2004-11-13 14:16:06 +00:00
} else {
2006-03-07 15:22:57 +00:00
gint32 remaining = tvb_length_remaining ( tvb , offset ) ;
len = remaining > 0 ? remaining : 0 ;
2004-11-13 14:16:06 +00:00
}
2004-06-24 05:31:21 +00:00
2006-02-28 09:39:53 +00:00
/* we cant handle integers > 64 bits */
2004-06-24 05:31:21 +00:00
if ( len > 8 ) {
2004-07-29 08:41:51 +00:00
header_field_info * hfinfo ;
2005-09-01 19:35:23 +00:00
proto_item * pi = NULL ;
2004-07-29 08:41:51 +00:00
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
pi = proto_tree_add_text ( tree , tvb , offset , len , " %s : 0x " , hfinfo - > name ) ;
}
2004-07-29 08:41:51 +00:00
if ( pi ) {
for ( i = 0 ; i < len ; i + + ) {
2004-09-25 02:44:45 +00:00
proto_item_append_text ( pi , " %02x " , tvb_get_guint8 ( tvb , offset ) ) ;
offset + + ;
2004-07-29 08:41:51 +00:00
}
2005-09-01 19:35:23 +00:00
} else {
offset + = len ;
2004-07-29 08:41:51 +00:00
}
2004-09-25 02:44:45 +00:00
return offset ;
2004-06-24 05:31:21 +00:00
}
2006-03-09 16:00:33 +00:00
2004-02-20 10:04:10 +00:00
val = 0 ;
2005-08-18 08:37:31 +00:00
if ( len > 0 ) {
2004-03-25 09:18:03 +00:00
/* extend sign bit */
2006-02-28 09:39:53 +00:00
if ( tvb_get_guint8 ( tvb , offset ) & 0x80 ) {
val = - 1 ;
}
for ( i = 0 ; i < len ; i + + ) {
val = ( val < < 8 ) | tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
}
2004-02-20 10:04:10 +00:00
}
2008-01-04 13:39:24 +00:00
actx - > created_item = NULL ;
2004-02-20 10:04:10 +00:00
2006-03-09 16:00:33 +00:00
if ( hf_id > = 0 ) {
2005-04-14 20:16:35 +00:00
/* */
2006-02-28 09:39:53 +00:00
if ( len < 1 | | len > 8 ) {
2005-04-14 20:16:35 +00:00
proto_tree_add_text ( tree , tvb , offset - len , len , " Can't handle integer length: %u " , len ) ;
} else {
2006-02-28 09:39:53 +00:00
header_field_info * hfi ;
hfi = proto_registrar_get_nth ( hf_id ) ;
switch ( hfi - > type ) {
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
2007-07-26 14:00:48 +00:00
actx - > created_item = proto_tree_add_uint ( tree , hf_id , tvb , offset - len , len , ( guint32 ) val ) ;
2006-02-28 09:39:53 +00:00
break ;
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2007-07-26 14:00:48 +00:00
actx - > created_item = proto_tree_add_int ( tree , hf_id , tvb , offset - len , len , ( gint32 ) val ) ;
2006-02-28 09:39:53 +00:00
break ;
case FT_INT64 :
2007-07-26 14:00:48 +00:00
actx - > created_item = proto_tree_add_int64 ( tree , hf_id , tvb , offset - len , len , val ) ;
2006-02-28 09:39:53 +00:00
break ;
case FT_UINT64 :
2007-07-26 14:00:48 +00:00
actx - > created_item = proto_tree_add_uint64 ( tree , hf_id , tvb , offset - len , len , ( guint64 ) val ) ;
2006-02-28 09:39:53 +00:00
break ;
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
2005-04-14 20:16:35 +00:00
}
2004-02-20 10:04:10 +00:00
}
2009-12-18 15:18:31 +00:00
if ( value ) {
* value = val ;
}
return offset ;
}
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 )
{
gint64 val ;
offset = dissect_ber_integer64 ( implicit_tag , actx , tree , tvb , offset , hf_id , & val ) ;
2004-02-20 10:04:10 +00:00
if ( value ) {
* value = val ;
}
2009-12-18 15:18:31 +00:00
ber_check_value64 ( val , min_len , max_len , actx , actx - > created_item ) ;
2004-02-20 10:04:10 +00:00
return offset ;
}
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
{
gint64 val ;
2007-05-15 05:49:43 +00:00
offset = dissect_ber_integer64 ( implicit_tag , actx , tree , tvb , offset , hf_id , & val ) ;
2006-02-28 09:39:53 +00:00
if ( value ) {
* value = ( guint32 ) val ;
}
return offset ;
}
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 )
{
gint64 val ;
offset = dissect_ber_integer64 ( implicit_tag , actx , tree , tvb , offset , hf_id , & val ) ;
if ( value ) {
* value = ( guint32 ) val ;
}
ber_check_value ( ( guint32 ) val , min_len , max_len , actx , actx - > created_item ) ;
return offset ;
}
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
{
2005-11-26 04:16:40 +00:00
gint8 class ;
2004-02-20 10:04:10 +00:00
gboolean pc ;
2005-11-26 04:16:40 +00:00
gint32 tag ;
2004-02-20 10:04:10 +00:00
guint32 len ;
guint8 val ;
2004-03-25 09:18:03 +00:00
header_field_info * hfi ;
2004-02-20 10:04:10 +00:00
2005-02-23 08:57:47 +00:00
if ( ! implicit_tag ) {
2007-05-15 05:49:43 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
2005-02-23 08:57:47 +00:00
/*if(class!=BER_CLASS_UNI)*/
} else {
/* nothing to do here, yet */
}
2006-03-09 16:00:33 +00:00
2004-02-20 10:04:10 +00:00
val = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
2008-01-04 13:39:24 +00:00
actx - > created_item = NULL ;
2004-02-20 10:04:10 +00:00
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-03-25 09:18:03 +00:00
hfi = proto_registrar_get_nth ( hf_id ) ;
2005-08-18 08:37:31 +00:00
if ( hfi - > type = = FT_BOOLEAN )
2008-01-04 13:39:24 +00:00
actx - > created_item = proto_tree_add_boolean ( tree , hf_id , tvb , offset - 1 , 1 , val ) ;
2004-03-25 09:18:03 +00:00
else
2008-01-04 13:39:24 +00:00
actx - > created_item = proto_tree_add_uint ( tree , hf_id , tvb , offset - 1 , 1 , val ? 1 : 0 ) ;
2004-02-20 10:04:10 +00:00
}
2006-06-29 21:04:37 +00:00
if ( value ) {
* value = ( val ? TRUE : FALSE ) ;
}
2004-02-20 10:04:10 +00:00
return offset ;
}
2007-06-12 21:29:27 +00:00
/* 8.5 Encoding of a real value */
2008-01-18 05:55:24 +00:00
/* NOT 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
{
gint8 class ;
gboolean pc ;
gint32 tag ;
2008-01-18 05:55:24 +00:00
guint32 val_length , end_offset ;
double val = 0 ;
2004-02-20 10:04:10 +00:00
2007-06-12 21:29:27 +00:00
if ( ! implicit_tag ) {
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & class , & pc , & tag ) ;
2008-01-18 05:55:24 +00:00
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & val_length , NULL ) ;
2007-06-12 21:29:27 +00:00
} else {
/* 8.5.1 The encoding of a real value shall be primitive. */
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
/* 8.5.2 If the real value is the value zero,
* there shall be no contents octets in the encoding .
*/
2008-01-18 05:55:24 +00:00
if ( val_length = = 0 ) {
2007-06-12 21:29:27 +00:00
if ( value )
* value = 0 ;
return offset ;
}
2008-01-18 05:55:24 +00:00
end_offset = offset + val_length ;
val = asn1_get_real ( tvb_get_ptr ( tvb , offset , val_length ) , val_length ) ;
actx - > created_item = proto_tree_add_double ( tree , hf_id , tvb , offset , val_length , val ) ;
if ( value ) * value = val ;
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
*/
2007-05-13 20:58:29 +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 ) {
2008-06-27 04:52:56 +00:00
gint8 classx ;
gboolean pcx , ind = 0 , ind_field , imp_tag = FALSE ;
gint32 tagx ;
guint32 lenx ;
2004-03-25 09:18:03 +00:00
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
2006-12-19 22:04:22 +00:00
proto_item * cause ;
2007-08-24 10:20:22 +00:00
int end_offset = 0 ;
int s_offset ;
2007-07-05 13:14:25 +00:00
int hoffset ;
2005-08-28 17:57:30 +00:00
gint length_remaining ;
2004-07-23 23:06:38 +00:00
tvbuff_t * next_tvb ;
2005-11-26 04:16:40 +00:00
s_offset = offset ;
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 ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( tvb , offset ) > 3 ) {
2005-08-18 08:37:31 +00:00
printf ( " SEQUENCE dissect_ber_sequence(%s) entered offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2004-11-14 05:10:44 +00:00
} else {
2005-08-18 08:37:31 +00:00
printf ( " SEQUENCE dissect_ber_sequence(%s) entered \n " , name ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2007-08-24 08:12:39 +00:00
hoffset = offset ;
if ( ! implicit_tag ) {
offset = get_ber_identifier ( tvb , offset , NULL , NULL , NULL ) ;
2008-06-27 04:52:56 +00:00
offset = get_ber_length ( tvb , offset , & lenx , NULL ) ;
2007-08-24 08:12:39 +00:00
} else {
/* was implicit tag so just use the length of the tvb */
2008-06-27 04:52:56 +00:00
lenx = tvb_length_remaining ( tvb , offset ) ;
end_offset = offset + lenx ;
2007-08-24 08:12:39 +00:00
}
/* create subtree */
if ( hf_id > = 0 ) {
if ( parent_tree ) {
2008-06-27 04:52:56 +00:00
item = proto_tree_add_item ( parent_tree , hf_id , tvb , hoffset , lenx + offset - hoffset , FALSE ) ;
2007-08-24 08:12:39 +00:00
tree = proto_item_add_subtree ( item , ett_id ) ;
}
}
offset = hoffset ;
2004-11-14 05:10:44 +00:00
if ( ! implicit_tag ) {
/* first we must read the sequence header */
2008-06-27 04:52:56 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & classx , & pcx , & tagx ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & lenx , & ind ) ;
2004-11-14 05:10:44 +00:00
if ( ind ) {
2005-08-18 08:37:31 +00:00
/* Fixed the length is correctly returned from dissect ber_length
end_offset = tvb_length ( tvb ) ; */
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx - 2 ;
2004-11-14 05:10:44 +00:00
} else {
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx ;
2004-11-14 05:10:44 +00:00
}
2004-02-20 10:04:10 +00:00
2004-11-14 05:10:44 +00:00
/* sanity check: we only handle Constructed Universal Sequences */
2008-06-27 04:52:56 +00:00
if ( ( classx ! = BER_CLASS_APP ) & & ( classx ! = BER_CLASS_PRI ) )
if ( ( ! pcx )
| | ( ! implicit_tag & & ( ( classx ! = BER_CLASS_UNI )
| | ( tagx ! = BER_UNI_TAG_SEQUENCE ) ) ) ) {
2007-07-05 13:14:25 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2008-06-27 04:52:56 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , lenx , " BER Error: Sequence expected but class:%s(%d) %s tag:%d was unexpected " , val_to_str ( classx , ber_class_codes , " Unknown " ) , classx , pcx ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tagx ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Sequence expected " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2004-11-14 05:10:44 +00:00
return end_offset ;
}
2004-02-20 10:04:10 +00:00
}
/* loop over all entries until we reach the end of the sequence */
2004-03-25 09:18:03 +00:00
while ( offset < end_offset ) {
2004-12-13 08:15:34 +00:00
gint8 class ;
2004-02-20 10:04:10 +00:00
gboolean pc ;
2004-12-13 08:15:34 +00:00
gint32 tag ;
2004-02-20 10:04:10 +00:00
guint32 len ;
2007-07-05 13:14:25 +00:00
int eoffset , count ;
2005-08-18 08:37:31 +00:00
/*if(ind){ this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2007-05-22 21:15:00 +00:00
but ber dissector uses this to eat the tag length then pass into here . . . EOC still on there . . . */
2005-08-18 08:37:31 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
2006-09-24 21:04:53 +00:00
/* If the first bytes is 00 00 of a indefenert length field it's a zero length field*/
2007-05-13 20:58:29 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , & ind ) ;
2006-09-24 21:04:53 +00:00
proto_item_append_text ( item , " 0 items " ) ;
return end_offset ;
/*
2005-08-18 08:37:31 +00:00
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , s_offset , offset + 2 , " ERROR WRONG SEQ EOC " ) ;
}
return end_offset ;
2006-09-24 21:04:53 +00:00
*/
2005-08-18 08:37:31 +00:00
}
/*}*/
hoffset = offset ;
/* read header and len for next field */
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind_field ) ;
2005-08-18 08:37:31 +00:00
eoffset = offset + len ;
2006-07-07 20:11:06 +00:00
/* Make sure we move forward */
2006-07-09 22:12:02 +00:00
if ( eoffset < = hoffset )
THROW ( ReportedBoundsError ) ;
2005-08-18 08:37:31 +00:00
2006-09-24 21:04:53 +00:00
/*if(ind_field && (len == 2)){
/ disgusting indefinite length zero length field , what are these people doing /
2006-06-09 21:09:57 +00:00
offset = eoffset ;
continue ;
}
2006-09-24 21:04:53 +00:00
*/
2006-06-09 21:09:57 +00:00
2005-08-18 08:37:31 +00:00
ber_sequence_try_again :
/* have we run out of known entries in the sequence ?*/
if ( ! seq - > func ) {
2005-11-26 04:16:40 +00:00
/* it was not, move to the next one and try again */
2007-05-13 20:58:29 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , NULL , NULL ) ;
2006-12-19 22:04:22 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: This field lies beyond the end of the known sequence definition. " ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Unknown field in Sequence " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2005-08-18 08:37:31 +00:00
offset = eoffset ;
continue ;
}
/* Verify that this one is the one we want.
* Skip check completely if class = = ANY
* of if NOCHKTAG is set
*/
/* 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
*/
if ( ( ( seq - > class = = BER_CLASS_CON ) | | ( seq - > class = = BER_CLASS_APP ) | | ( seq - > class = = BER_CLASS_PRI ) ) & & ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) ) ) {
2006-03-09 16:00:33 +00:00
if ( ( seq - > class ! = BER_CLASS_ANY )
& & ( seq - > tag ! = - 1 )
2005-08-18 08:37:31 +00:00
& & ( ( seq - > class ! = class )
| | ( seq - > tag ! = tag ) ) ) {
2005-08-22 05:49:09 +00:00
/* it was not, move to the next one and try again */
2005-08-18 08:37:31 +00:00
if ( seq - > flags & BER_FLAGS_OPTIONAL ) {
/* well this one was optional so just skip to the next one and try again. */
seq + + ;
goto ber_sequence_try_again ;
}
2007-05-13 20:58:29 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , NULL , NULL ) ;
2006-12-19 22:04:22 +00:00
if ( seq - > class = = BER_CLASS_UNI ) {
cause = proto_tree_add_text ( tree , tvb , offset , len ,
2007-11-19 20:23:49 +00:00
" BER Error: Wrong field in SEQUENCE expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d " ,
val_to_str ( seq - > class , ber_class_codes , " Unknown " ) , seq - > class ,
2005-08-18 08:37:31 +00:00
seq - > tag , val_to_str ( seq - > tag , ber_uni_tag_codes , " Unknown " ) ,
2007-11-19 20:23:49 +00:00
val_to_str ( class , ber_class_codes , " Unknown " ) , class , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in SEQUENCE " ) ;
2005-08-18 08:37:31 +00:00
} else {
2006-12-19 22:04:22 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len ,
2007-11-19 20:23:49 +00:00
" BER Error: Wrong field in SEQUENCE expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d " ,
val_to_str ( seq - > class , ber_class_codes , " Unknown " ) , seq - > class ,
seq - > tag , val_to_str ( class , ber_class_codes , " Unknown " ) , class , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in SEQUENCE " ) ;
2005-08-18 08:37:31 +00:00
}
2007-07-05 13:14:25 +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 ) ;
}
2005-08-18 08:37:31 +00:00
seq + + ;
offset = eoffset ;
continue ;
}
} else if ( ! ( seq - > flags & BER_FLAGS_NOTCHKTAG ) ) {
2006-03-09 16:00:33 +00:00
if ( ( seq - > class ! = BER_CLASS_ANY )
& & ( seq - > tag ! = - 1 )
2005-08-18 08:37:31 +00:00
& & ( ( seq - > class ! = class )
| | ( seq - > tag ! = tag ) ) ) {
2005-11-26 04:16:40 +00:00
/* it was not, move to the next one and try again */
2005-08-18 08:37:31 +00:00
if ( seq - > flags & BER_FLAGS_OPTIONAL ) {
/* well this one was optional so just skip to the next one and try again. */
seq + + ;
goto ber_sequence_try_again ;
}
2007-05-13 20:58:29 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , NULL , NULL ) ;
2005-08-18 08:37:31 +00:00
if ( seq - > class = = BER_CLASS_UNI ) {
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: Wrong field in sequence expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d " , val_to_str ( seq - > class , ber_class_codes , " Unknown " ) , seq - > class , seq - > tag , val_to_str ( seq - > tag , ber_uni_tag_codes , " Unknown " ) , val_to_str ( class , ber_class_codes , " Unknown " ) , class , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in sequence " ) ;
2005-08-18 08:37:31 +00:00
} else {
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: Wrong field in sequence expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d " , val_to_str ( seq - > class , ber_class_codes , " Unknown " ) , seq - > class , seq - > tag , val_to_str ( class , ber_class_codes , " Unknown " ) , class , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in sequence " ) ;
2005-08-18 08:37:31 +00:00
}
2007-07-05 13:14:25 +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 ) ;
}
2005-08-18 08:37:31 +00:00
seq + + ;
offset = eoffset ;
continue ;
}
}
if ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) ) {
/* dissect header and len for field */
2006-09-24 21:04:53 +00:00
if ( ind_field & & ( len = = 2 ) ) {
/* This is a Zero length field */
next_tvb = tvb_new_subset ( tvb , offset , len , len ) ;
hoffset = eoffset ;
} else {
2007-05-13 20:58:29 +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 ) ;
2006-09-24 21:04:53 +00:00
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > eoffset - hoffset - ( 2 * ind_field ) )
length_remaining = eoffset - hoffset - ( 2 * ind_field ) ;
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , eoffset - hoffset - ( 2 * ind_field ) ) ;
}
2005-08-28 17:57:30 +00:00
}
else {
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > eoffset - hoffset )
length_remaining = eoffset - hoffset ;
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , eoffset - hoffset ) ;
2005-08-18 08:37:31 +00:00
}
2006-03-09 16:00:33 +00:00
2005-08-18 08:37:31 +00:00
/* call the dissector for this field */
2005-08-28 17:57:30 +00:00
/*if ((eoffset-hoffset)>length_remaining) {*/
2005-08-18 08:37:31 +00:00
/* If the field is indefinite (i.e. we dont know the
* length ) of if the tvb is short , then just
* give it all of the tvb and hope for the best .
*/
2009-08-16 12:36:22 +00:00
/*next_tvb = tvb_new_subset_remaining(tvb, hoffset);*/
2005-08-18 08:37:31 +00:00
/*} else {*/
2006-03-09 16:00:33 +00:00
2005-08-18 08:37:31 +00:00
/*}*/
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 ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2005-06-22 09:58:46 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
2005-08-18 08:37:31 +00:00
if ( tvb_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_length_remaining ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 1 ) , tvb_get_guint8 ( next_tvb , 2 ) ) ;
2005-06-22 09:58:46 +00:00
} else {
2005-08-18 08:37:31 +00:00
printf ( " SEQUENCE dissect_ber_sequence(%s) calling subdissector \n " , name ) ;
2005-06-22 09:58:46 +00:00
}
}
# endif
2005-09-19 16:23:05 +00:00
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
2007-05-22 16:17:54 +00:00
imp_tag = FALSE ;
if ( seq - > flags & BER_FLAGS_IMPLTAG ) {
imp_tag = TRUE ;
}
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 ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2005-08-18 08:37:31 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
printf ( " SEQUENCE dissect_ber_sequence(%s) subdissector ate %d bytes \n " , name , count ) ;
}
# endif
/* if it was optional and no bytes were eaten and it was */
/* supposed to (len<>0), just try again. */
if ( ( len ! = 0 ) & & ( count = = 0 ) & & ( seq - > flags & BER_FLAGS_OPTIONAL ) ) {
seq + + ;
goto ber_sequence_try_again ;
/* move the offset to the beginning of the next sequenced item */
}
2005-11-26 04:16:40 +00:00
offset = eoffset ;
if ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) ) {
2006-09-24 21:04:53 +00:00
/* if we stripped the tag and length we should also strip the EOC is ind_len
* Unless its a zero length field ( len = 2 )
*/
if ( ( ind_field = = 1 ) & & ( len > 2 ) )
2005-08-18 21:36:59 +00:00
{
/* skip over EOC */
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , offset , count , " SEQ FIELD EOC " ) ;
}
}
2005-11-26 04:16:40 +00:00
}
2009-10-04 19:25:46 +00:00
seq + + ;
2005-08-18 08:37:31 +00:00
}
/* if we didnt end up at exactly offset, then we ate too many bytes */
if ( offset ! = end_offset ) {
tvb_ensure_bytes_exist ( tvb , offset - 2 , 2 ) ;
2006-12-19 22:04:22 +00:00
cause = proto_tree_add_text ( tree , tvb , offset - 2 , 2 , " BER Error: Sequence ate %d too many bytes " , offset - end_offset ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: too many bytes in Sequence " ) ;
2005-08-18 08:37:31 +00:00
}
if ( ind ) {
/* need to eat this EOC
2005-11-26 04:16:40 +00:00
end_offset = tvb_length ( tvb ) ; */
2006-03-09 16:00:33 +00:00
end_offset + = 2 ;
2005-11-26 04:16:40 +00:00
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , end_offset - 2 , 2 , " SEQ EOC " ) ;
2005-08-18 08:37:31 +00:00
}
2005-11-26 04:16:40 +00:00
}
2005-08-18 08:37:31 +00:00
return end_offset ;
}
2007-05-22 16:17:54 +00:00
int dissect_ber_old_sequence ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_old_sequence_t * seq , gint hf_id , gint ett_id ) {
2008-06-27 04:52:56 +00:00
gint8 classx ;
gboolean pcx , ind = 0 , ind_field ;
gint32 tagx ;
guint32 lenx ;
2005-08-18 08:37:31 +00:00
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
2006-12-19 22:04:22 +00:00
proto_item * cause ;
2007-08-24 10:20:22 +00:00
int end_offset = 0 ;
int s_offset ;
2007-07-05 13:14:25 +00:00
int hoffset ;
2005-08-28 17:57:30 +00:00
gint length_remaining ;
2005-08-18 08:37:31 +00:00
tvbuff_t * next_tvb ;
2007-05-22 16:17:54 +00:00
2005-08-18 08:37:31 +00:00
s_offset = offset ;
2005-06-22 09:58:46 +00:00
# ifdef DEBUG_BER
2007-05-22 16:17:54 +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 ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2005-06-22 09:58:46 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( tvb , offset ) > 3 ) {
2007-05-22 16:17:54 +00:00
printf ( " SEQUENCE dissect_ber_old_sequence(%s) entered offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2005-06-22 09:58:46 +00:00
} else {
2007-05-22 16:17:54 +00:00
printf ( " SEQUENCE dissect_ber_old_sequence(%s) entered \n " , name ) ;
2005-06-22 09:58:46 +00:00
}
}
# endif
2007-08-24 08:12:39 +00:00
hoffset = offset ;
if ( ! implicit_tag ) {
offset = get_ber_identifier ( tvb , offset , NULL , NULL , NULL ) ;
2008-06-27 04:52:56 +00:00
offset = get_ber_length ( tvb , offset , & lenx , NULL ) ;
2007-08-24 08:12:39 +00:00
} else {
/* was implicit tag so just use the length of the tvb */
2008-06-27 04:52:56 +00:00
lenx = tvb_length_remaining ( tvb , offset ) ;
end_offset = offset + lenx ;
2007-08-24 08:12:39 +00:00
}
/* create subtree */
if ( hf_id > = 0 ) {
if ( parent_tree ) {
2008-06-27 04:52:56 +00:00
item = proto_tree_add_item ( parent_tree , hf_id , tvb , hoffset , lenx + offset - hoffset , FALSE ) ;
2007-08-24 08:12:39 +00:00
tree = proto_item_add_subtree ( item , ett_id ) ;
}
}
offset = hoffset ;
2005-08-18 08:37:31 +00:00
if ( ! implicit_tag ) {
/* first we must read the sequence header */
2008-06-27 04:52:56 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & classx , & pcx , & tagx ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & lenx , & ind ) ;
2005-08-18 08:37:31 +00:00
if ( ind ) {
/* Fixed the length is correctly returned from dissect ber_length
end_offset = tvb_length ( tvb ) ; */
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx - 2 ;
2005-08-18 08:37:31 +00:00
} else {
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx ;
2004-10-16 12:53:09 +00:00
}
2005-08-18 08:37:31 +00:00
2007-05-22 16:17:54 +00:00
/* sanity check: we only handle Constructed Universal Sequences */
2008-06-27 04:52:56 +00:00
if ( ( classx ! = BER_CLASS_APP ) & & ( classx ! = BER_CLASS_PRI ) )
if ( ( ! pcx )
| | ( ! implicit_tag & & ( ( classx ! = BER_CLASS_UNI )
| | ( tagx ! = BER_UNI_TAG_SEQUENCE ) ) ) ) {
2007-07-05 13:14:25 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2008-06-27 04:52:56 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , lenx , " BER Error: Sequence expected but class:%s(%d) %s tag:%d was unexpected " , val_to_str ( classx , ber_class_codes , " Unknown " ) , classx , pcx ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tagx ) ;
2007-05-22 16:17:54 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Sequence expected " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2007-05-22 16:17:54 +00:00
return end_offset ;
2005-08-18 08:37:31 +00:00
}
}
2007-05-22 16:17:54 +00:00
/* loop over all entries until we reach the end of the sequence */
2005-08-18 08:37:31 +00:00
while ( offset < end_offset ) {
gint8 class ;
gboolean pc ;
gint32 tag ;
guint32 len ;
2007-07-05 13:14:25 +00:00
int eoffset , count ;
2005-08-18 08:37:31 +00:00
/*if(ind){ this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2007-05-22 21:15:00 +00:00
but ber dissector uses this to eat the tag length then pass into here . . . EOC still on there . . . */
2005-08-18 08:37:31 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
2007-05-22 16:17:54 +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 , & class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , & ind ) ;
proto_item_append_text ( item , " 0 items " ) ;
return end_offset ;
/*
2005-08-18 08:37:31 +00:00
if ( show_internal_ber_fields ) {
2007-05-22 16:17:54 +00:00
proto_tree_add_text ( tree , tvb , s_offset , offset + 2 , " ERROR WRONG SEQ EOC " ) ;
2005-08-18 08:37:31 +00:00
}
return end_offset ;
2007-05-22 16:17:54 +00:00
*/
2005-08-18 08:37:31 +00:00
}
2007-05-22 16:17:54 +00:00
/*}*/
2004-03-25 09:18:03 +00:00
hoffset = offset ;
2004-02-20 10:04:10 +00:00
/* read header and len for next field */
2004-03-25 09:18:03 +00:00
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind_field ) ;
2004-03-25 09:18:03 +00:00
eoffset = offset + len ;
2007-05-22 16:17:54 +00:00
/* Make sure we move forward */
if ( eoffset < = hoffset )
THROW ( ReportedBoundsError ) ;
2005-08-18 08:37:31 +00:00
2007-05-22 16:17:54 +00:00
/*if(ind_field && (len == 2)){
/ disgusting indefinite length zero length field , what are these people doing /
offset = eoffset ;
continue ;
}
*/
ber_old_sequence_try_again :
/* have we run out of known entries in the sequence ?*/
if ( ! seq - > func ) {
/* 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 ) ;
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: This field lies beyond the end of the known sequence definition. " ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Unknown field in Sequence " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2007-05-22 16:17:54 +00:00
offset = eoffset ;
continue ;
}
/* Verify that this one is the one we want.
2004-07-20 10:45:11 +00:00
* Skip check completely if class = = ANY
2004-10-24 03:51:27 +00:00
* of if NOCHKTAG is set
2004-07-20 10:45:11 +00:00
*/
2007-05-22 16:17:54 +00:00
/* XXX Bug in asn2eth,
* for scope [ 7 ] Scope OPTIONAL ,
* it generates
* { BER_CLASS_CON , 7 , BER_FLAGS_OPTIONAL | BER_FLAGS_NOTCHKTAG , dissect_scope } ,
* and there should not be a NOTCHKTAG here
*/
if ( ( ( seq - > class = = BER_CLASS_CON ) | | ( seq - > class = = BER_CLASS_APP ) | | ( seq - > class = = BER_CLASS_PRI ) ) & & ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) ) ) {
if ( ( seq - > class ! = BER_CLASS_ANY )
& & ( seq - > tag ! = - 1 )
& & ( ( seq - > class ! = class )
| | ( seq - > tag ! = tag ) ) ) {
/* it was not, move to the next one and try again */
if ( seq - > flags & BER_FLAGS_OPTIONAL ) {
/* well this one was optional so just skip to the next one and try again. */
seq + + ;
goto ber_old_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 ) ;
if ( seq - > class = = BER_CLASS_UNI ) {
cause = proto_tree_add_text ( tree , tvb , offset , len ,
2007-11-19 20:23:49 +00:00
" BER Error: Wrong field in SEQUENCE expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d " ,
val_to_str ( seq - > class , ber_class_codes , " Unknown " ) , seq - > class ,
2007-05-22 16:17:54 +00:00
seq - > tag , val_to_str ( seq - > tag , ber_uni_tag_codes , " Unknown " ) ,
2007-11-19 20:23:49 +00:00
val_to_str ( class , ber_class_codes , " Unknown " ) , class , tag ) ;
2007-05-22 16:17:54 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in SEQUENCE " ) ;
} else {
cause = proto_tree_add_text ( tree , tvb , offset , len ,
2007-11-19 20:23:49 +00:00
" BER Error: Wrong field in SEQUENCE expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d " ,
val_to_str ( seq - > class , ber_class_codes , " Unknown " ) , seq - > class ,
seq - > tag , val_to_str ( class , ber_class_codes , " Unknown " ) , class , tag ) ;
2007-05-22 16:17:54 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in SEQUENCE " ) ;
}
2007-07-05 13:14:25 +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 ) ;
}
2007-05-22 16:17:54 +00:00
seq + + ;
offset = eoffset ;
continue ;
2004-11-14 05:10:44 +00:00
}
2007-05-22 16:17:54 +00:00
} else if ( ! ( seq - > flags & BER_FLAGS_NOTCHKTAG ) ) {
if ( ( seq - > class ! = BER_CLASS_ANY )
& & ( seq - > tag ! = - 1 )
& & ( ( seq - > class ! = class )
| | ( seq - > tag ! = tag ) ) ) {
/* it was not, move to the next one and try again */
if ( seq - > flags & BER_FLAGS_OPTIONAL ) {
/* well this one was optional so just skip to the next one and try again. */
seq + + ;
goto ber_old_sequence_try_again ;
}
2006-03-09 16:00:33 +00:00
2007-05-22 16:17:54 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , NULL , NULL ) ;
if ( seq - > class = = BER_CLASS_UNI ) {
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: Wrong field in sequence expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d " , val_to_str ( seq - > class , ber_class_codes , " Unknown " ) , seq - > class , seq - > tag , val_to_str ( seq - > tag , ber_uni_tag_codes , " Unknown " ) , val_to_str ( class , ber_class_codes , " Unknown " ) , class , tag ) ;
2007-05-22 16:17:54 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in sequence " ) ;
} else {
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: Wrong field in sequence expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d " , val_to_str ( seq - > class , ber_class_codes , " Unknown " ) , seq - > class , seq - > tag , val_to_str ( class , ber_class_codes , " Unknown " ) , class , tag ) ;
2007-05-22 16:17:54 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in sequence " ) ;
}
2007-07-05 13:14:25 +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 ) ;
}
2007-05-22 16:17:54 +00:00
seq + + ;
offset = eoffset ;
continue ;
}
}
2005-08-28 19:50:36 +00:00
2007-05-22 16:17:54 +00:00
if ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) ) {
/* dissect header and len for field */
if ( ind_field & & ( len = = 2 ) ) {
/* This is a Zero length field */
next_tvb = tvb_new_subset ( tvb , offset , len , len ) ;
hoffset = eoffset ;
} else {
2007-05-13 20:58:29 +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 ) ;
2005-08-28 19:50:36 +00:00
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > eoffset - hoffset - ( 2 * ind_field ) )
length_remaining = eoffset - hoffset - ( 2 * ind_field ) ;
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , eoffset - hoffset - ( 2 * ind_field ) ) ;
}
2007-05-22 16:17:54 +00:00
}
else {
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > eoffset - hoffset )
length_remaining = eoffset - hoffset ;
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , eoffset - hoffset ) ;
}
2004-02-20 10:04:10 +00:00
2007-05-22 16:17:54 +00:00
/* call the dissector for this field */
/*if ((eoffset-hoffset)>length_remaining) {*/
/* If the field is indefinite (i.e. we dont know the
* length ) of if the tvb is short , then just
* give it all of the tvb and hope for the best .
*/
2009-08-16 12:36:22 +00:00
/*next_tvb = tvb_new_subset_remaining(tvb, hoffset);*/
2007-05-22 16:17:54 +00:00
/*} else {*/
2006-03-09 16:00:33 +00:00
2007-05-22 16:17:54 +00:00
/*}*/
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 ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( next_tvb , 0 ) > 3 ) {
2007-05-22 16:17:54 +00:00
printf ( " SEQUENCE dissect_ber_old_sequence(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_length_remaining ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 1 ) , tvb_get_guint8 ( next_tvb , 2 ) ) ;
2004-11-14 05:10:44 +00:00
} else {
2007-05-22 16:17:54 +00:00
printf ( " SEQUENCE dissect_ber_old_sequence(%s) calling subdissector \n " , name ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2007-05-22 16:17:54 +00:00
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
2005-08-28 19:50:36 +00:00
}
2007-05-22 16:17:54 +00:00
count = seq - > func ( tree , next_tvb , 0 , actx ) ;
2005-08-28 19:50:36 +00:00
2007-05-22 16:17:54 +00:00
# ifdef DEBUG_BER
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
printf ( " SEQUENCE dissect_ber_old_sequence(%s) subdissector ate %d bytes \n " , name , count ) ;
}
# endif
/* if it was optional and no bytes were eaten and it was */
/* supposed to (len<>0), just try again. */
if ( ( len ! = 0 ) & & ( count = = 0 ) & & ( seq - > flags & BER_FLAGS_OPTIONAL ) ) {
seq + + ;
goto ber_old_sequence_try_again ;
/* move the offset to the beginning of the next sequenced item */
}
offset = eoffset ;
seq + + ;
if ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) ) {
/* if we stripped the tag and length we should also strip the EOC is ind_len
* Unless its a zero length field ( len = 2 )
*/
if ( ( ind_field = = 1 ) & & ( len > 2 ) )
{
/* skip over EOC */
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , offset , count , " SEQ FIELD EOC " ) ;
}
}
}
}
/* if we didnt end up at exactly offset, then we ate too many bytes */
if ( offset ! = end_offset ) {
tvb_ensure_bytes_exist ( tvb , offset - 2 , 2 ) ;
cause = proto_tree_add_text ( tree , tvb , offset - 2 , 2 , " BER Error: Sequence ate %d too many bytes " , offset - end_offset ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: too many bytes in Sequence " ) ;
}
if ( ind ) {
/* need to eat this EOC
end_offset = tvb_length ( tvb ) ; */
end_offset + = 2 ;
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , end_offset - 2 , 2 , " SEQ EOC " ) ;
}
}
return end_offset ;
}
/* This function dissects a BER set
*/
int 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 ) {
2008-06-27 04:52:56 +00:00
gint8 classx ;
gboolean pcx , ind = 0 , ind_field , imp_tag = FALSE ;
gint32 tagx ;
guint32 lenx ;
2007-05-22 16:17:54 +00:00
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
proto_item * cause ;
int end_offset , s_offset ;
2007-07-05 13:14:25 +00:00
int hoffset ;
2007-05-22 16:17:54 +00:00
gint length_remaining ;
tvbuff_t * next_tvb ;
const ber_sequence_t * cset = NULL ;
# define MAX_SET_ELEMENTS 32
guint32 mandatory_fields = 0 ;
guint8 set_idx ;
gboolean first_pass ;
s_offset = offset ;
# ifdef DEBUG_BER
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( tvb , offset ) > 3 ) {
printf ( " SET dissect_ber_set(%s) entered offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
} else {
printf ( " SET dissect_ber_set(%s) entered \n " , name ) ;
}
}
# endif
if ( ! implicit_tag ) {
2007-07-05 13:14:25 +00:00
hoffset = offset ;
2007-05-22 16:17:54 +00:00
/* first we must read the sequence header */
2008-06-27 04:52:56 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & classx , & pcx , & tagx ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & lenx , & ind ) ;
2007-05-22 16:17:54 +00:00
if ( ind ) {
/* Fixed the length is correctly returned from dissect ber_length
end_offset = tvb_length ( tvb ) ; */
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx - 2 ;
2007-05-22 16:17:54 +00:00
} else {
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx ;
2007-05-22 16:17:54 +00:00
}
/* sanity check: we only handle Constructed Universal Sets */
2008-06-27 04:52:56 +00:00
if ( ( classx ! = BER_CLASS_APP ) & & ( classx ! = BER_CLASS_PRI ) )
if ( ( ! pcx )
| | ( ! implicit_tag & & ( ( classx ! = BER_CLASS_UNI )
| | ( tagx ! = BER_UNI_TAG_SET ) ) ) ) {
2007-07-05 13:14:25 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2008-06-27 04:52:56 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , lenx , " BER Error: SET expected but class:%s(%d) %s tag:%d was found " , val_to_str ( classx , ber_class_codes , " Unknown " ) , classx , pcx ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tagx ) ;
2007-05-22 16:17:54 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: SET expected " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2007-05-22 16:17:54 +00:00
return end_offset ;
}
} else {
/* was implicit tag so just use the length of the tvb */
2008-06-27 04:52:56 +00:00
lenx = tvb_length_remaining ( tvb , offset ) ;
end_offset = offset + lenx ;
2007-05-22 16:17:54 +00:00
}
/* create subtree */
if ( hf_id > = 0 ) {
if ( parent_tree ) {
2008-06-27 04:52:56 +00:00
item = proto_tree_add_item ( parent_tree , hf_id , tvb , offset , lenx , FALSE ) ;
2007-05-22 16:17:54 +00:00
tree = proto_item_add_subtree ( item , ett_id ) ;
}
}
/* 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 */
while ( offset < end_offset ) {
gint8 class ;
gboolean pc ;
gint32 tag ;
guint32 len ;
2007-07-05 13:14:25 +00:00
int eoffset , count ;
2007-05-22 16:17:54 +00:00
/*if(ind){ this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2007-05-22 21:15:00 +00:00
but ber dissector uses this to eat the tag length then pass into here . . . EOC still on there . . . */
2007-05-22 16:17:54 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , s_offset , offset + 2 , " SEQ EOC " ) ;
}
return end_offset ;
}
/* } */
hoffset = offset ;
/* read header and len for next field */
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind_field ) ;
2007-05-22 16:17:54 +00:00
eoffset = offset + len ;
/* Look through the Set to see if this class/id exists and
* hasn ' t been seen before
* Skip check completely if class = = ANY
* of if NOCHKTAG is set
*/
for ( first_pass = TRUE , cset = set , set_idx = 0 ; cset - > func | | first_pass ; cset + + , set_idx + + ) {
/* we reset for a second pass when we will look for choices */
if ( ! cset - > func ) {
first_pass = FALSE ;
cset = set ; /* reset to the beginning */
set_idx = 0 ;
}
if ( ( first_pass & & ( ( cset - > class = = class ) & & ( cset - > tag = = tag ) ) ) | |
( ! first_pass & & ( ( cset - > class = = BER_CLASS_ANY ) & & ( cset - > tag = = - 1 ) ) ) ) /* choices */
{
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 ) ;
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > eoffset - hoffset - ( 2 * ind_field ) )
length_remaining = eoffset - hoffset - ( 2 * ind_field ) ;
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , eoffset - hoffset - ( 2 * ind_field ) ) ;
}
else {
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > eoffset - hoffset )
length_remaining = eoffset - hoffset ;
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , eoffset - hoffset ) ;
}
/* call the dissector for this field */
/*if ((eoffset-hoffset)>length_remaining) {*/
/* If the field is indefinite (i.e. we dont know the
* length ) of if the tvb is short , then just
* give it all of the tvb and hope for the best .
*/
2009-08-16 12:36:22 +00:00
/*next_tvb = tvb_new_subset_remaining(tvb, hoffset);*/
2007-05-22 16:17:54 +00:00
/*} else {*/
/*}*/
# ifdef DEBUG_BER
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_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_length_remaining ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 1 ) , tvb_get_guint8 ( next_tvb , 2 ) ) ;
} else {
printf ( " SET dissect_ber_set(%s) calling subdissector \n " , name ) ;
}
}
# endif
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
2007-06-23 15:31:37 +00:00
imp_tag = FALSE ;
2007-05-22 16:17:54 +00:00
if ( ( cset - > flags & BER_FLAGS_IMPLTAG ) )
imp_tag = TRUE ;
count = cset - > func ( imp_tag , next_tvb , 0 , actx , tree , * cset - > p_id ) ;
/* if we consumed some bytes,
or we knew the length was zero ( during the first pass only ) */
2007-08-13 16:41:16 +00:00
if ( count | | ( first_pass & & ( len = = 0 | | ( ind_field = = 1 & & len = = 2 ) ) ) ) {
2007-05-22 16:17:54 +00:00
/* we found it! */
if ( set_idx < MAX_SET_ELEMENTS )
mandatory_fields & = ~ ( 1 < < set_idx ) ;
offset = eoffset ;
if ( ! ( cset - > flags & BER_FLAGS_NOOWNTAG ) ) {
/* if we stripped the tag and length we should also strip the EOC is ind_len */
if ( ind_field = = 1 ) {
/* skip over EOC */
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , offset , count , " SET FIELD EOC " ) ;
}
}
}
break ;
}
}
}
if ( ! cset - > func ) {
/* we didn't find a match */
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: Unknown field in SET class:%s(%d) tag:%d " , val_to_str ( class , ber_class_codes , " Unknown " ) , class , tag ) ;
2007-05-22 16:17:54 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Unknown field in SET " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2007-05-22 16:17:54 +00:00
offset = eoffset ;
}
}
if ( mandatory_fields ) {
/* OK - we didn't find some of the elements we expected */
for ( set_idx = 0 ; ( cset = & set [ set_idx ] ) - > func & & ( set_idx < MAX_SET_ELEMENTS ) ; set_idx + + ) {
if ( mandatory_fields & ( 1 < < set_idx ) ) {
/* here is something we should have seen - but didn't! */
2008-06-27 04:52:56 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , lenx ,
2007-11-19 20:23:49 +00:00
" BER Error: Missing field in SET class:%s(%d) tag:%d expected " ,
val_to_str ( cset - > class , ber_class_codes , " Unknown " ) , cset - > class ,
2007-05-22 16:17:54 +00:00
cset - > tag ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Missing field in SET " ) ;
}
}
}
/* if we didnt end up at exactly offset, then we ate too many bytes */
if ( offset ! = end_offset ) {
tvb_ensure_bytes_exist ( tvb , offset - 2 , 2 ) ;
cause = proto_tree_add_text ( tree , tvb , offset - 2 , 2 , " BER Error: SET ate %d too many bytes " , offset - end_offset ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: too many bytes in SET " ) ;
}
if ( ind ) {
/* need to eat this EOC
end_offset = tvb_length ( tvb ) ; */
end_offset + = 2 ;
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , end_offset - 2 , 2 , " SET EOC " ) ;
}
}
return end_offset ;
}
int dissect_ber_old_set ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_old_sequence_t * set , gint hf_id , gint ett_id ) {
2008-06-27 04:52:56 +00:00
gint8 classx ;
gboolean pcx , ind = 0 , ind_field ;
gint32 tagx ;
guint32 lenx ;
2007-05-22 16:17:54 +00:00
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
proto_item * cause ;
int end_offset , s_offset ;
2007-07-05 13:14:25 +00:00
int hoffset ;
2007-05-22 16:17:54 +00:00
gint length_remaining ;
tvbuff_t * next_tvb ;
const ber_old_sequence_t * cset = NULL ;
# define MAX_SET_ELEMENTS 32
guint32 mandatory_fields = 0 ;
guint8 set_idx ;
gboolean first_pass ;
s_offset = offset ;
# ifdef DEBUG_BER
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( tvb , offset ) > 3 ) {
printf ( " SET dissect_old_ber_set(%s) entered offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
} else {
printf ( " SET dissect_old_ber_set(%s) entered \n " , name ) ;
}
}
# endif
if ( ! implicit_tag ) {
2007-07-05 13:14:25 +00:00
hoffset = offset ;
2007-05-22 16:17:54 +00:00
/* first we must read the sequence header */
2008-06-27 04:52:56 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & classx , & pcx , & tagx ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & lenx , & ind ) ;
2007-05-22 16:17:54 +00:00
if ( ind ) {
/* Fixed the length is correctly returned from dissect ber_length
end_offset = tvb_length ( tvb ) ; */
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx - 2 ;
2007-05-22 16:17:54 +00:00
} else {
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx ;
2007-05-22 16:17:54 +00:00
}
/* sanity check: we only handle Constructed Universal Sets */
2008-06-27 04:52:56 +00:00
if ( ( classx ! = BER_CLASS_APP ) & & ( classx ! = BER_CLASS_PRI ) )
if ( ( ! pcx )
| | ( ! implicit_tag & & ( ( classx ! = BER_CLASS_UNI )
| | ( tagx ! = BER_UNI_TAG_SET ) ) ) ) {
2007-07-05 13:14:25 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2008-06-27 04:52:56 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , lenx , " BER Error: SET expected but class:%s(%d) %s tag:%d was found " , val_to_str ( classx , ber_class_codes , " Unknown " ) , classx , pcx ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tagx ) ;
2007-05-22 16:17:54 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: SET expected " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2007-05-22 16:17:54 +00:00
return end_offset ;
}
} else {
/* was implicit tag so just use the length of the tvb */
2008-06-27 04:52:56 +00:00
lenx = tvb_length_remaining ( tvb , offset ) ;
end_offset = offset + lenx ;
2007-05-22 16:17:54 +00:00
}
/* create subtree */
if ( hf_id > = 0 ) {
if ( parent_tree ) {
2008-06-27 04:52:56 +00:00
item = proto_tree_add_item ( parent_tree , hf_id , tvb , offset , lenx , FALSE ) ;
2007-05-22 16:17:54 +00:00
tree = proto_item_add_subtree ( item , ett_id ) ;
}
}
/* 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 */
while ( offset < end_offset ) {
gint8 class ;
gboolean pc ;
gint32 tag ;
guint32 len ;
2007-07-05 13:14:25 +00:00
int eoffset , count ;
2007-05-22 16:17:54 +00:00
/*if(ind){ this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2007-05-22 21:15:00 +00:00
but ber dissector uses this to eat the tag length then pass into here . . . EOC still on there . . . */
2007-05-22 16:17:54 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , s_offset , offset + 2 , " SEQ EOC " ) ;
}
return end_offset ;
}
/* } */
hoffset = offset ;
/* read header and len for next field */
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind_field ) ;
2007-05-22 16:17:54 +00:00
eoffset = offset + len ;
/* Look through the Set to see if this class/id exists and
* hasn ' t been seen before
* Skip check completely if class = = ANY
* of if NOCHKTAG is set
*/
for ( first_pass = TRUE , cset = set , set_idx = 0 ; cset - > func | | first_pass ; cset + + , set_idx + + ) {
/* we reset for a second pass when we will look for choices */
if ( ! cset - > func ) {
first_pass = FALSE ;
cset = set ; /* reset to the beginning */
set_idx = 0 ;
}
if ( ( first_pass & & ( ( cset - > class = = class ) & & ( cset - > tag = = tag ) ) ) | |
( ! first_pass & & ( ( cset - > class = = BER_CLASS_ANY ) & & ( cset - > tag = = - 1 ) ) ) ) /* choices */
{
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 ) ;
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > eoffset - hoffset - ( 2 * ind_field ) )
length_remaining = eoffset - hoffset - ( 2 * ind_field ) ;
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , eoffset - hoffset - ( 2 * ind_field ) ) ;
}
else {
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > eoffset - hoffset )
length_remaining = eoffset - hoffset ;
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , eoffset - hoffset ) ;
}
/* call the dissector for this field */
/*if ((eoffset-hoffset)>length_remaining) {*/
/* If the field is indefinite (i.e. we dont know the
* length ) of if the tvb is short , then just
* give it all of the tvb and hope for the best .
*/
2009-08-16 12:36:22 +00:00
/*next_tvb = tvb_new_subset_remaining(tvb, hoffset);*/
2007-05-22 16:17:54 +00:00
/*} else {*/
/*}*/
# ifdef DEBUG_BER
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( next_tvb , 0 ) > 3 ) {
printf ( " SET dissect_old_ber_set(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_length_remaining ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 1 ) , tvb_get_guint8 ( next_tvb , 2 ) ) ;
} else {
printf ( " SET dissect_old_ber_set(%s) calling subdissector \n " , name ) ;
}
}
# endif
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
count = cset - > func ( tree , next_tvb , 0 , actx ) ;
/* if we consumed some bytes,
or we knew the length was zero ( during the first pass only ) */
2007-08-13 16:41:16 +00:00
if ( count | | ( first_pass & & ( len = = 0 | | ( ind_field = = 1 & & len = = 2 ) ) ) ) {
2007-05-22 16:17:54 +00:00
/* we found it! */
if ( set_idx < MAX_SET_ELEMENTS )
mandatory_fields & = ~ ( 1 < < set_idx ) ;
offset = eoffset ;
if ( ! ( cset - > flags & BER_FLAGS_NOOWNTAG ) ) {
/* if we stripped the tag and length we should also strip the EOC is ind_len */
if ( ind_field = = 1 ) {
/* skip over EOC */
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , offset , count , " SET FIELD EOC " ) ;
}
}
}
break ;
}
}
}
if ( ! cset - > func ) {
/* we didn't find a match */
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: Unknown field in SET class:%s(%d) tag:%d " , val_to_str ( class , ber_class_codes , " Unknown " ) , class , tag ) ;
2007-05-22 16:17:54 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Unknown field in SET " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2006-03-09 16:00:33 +00:00
offset = eoffset ;
}
2005-08-28 19:50:36 +00:00
}
if ( mandatory_fields ) {
/* OK - we didn't find some of the elements we expected */
for ( set_idx = 0 ; ( cset = & set [ set_idx ] ) - > func & & ( set_idx < MAX_SET_ELEMENTS ) ; set_idx + + ) {
if ( mandatory_fields & ( 1 < < set_idx ) ) {
/* here is something we should have seen - but didn't! */
2008-06-27 04:52:56 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , lenx ,
2007-11-19 20:23:49 +00:00
" BER Error: Missing field in SET class:%s(%d) tag:%d expected " ,
val_to_str ( cset - > class , ber_class_codes , " Unknown " ) , cset - > class ,
2005-08-28 19:50:36 +00:00
cset - > tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Missing field in SET " ) ;
2005-08-28 19:50:36 +00:00
}
}
2004-02-20 10:04:10 +00:00
}
2007-05-22 16:17:54 +00:00
/* if we didnt end up at exactly offset, then we ate too many bytes */
if ( offset ! = end_offset ) {
tvb_ensure_bytes_exist ( tvb , offset - 2 , 2 ) ;
cause = proto_tree_add_text ( tree , tvb , offset - 2 , 2 , " BER Error: SET ate %d too many bytes " , offset - end_offset ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: too many bytes in SET " ) ;
}
if ( ind ) {
/* need to eat this EOC
end_offset = tvb_length ( tvb ) ; */
end_offset + = 2 ;
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , end_offset - 2 , 2 , " SET EOC " ) ;
}
}
return end_offset ;
}
/* this function dissects a BER choice
* If we did not find a matching choice , just return offset unchanged
* in case it was a CHOICE { } OPTIONAL
*/
# ifdef DEBUG_BER
# define DEBUG_BER_CHOICE
# endif
int
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 )
{
gint8 class ;
gboolean pc , ind , imp_tag = FALSE ;
gint32 tag ;
guint32 len ;
const ber_choice_t * ch ;
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
int end_offset , start_offset , count ;
int hoffset = offset ;
header_field_info * hfinfo ;
gint length , length_remaining ;
tvbuff_t * next_tvb ;
gboolean first_pass ;
# ifdef DEBUG_BER_CHOICE
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( tvb , offset ) > 3 ) {
printf ( " CHOICE dissect_ber_choice(%s) entered offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
} else {
printf ( " CHOICE dissect_ber_choice(%s) entered len:%d \n " , name , tvb_length_remaining ( tvb , offset ) ) ;
}
}
# endif
start_offset = offset ;
2007-11-23 12:22:22 +00:00
if ( tvb_length_remaining ( tvb , offset ) = = 0 ) {
item = proto_tree_add_text ( parent_tree , tvb , offset , 0 , " BER Error: Empty choice was found " ) ;
proto_item_set_expert_flags ( item , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , item , PI_MALFORMED , PI_WARN , " BER Error: Empty choice was found " ) ;
return offset ;
}
2007-05-22 16:17:54 +00:00
/* read header and len for choice field */
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind ) ;
2007-05-22 16:17:54 +00:00
end_offset = offset + len ;
/* Some sanity checks.
* The hf field passed to us MUST be an integer type
*/
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
switch ( hfinfo - > type ) {
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
break ;
default :
proto_tree_add_text ( tree , tvb , offset , len , " dissect_ber_choice(): Was passed a HF field that was not integer type : %s " , hfinfo - > abbrev ) ;
fprintf ( stderr , " dissect_ber_choice(): frame:%u offset:%d Was passed a HF field that was not integer type : %s \n " , actx - > pinfo - > fd - > num , offset , hfinfo - > abbrev ) ;
return end_offset ;
}
}
/* loop over all entries until we find the right choice or
run out of entries */
ch = choice ;
if ( branch_taken ) {
* branch_taken = - 1 ;
}
first_pass = TRUE ;
while ( ch - > func | | first_pass ) {
if ( branch_taken ) {
( * branch_taken ) + + ;
}
/* we reset for a second pass when we will look for choices */
if ( ! ch - > func ) {
first_pass = FALSE ;
ch = choice ; /* reset to the beginning */
if ( branch_taken ) {
* branch_taken = - 1 ;
}
}
choice_try_again :
# ifdef DEBUG_BER_CHOICE
printf ( " CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d:(expected)%d flags:%d \n " , ch , class , ch - > class , tag , ch - > tag , ch - > flags ) ;
# endif
if ( ( first_pass & & ( ( ( ch - > class = = class ) & & ( ch - > tag = = tag ) )
| | ( ( ch - > class = = class ) & & ( ch - > tag = = - 1 ) & & ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) ) ) | |
( ! first_pass & & ( ( ( ch - > class = = BER_CLASS_ANY ) & & ( ch - > tag = = - 1 ) ) ) ) /* we failed on the first pass so now try any choices */
) {
if ( ! ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) {
/* 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 ) ;
start_offset = hoffset ;
if ( ind )
{
length = len - 2 ;
}
else
{
length = len ;
}
}
else
length = end_offset - hoffset ;
/* create subtree */
if ( hf_id > = 0 ) {
if ( parent_tree ) {
item = proto_tree_add_uint ( parent_tree , hf_id , tvb , hoffset , end_offset - hoffset , ch - > value ) ;
tree = proto_item_add_subtree ( item , ett_id ) ;
}
}
2007-11-19 17:46:11 +00:00
2007-05-22 16:17:54 +00:00
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > length )
length_remaining = length ;
# ifdef REMOVED
/* 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
*/
if ( first_pass )
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , length ) ;
else
next_tvb = tvb ; /* we didn't make selection on this class/tag so pass it on */
# endif
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , length ) ;
# ifdef DEBUG_BER_CHOICE
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_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_length_remaining ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 1 ) , tvb_get_guint8 ( next_tvb , 2 ) ) ;
} else {
printf ( " CHOICE dissect_ber_choice(%s) calling subdissector len:%d \n " , name , tvb_length ( next_tvb ) ) ;
}
}
# endif
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
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 ) ;
# ifdef DEBUG_BER_CHOICE
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
printf ( " CHOICE dissect_ber_choice(%s) subdissector ate %d bytes \n " , name , count ) ;
}
# endif
if ( ( count = = 0 ) & & ( ( ( ch - > class = = class ) & & ( ch - > tag = = - 1 ) & & ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) | | ! first_pass ) ) {
/* wrong one, break and try again */
ch + + ;
# ifdef DEBUG_BER_CHOICE
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
printf ( " CHOICE dissect_ber_choice(%s) trying again \n " , name ) ;
}
# endif
goto choice_try_again ;
}
if ( ! ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) {
if ( ind )
{
/* we are traversing a indfinite length choice where we did not pass the tag length */
/* we need to eat the EOC */
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , start_offset , count + 2 , " CHOICE EOC " ) ;
}
}
}
return end_offset ;
}
ch + + ;
}
if ( branch_taken ) {
/* none of the branches were taken so set the param
back to - 1 */
* branch_taken = - 1 ;
2004-02-20 10:04:10 +00:00
}
2006-03-09 16:00:33 +00:00
2007-05-22 16:17:54 +00:00
# ifdef REMOVED
/*XXX here we should have another flag to the CHOICE to distinguish
2008-11-29 11:17:34 +00:00
* between the case when we know it is a mandatory or if the CHOICE is optional = = no arm matched */
2005-08-28 19:50:36 +00:00
2007-05-22 16:17:54 +00:00
/* oops no more entries and we still havent found
* our guy : - (
*/
2007-11-19 20:23:49 +00:00
item = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: This choice field was not found. " ) ;
proto_item_set_expert_flags ( item , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , item , PI_MALFORMED , PI_WARN , " BER Error: This choice field was not found " ) ;
2004-02-20 10:04:10 +00:00
return end_offset ;
2007-05-22 16:17:54 +00:00
# endif
2005-08-28 19:50:36 +00:00
2007-05-22 16:17:54 +00:00
return start_offset ;
2004-02-20 10:04:10 +00:00
}
int
2007-05-22 16:17:54 +00:00
dissect_ber_old_choice ( asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_old_choice_t * choice , gint hf_id , gint ett_id , gint * branch_taken )
2004-02-20 10:04:10 +00:00
{
2004-12-13 08:15:34 +00:00
gint8 class ;
2004-10-24 03:51:27 +00:00
gboolean pc , ind ;
2004-12-13 08:15:34 +00:00
gint32 tag ;
2004-02-20 10:04:10 +00:00
guint32 len ;
2007-05-22 16:17:54 +00:00
const ber_old_choice_t * ch ;
2004-02-20 10:04:10 +00:00
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
2004-11-14 05:10:44 +00:00
int end_offset , start_offset , count ;
2004-03-25 09:18:03 +00:00
int hoffset = offset ;
2004-06-25 09:24:17 +00:00
header_field_info * hfinfo ;
2005-08-28 17:57:30 +00:00
gint length , length_remaining ;
2004-11-14 05:10:44 +00:00
tvbuff_t * next_tvb ;
2005-08-28 19:50:36 +00:00
gboolean first_pass ;
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 ;
2004-11-14 05:10:44 +00:00
header_field_info * hfinfo ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( tvb , offset ) > 3 ) {
2007-05-22 16:17:54 +00:00
printf ( " CHOICE dissect_ber_old_choice(%s) entered offset:%d len:%d %02x:%02x:%02x \n " , name , offset , tvb_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2004-11-14 05:10:44 +00:00
} else {
2007-05-22 16:17:54 +00:00
printf ( " CHOICE dissect_ber_old_choice(%s) entered len:%d \n " , name , tvb_length_remaining ( tvb , offset ) ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2004-10-28 11:35:43 +00:00
start_offset = offset ;
2007-11-23 12:22:22 +00:00
if ( tvb_length_remaining ( tvb , offset ) = = 0 ) {
item = proto_tree_add_text ( parent_tree , tvb , offset , 0 , " BER Error: Empty choice was found " ) ;
proto_item_set_expert_flags ( item , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , item , PI_MALFORMED , PI_WARN , " BER Error: Empty choice was found " ) ;
return offset ;
}
2004-03-25 09:18:03 +00:00
/* read header and len for choice field */
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind ) ;
2005-08-18 08:37:31 +00:00
end_offset = offset + len ;
2006-03-09 16:00:33 +00:00
/* Some sanity checks.
* The hf field passed to us MUST be an integer type
2004-06-25 09:24:17 +00:00
*/
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-06-25 09:24:17 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
switch ( hfinfo - > type ) {
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
break ;
default :
2007-05-22 16:17:54 +00:00
proto_tree_add_text ( tree , tvb , offset , len , " dissect_ber_old_choice(): Was passed a HF field that was not integer type : %s " , hfinfo - > abbrev ) ;
fprintf ( stderr , " dissect_ber_old_choice(): frame:%u offset:%d Was passed a HF field that was not integer type : %s \n " , actx - > pinfo - > fd - > num , offset , hfinfo - > abbrev ) ;
2004-06-25 09:24:17 +00:00
return end_offset ;
}
}
2006-03-09 16:00:33 +00:00
/* loop over all entries until we find the right choice or
2004-02-20 10:04:10 +00:00
run out of entries */
2004-03-25 09:18:03 +00:00
ch = choice ;
2005-09-05 16:31:24 +00:00
if ( branch_taken ) {
* branch_taken = - 1 ;
}
2005-08-28 19:50:36 +00:00
first_pass = TRUE ;
while ( ch - > func | | first_pass ) {
2005-09-05 16:31:24 +00:00
if ( branch_taken ) {
( * branch_taken ) + + ;
}
2005-08-28 19:50:36 +00:00
/* we reset for a second pass when we will look for choices */
if ( ! ch - > func ) {
first_pass = FALSE ;
ch = choice ; /* reset to the beginning */
2005-09-05 16:31:24 +00:00
if ( branch_taken ) {
* branch_taken = - 1 ;
}
2005-08-28 19:50:36 +00:00
}
2004-12-12 22:19:00 +00:00
choice_try_again :
2007-05-02 20:37:25 +00:00
# ifdef DEBUG_BER_CHOICE
printf ( " CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d:(expected)%d flags:%d \n " , ch , class , ch - > class , tag , ch - > tag , ch - > flags ) ;
2004-12-12 22:19:00 +00:00
# endif
2005-08-28 19:50:36 +00:00
if ( ( first_pass & & ( ( ( ch - > class = = class ) & & ( ch - > tag = = tag ) )
| | ( ( ch - > class = = class ) & & ( ch - > tag = = - 1 ) & & ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) ) ) | |
( ! first_pass & & ( ( ( ch - > class = = BER_CLASS_ANY ) & & ( ch - > tag = = - 1 ) ) ) ) /* we failed on the first pass so now try any choices */
2004-12-12 22:19:00 +00:00
) {
2005-08-18 08:37:31 +00:00
if ( ! ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) {
2004-03-25 09:18:03 +00:00
/* dissect header and len for field */
2007-05-13 20:58:29 +00:00
hoffset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , start_offset , NULL , NULL , NULL ) ;
hoffset = dissect_ber_length ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL ) ;
2004-11-14 05:10:44 +00:00
start_offset = hoffset ;
2005-08-18 08:37:31 +00:00
if ( ind )
{
length = len - 2 ;
}
else
{
length = len ;
}
2004-03-25 09:18:03 +00:00
}
2005-08-18 08:37:31 +00:00
else
length = end_offset - hoffset ;
2004-03-25 09:18:03 +00:00
/* create subtree */
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-03-25 09:18:03 +00:00
if ( parent_tree ) {
item = proto_tree_add_uint ( parent_tree , hf_id , tvb , hoffset , end_offset - hoffset , ch - > value ) ;
tree = proto_item_add_subtree ( item , ett_id ) ;
}
}
2007-11-19 17:46:11 +00:00
2005-08-28 17:57:30 +00:00
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > length )
length_remaining = length ;
2006-02-02 08:34:59 +00:00
2006-03-09 16:00:33 +00:00
# ifdef REMOVED
2006-02-02 08:34:59 +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
*/
2005-09-06 05:30:06 +00:00
if ( first_pass )
2005-08-28 17:57:30 +00:00
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , length ) ;
2005-09-06 05:30:06 +00:00
else
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
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , length ) ;
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 ;
2004-11-14 05:10:44 +00:00
header_field_info * hfinfo ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( next_tvb , 0 ) > 3 ) {
2007-05-22 16:17:54 +00:00
printf ( " CHOICE dissect_ber_old_choice(%s) calling subdissector start_offset:%d offset:%d len:%d %02x:%02x:%02x \n " , name , start_offset , offset , tvb_length_remaining ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 0 ) , tvb_get_guint8 ( next_tvb , 1 ) , tvb_get_guint8 ( next_tvb , 2 ) ) ;
2004-11-14 05:10:44 +00:00
} else {
2007-05-22 16:17:54 +00:00
printf ( " CHOICE dissect_ber_old_choice(%s) calling subdissector len:%d \n " , name , tvb_length ( next_tvb ) ) ;
2004-11-14 05:10:44 +00:00
}
}
# endif
2005-09-19 16:23:05 +00:00
if ( next_tvb = = NULL ) {
/* Assume that we have a malformed packet. */
THROW ( ReportedBoundsError ) ;
}
2007-05-13 20:58:29 +00:00
count = ch - > func ( tree , next_tvb , 0 , actx ) ;
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 ;
2004-11-14 05:10:44 +00:00
header_field_info * hfinfo ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
2007-05-22 16:17:54 +00:00
printf ( " CHOICE dissect_ber_old_choice(%s) subdissector ate %d bytes \n " , name , count ) ;
2004-11-14 05:10:44 +00:00
}
# endif
2005-09-06 05:30:06 +00:00
if ( ( count = = 0 ) & & ( ( ( ch - > class = = class ) & & ( ch - > tag = = - 1 ) & & ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) | | ! first_pass ) ) {
2004-12-12 22:19:00 +00:00
/* wrong one, break and try again */
ch + + ;
2007-05-02 20:37:25 +00:00
# ifdef DEBUG_BER_CHOICE
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
2007-05-22 16:17:54 +00:00
printf ( " CHOICE dissect_ber_old_choice(%s) trying again \n " , name ) ;
2007-05-02 20:37:25 +00:00
}
# endif
2004-12-12 22:19:00 +00:00
goto choice_try_again ;
}
2005-08-18 08:37:31 +00:00
if ( ! ( ch - > flags & BER_FLAGS_NOOWNTAG ) ) {
if ( ind )
{
/* we are traversing a indfinite length choice where we did not pass the tag length */
/* we need to eat the EOC */
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , start_offset , count + 2 , " CHOICE EOC " ) ;
}
2006-03-09 16:00:33 +00:00
}
2004-10-24 03:51:27 +00:00
}
2005-08-18 08:37:31 +00:00
return end_offset ;
2004-02-20 10:04:10 +00:00
}
ch + + ;
}
2005-09-05 16:31:24 +00:00
if ( branch_taken ) {
2006-03-09 16:00:33 +00:00
/* none of the branches were taken so set the param
2005-09-05 16:31:24 +00:00
back to - 1 */
* branch_taken = - 1 ;
}
2004-10-28 11:35:43 +00:00
# ifdef REMOVED
/*XXX here we should have another flag to the CHOICE to distinguish
2008-11-29 11:17:34 +00:00
* between the case when we know it is a mandatory or if the CHOICE is optional = = no arm matched */
2004-10-28 11:35:43 +00:00
2004-02-20 10:04:10 +00:00
/* oops no more entries and we still havent found
* our guy : - (
*/
2006-12-19 22:04:22 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: This choice field was not found. " ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: This choice field was not found " ) ;
2004-02-20 10:04:10 +00:00
return end_offset ;
2004-10-28 11:35:43 +00:00
# endif
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
{
2004-12-13 08:15:34 +00:00
gint8 class ;
2004-02-20 10:04:10 +00:00
gboolean pc ;
2004-12-13 08:15:34 +00:00
gint32 tag ;
2004-02-20 10:04:10 +00:00
guint32 len ;
int end_offset ;
2007-07-05 13:14:25 +00:00
int hoffset ;
2004-02-20 10:04:10 +00:00
char str_arr [ 256 ] ;
guint32 max_len ;
char * str ;
2006-12-19 22:04:22 +00:00
proto_item * cause ;
2004-02-20 10:04:10 +00:00
str = str_arr ;
max_len = 255 ;
if ( name_string ) {
str = name_string ;
max_len = name_len ;
}
2007-07-05 13:14:25 +00:00
hoffset = offset ;
2004-02-20 10:04:10 +00:00
/* first we must read the GeneralString header */
2007-05-15 05:49:43 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
2004-02-20 10:04:10 +00:00
end_offset = offset + len ;
/* sanity check: we only handle Universal GeneralString*/
if ( ( class ! = BER_CLASS_UNI )
| | ( tag ! = BER_UNI_TAG_GENSTR ) ) {
2007-07-05 13:14:25 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: GeneralString expected but class:%s(%d) %s tag:%d was unexpected " , val_to_str ( class , ber_class_codes , " Unknown " ) , class , pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-15 05:49:43 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: GeneralString expected " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2004-02-20 10:04:10 +00:00
return end_offset ;
}
if ( len > = ( max_len - 1 ) ) {
len = max_len - 1 ;
}
2006-03-09 16:00:33 +00:00
2004-02-20 10:04:10 +00:00
tvb_memcpy ( tvb , str , offset , len ) ;
str [ len ] = 0 ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-02-20 10:04:10 +00:00
proto_tree_add_string ( tree , hf_id , tvb , offset , len , str ) ;
}
return end_offset ;
}
2004-03-25 09:18:03 +00:00
# endif
2009-12-18 15:18:31 +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 ) {
2004-12-13 08:15:34 +00:00
gint8 class ;
2004-03-25 09:18:03 +00:00
gboolean pc ;
2004-12-13 08:15:34 +00:00
gint32 tag ;
2004-03-25 09:18:03 +00:00
guint32 len ;
int eoffset ;
int hoffset = offset ;
2006-12-19 22:04:22 +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 ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_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_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
} else {
printf ( " RESTRICTED STRING dissect_ber_octet_string(%s) entered \n " , name ) ;
}
}
# endif
2004-03-25 09:18:03 +00:00
2005-08-18 08:37:31 +00:00
if ( ! implicit_tag ) {
2004-11-14 05:10:44 +00:00
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , NULL ) ;
2004-11-14 05:10:44 +00:00
eoffset = offset + len ;
/* sanity check */
2004-03-25 09:18:03 +00:00
if ( ( class ! = BER_CLASS_UNI )
| | ( tag ! = type ) ) {
2007-07-05 13:14:25 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: String with tag=%d expected but class:%s(%d) %s tag:%d was unexpected " , type , val_to_str ( class , ber_class_codes , " Unknown " ) , class , pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-15 05:49:43 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: String expected " ) ;
2007-07-05 13:14:25 +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 ;
2004-03-25 09:18:03 +00:00
}
}
/* 8.21.3 */
2009-12-18 15:18:31 +00:00
return dissect_ber_constrained_octet_string ( implicit_tag , actx , tree , tvb , hoffset , min_len , max_len , hf_id , out_tvb ) ;
}
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 )
{
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
{
2005-04-13 21:20:23 +00:00
tvbuff_t * out_tvb = NULL ;
2009-04-03 16:53:40 +00:00
gint tvb_len ;
2004-03-25 09:18:03 +00:00
2007-05-15 05:49:43 +00:00
offset = dissect_ber_restricted_string ( FALSE , BER_UNI_TAG_GeneralString , actx , tree , tvb , offset , hf_id , ( name_string ) ? & out_tvb : NULL ) ;
2004-03-25 09:18:03 +00:00
2005-08-18 08:37:31 +00:00
if ( name_string ) {
2009-04-03 16:53:40 +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 ?
*/
if ( out_tvb ) {
tvb_len = tvb_length ( out_tvb ) ;
2009-04-03 17:06:20 +00:00
if ( ( guint ) tvb_len > = name_len ) {
2009-04-03 16:53:40 +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 ' ;
}
2004-03-25 09:18:03 +00:00
}
}
return offset ;
}
2005-10-16 00:36:43 +00:00
/* 8.19 Encoding of an object identifier value.
*/
2007-05-15 05:49:43 +00:00
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 )
2005-11-14 10:02:31 +00:00
{
2004-12-13 08:15:34 +00:00
gint8 class ;
2004-02-20 10:04:10 +00:00
gboolean pc ;
2004-12-13 08:15:34 +00:00
gint32 tag ;
2005-04-28 09:54:03 +00:00
guint32 len ;
2004-03-25 09:18:03 +00:00
int eoffset ;
2007-07-05 13:14:25 +00:00
int hoffset ;
2007-08-25 17:29:55 +00:00
const char * str ;
2006-12-19 22:04:22 +00:00
proto_item * cause ;
2005-12-05 17:24:19 +00:00
header_field_info * hfi ;
2005-12-08 23:21:26 +00:00
const gchar * name ;
2005-12-05 17:24:19 +00:00
2004-11-14 09:45:04 +00:00
# ifdef DEBUG_BER
{
2007-05-02 20:37:25 +00:00
const char * name ;
2004-11-14 09:45:04 +00:00
header_field_info * hfinfo ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-11-14 09:45:04 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( tvb , offset ) > 3 ) {
printf ( " OBJECT IDENTIFIER dissect_ber_object_identifier(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x \n " , name , implicit_tag , offset , tvb_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
} else {
printf ( " OBJECT IDENTIFIER dissect_ber_object_identifier(%s) entered \n " , name ) ;
}
}
# endif
2005-08-18 08:37:31 +00:00
if ( ! implicit_tag ) {
2007-07-05 13:14:25 +00:00
hoffset = offset ;
2004-11-14 05:10:44 +00:00
/* sanity check */
2007-05-15 05:49:43 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
2004-11-14 05:10:44 +00:00
eoffset = offset + len ;
2004-03-25 09:18:03 +00:00
if ( ( class ! = BER_CLASS_UNI )
| | ( tag ! = BER_UNI_TAG_OID ) ) {
2007-07-05 13:14:25 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: Object Identifier expected but class:%s(%d) %s tag:%d was unexpected " , val_to_str ( class , ber_class_codes , " Unknown " ) , class , pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-15 05:49:43 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Object Identifier expected " ) ;
2007-07-05 13:14:25 +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 ;
2004-03-25 09:18:03 +00:00
}
2004-11-14 05:10:44 +00:00
} else {
len = tvb_length_remaining ( tvb , offset ) ;
eoffset = offset + len ;
2004-03-25 09:18:03 +00:00
}
2008-01-04 13:39:24 +00:00
actx - > created_item = NULL ;
2005-12-08 11:27:14 +00:00
hfi = proto_registrar_get_nth ( hf_id ) ;
if ( hfi - > type = = FT_OID ) {
2007-07-26 14:00:48 +00:00
actx - > created_item = proto_tree_add_item ( tree , hf_id , tvb , offset , len , FALSE ) ;
2005-12-08 11:27:14 +00:00
} else if ( IS_FT_STRING ( hfi - > type ) ) {
2007-11-01 22:07:43 +00:00
str = oid_encoded2string ( tvb_get_ptr ( tvb , offset , len ) , len ) ;
2007-07-26 14:00:48 +00:00
actx - > created_item = proto_tree_add_string ( tree , hf_id , tvb , offset , len , str ) ;
if ( actx - > created_item ) {
2005-12-08 23:21:26 +00:00
/* see if we know the name of this oid */
2007-11-01 19:36:39 +00:00
name = oid_resolved_from_encoded ( tvb_get_ptr ( tvb , offset , len ) , len ) ;
2005-12-08 23:21:26 +00:00
if ( name ) {
2007-07-26 14:00:48 +00:00
proto_item_append_text ( actx - > created_item , " (%s) " , name ) ;
2005-12-08 23:21:26 +00:00
}
2005-12-08 11:27:14 +00:00
}
} else {
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
2008-01-04 13:39:24 +00:00
2005-12-08 11:27:14 +00:00
if ( value_tvb )
* value_tvb = tvb_new_subset ( tvb , offset , len , len ) ;
2004-03-25 09:18:03 +00:00
return eoffset ;
}
2008-06-27 04:52:56 +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
{
tvbuff_t * value_tvb = NULL ;
guint length ;
2008-06-27 04:52:56 +00:00
offset = dissect_ber_object_identifier ( implicit_tag , actx , tree , tvb , offset , hf_id , ( value_stringx ) ? & value_tvb : NULL ) ;
2005-11-14 10:02:31 +00:00
2008-06-27 04:52:56 +00:00
if ( value_stringx ) {
2005-11-14 10:02:31 +00:00
if ( value_tvb & & ( length = tvb_length ( value_tvb ) ) ) {
2008-06-27 04:52:56 +00:00
* value_stringx = oid_encoded2string ( tvb_get_ptr ( value_tvb , 0 , length ) , length ) ;
2005-11-14 10:02:31 +00:00
} else {
2008-06-27 04:52:56 +00:00
* value_stringx = " " ;
2005-11-14 10:02:31 +00:00
}
}
return offset ;
}
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
2009-12-18 15:18:31 +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 ) {
2008-06-27 04:52:56 +00:00
gint8 classx ;
gboolean pcx , ind = FALSE , ind_field ;
gint32 tagx ;
guint32 lenx ;
2005-08-18 08:37:31 +00:00
2004-03-25 09:18:03 +00:00
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
2008-06-27 04:52:56 +00:00
proto_item * causex ;
int cnt , hoffsetx , end_offset ;
2004-03-25 09:18:03 +00:00
header_field_info * hfi ;
2008-10-16 10:50:12 +00:00
gint length_remaining ;
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 ;
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-11-14 05:10:44 +00:00
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( tvb , offset ) > 3 ) {
2005-08-18 08:37:31 +00:00
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_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
2004-11-14 05:10:44 +00:00
} else {
2005-08-18 08:37:31 +00:00
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
2004-11-14 05:10:44 +00:00
if ( ! implicit_tag ) {
2008-06-27 04:52:56 +00:00
hoffsetx = offset ;
2005-08-18 08:37:31 +00:00
/* first we must read the sequence header */
2008-06-27 04:52:56 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & classx , & pcx , & tagx ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & lenx , & ind ) ;
2004-11-14 05:10:44 +00:00
if ( ind ) {
/* if the length is indefinite we dont really know (yet) where the
* object ends so assume it spans the rest of the tvb for now .
*/
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx ;
2004-11-14 05:10:44 +00:00
} else {
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx ;
2004-11-14 05:10:44 +00:00
}
2004-02-20 10:04:10 +00:00
2004-11-14 05:10:44 +00:00
/* sanity check: we only handle Constructed Universal Sequences */
2008-06-27 04:52:56 +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 ) ;
causex = proto_tree_add_text ( tree , tvb , offset , lenx , " BER Error: %s Of expected but class:%s(%d) %s tag:%d was unexpected " ,
( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " , val_to_str ( classx , ber_class_codes , " Unknown " ) , classx , pcx ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tagx ) ;
proto_item_set_expert_flags ( causex , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , causex , PI_MALFORMED , PI_WARN , " BER Error: %s Of expected " , ( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " ) ;
2007-07-05 13:14:25 +00:00
if ( decode_unexpected ) {
2008-06-27 04:52:56 +00:00
proto_tree * unknown_tree = proto_item_add_subtree ( causex , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffsetx , unknown_tree ) ;
2007-07-05 13:14:25 +00:00
}
2004-11-14 05:10:44 +00:00
return end_offset ;
}
} else {
2006-03-09 16:00:33 +00:00
/* the tvb length should be correct now nope we could be comming from an implicit choice or sequence, thus we
2005-08-18 08:37:31 +00:00
read the items we match and return the length */
2008-06-27 04:52:56 +00:00
lenx = tvb_length_remaining ( tvb , offset ) ;
end_offset = offset + lenx ;
2004-02-20 10:04:10 +00:00
}
2004-03-25 09:18:03 +00:00
/* count number of items */
cnt = 0 ;
2008-06-27 04:52:56 +00:00
hoffsetx = offset ;
2005-08-29 08:24:15 +00:00
/* 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 */
if ( tvb_length_remaining ( tvb , offset ) = = tvb_reported_length_remaining ( tvb , offset ) ) {
while ( offset < end_offset ) {
guint32 len ;
2006-07-08 01:40:53 +00:00
gint s_offset ;
s_offset = offset ;
2006-03-09 16:00:33 +00:00
2009-10-04 19:25:46 +00:00
/*if(ind){ this sequence of was of indefinite length, if this is implicit indefinite impossible maybe
but ber dissector uses this to eat the tag length then pass into here . . . EOC still on there . . . */
2006-03-09 16:00:33 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
2005-08-29 08:24:15 +00:00
break ;
}
2009-10-04 19:25:46 +00:00
/*}*/
2004-10-24 03:51:27 +00:00
2005-08-29 08:24:15 +00:00
/* read header and len for next field */
offset = get_ber_identifier ( tvb , offset , NULL , NULL , NULL ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind ) ;
2005-08-29 08:24:15 +00:00
/* best place to get real length of implicit sequence of or set of is here... */
/* adjust end_offset if we find somthing that doesnt match */
offset + = len ;
cnt + + ;
2006-07-09 22:12:02 +00:00
if ( offset < = s_offset )
THROW ( ReportedBoundsError ) ;
2005-08-29 08:24:15 +00:00
}
2004-03-25 09:18:03 +00:00
}
2008-06-27 04:52:56 +00:00
offset = hoffsetx ;
2004-03-25 09:18:03 +00:00
2004-02-20 10:04:10 +00:00
/* create subtree */
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-03-25 09:18:03 +00:00
hfi = proto_registrar_get_nth ( hf_id ) ;
2004-02-20 10:04:10 +00:00
if ( parent_tree ) {
2005-08-18 08:37:31 +00:00
if ( hfi - > type = = FT_NONE ) {
2008-06-27 04:52:56 +00:00
item = proto_tree_add_item ( parent_tree , hf_id , tvb , offset , lenx , FALSE ) ;
2004-05-11 10:57:14 +00:00
proto_item_append_text ( item , " : " ) ;
} else {
2008-06-27 04:52:56 +00:00
item = proto_tree_add_uint ( parent_tree , hf_id , tvb , offset , lenx , cnt ) ;
2004-03-25 09:18:03 +00:00
proto_item_append_text ( item , ( cnt = = 1 ) ? " item " : " items " ) ;
}
2004-02-20 10:04:10 +00:00
tree = proto_item_add_subtree ( item , ett_id ) ;
2009-12-18 15:18:31 +00:00
ber_check_items ( cnt , min_len , max_len , actx , item ) ;
2004-02-20 10:04:10 +00:00
}
}
2007-05-22 16:17:54 +00:00
/* loop over all entries until we reach the end of the sequence */
while ( offset < end_offset ) {
gint8 class ;
gboolean pc ;
gint32 tag ;
guint32 len ;
int eoffset ;
int hoffset , count ;
proto_item * cause ;
2007-05-30 19:00:50 +00:00
gboolean imp_tag ;
2007-05-22 16:17:54 +00:00
hoffset = offset ;
2009-10-04 19:25:46 +00:00
/*if(ind){ this sequence was of indefinite length, if this is implicit indefinite impossible maybe
but ber dissector uses this to eat the tag length then pass into here . . . EOC still on there . . . */
2007-05-22 16:17:54 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
if ( show_internal_ber_fields ) {
proto_tree_add_text ( tree , tvb , hoffset , end_offset - hoffset , " SEQ OF EOC " ) ;
}
return offset + 2 ;
}
2009-10-04 19:25:46 +00:00
/*}*/
2007-05-22 16:17:54 +00:00
/* read header and len for next field */
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind_field ) ;
2007-05-22 16:17:54 +00:00
eoffset = offset + len ;
/* Make sure we move forward */
if ( eoffset < = hoffset )
THROW ( ReportedBoundsError ) ;
if ( ( class = = BER_CLASS_UNI ) & & ( tag = = BER_UNI_TAG_EOC ) ) {
/* This is a zero length sequence of*/
hoffset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL , NULL ) ;
hoffset = dissect_ber_length ( actx - > pinfo , tree , tvb , hoffset , NULL , NULL ) ;
return eoffset ;
}
/* verify that this one is the one we want */
/* ahup if we are implicit then we return to the uper layer how much we have used */
if ( seq - > class ! = BER_CLASS_ANY ) {
if ( ( seq - > class ! = class )
| | ( seq - > tag ! = tag ) ) {
if ( ! ( seq - > flags & BER_FLAGS_NOTCHKTAG ) ) {
2007-12-30 00:03:10 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: Wrong field in SQ OF(tag %u expected %u) " , tag , seq - > tag ) ;
2007-05-22 16:17:54 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in Sequence Of " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2007-05-22 16:17:54 +00:00
offset = eoffset ;
continue ;
/* wrong.... */
}
}
}
if ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) & & ! ( seq - > flags & BER_FLAGS_IMPLTAG ) ) {
/* 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 ) ;
}
if ( ( seq - > flags = = BER_FLAGS_IMPLTAG ) & & ( seq - > class = = BER_CLASS_CON ) ) {
/* 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 */
}
2008-10-16 10:50:12 +00:00
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > eoffset - hoffset )
length_remaining = eoffset - hoffset ;
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , eoffset - hoffset ) ;
2007-05-30 19:00:50 +00:00
imp_tag = FALSE ;
if ( seq - > flags = = BER_FLAGS_IMPLTAG )
imp_tag = TRUE ;
2007-05-22 16:17:54 +00:00
/* call the dissector for this field */
2008-10-16 10:50:12 +00:00
count = seq - > func ( imp_tag , next_tvb , 0 , actx , tree , * seq - > p_id ) - hoffset ;
2007-05-22 16:17:54 +00:00
/* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
doesnt match the next item , thus this implicit sequence is over , return the number of bytes
we have eaten to allow the possible upper sequence continue . . . */
cnt + + ; /* rubbish*/
offset = eoffset ;
}
/* if we didnt end up at exactly offset, then we ate too many bytes */
if ( offset ! = end_offset ) {
tvb_ensure_bytes_exist ( tvb , offset - 2 , 2 ) ;
2008-06-27 04:52:56 +00:00
causex = proto_tree_add_text ( tree , tvb , offset - 2 , 2 , " BER Error: %s Of ate %d too many bytes " ,
2007-05-22 16:17:54 +00:00
( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " , offset - end_offset ) ;
2008-06-27 04:52:56 +00:00
proto_item_set_expert_flags ( causex , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , causex , PI_MALFORMED , PI_WARN , " BER Error:too many byte in %s " , ( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " ) ;
2007-05-22 16:17:54 +00:00
}
return end_offset ;
}
static int dissect_ber_old_sq_of ( gboolean implicit_tag , gint32 type , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_old_sequence_t * seq , gint hf_id , gint ett_id ) {
2008-06-27 04:52:56 +00:00
gint8 classx ;
gboolean pcx , ind = FALSE , ind_field ;
gint32 tagx ;
guint32 lenx ;
2007-05-22 16:17:54 +00:00
proto_tree * tree = parent_tree ;
proto_item * item = NULL ;
2008-06-27 04:52:56 +00:00
proto_item * causex ;
int cnt , hoffsetx , end_offset ;
2007-05-22 16:17:54 +00:00
header_field_info * hfi ;
2008-10-16 10:50:12 +00:00
gint length_remaining ;
tvbuff_t * next_tvb ;
2007-05-22 16:17:54 +00:00
# ifdef DEBUG_BER_SQ_OF
{
const char * name ;
header_field_info * hfinfo ;
if ( hf_id > = 0 ) {
hfinfo = proto_registrar_get_nth ( hf_id ) ;
name = hfinfo - > name ;
} else {
name = " unnamed " ;
}
if ( tvb_length_remaining ( tvb , offset ) > 3 ) {
printf ( " SQ OF dissect_ber_old_sq_of(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x \n " , name , implicit_tag , offset , tvb_length_remaining ( tvb , offset ) , tvb_get_guint8 ( tvb , offset ) , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) ) ;
} else {
printf ( " SQ OF dissect_ber_old_sq_of(%s) entered \n " , name ) ;
}
}
# endif
if ( ! implicit_tag ) {
2008-06-27 04:52:56 +00:00
hoffsetx = offset ;
2007-05-22 16:17:54 +00:00
/* first we must read the sequence header */
2008-06-27 04:52:56 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & classx , & pcx , & tagx ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & lenx , & ind ) ;
2007-05-22 16:17:54 +00:00
if ( ind ) {
/* if the length is indefinite we dont really know (yet) where the
* object ends so assume it spans the rest of the tvb for now .
*/
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx ;
2007-05-22 16:17:54 +00:00
} else {
2008-06-27 04:52:56 +00:00
end_offset = offset + lenx ;
2007-05-22 16:17:54 +00:00
}
/* sanity check: we only handle Constructed Universal Sequences */
2008-06-27 04:52:56 +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 ) ;
causex = proto_tree_add_text ( tree , tvb , offset , lenx , " BER Error: %s Of expected but class:%s(%d) %s tag:%d was unexpected " ,
( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " , val_to_str ( classx , ber_class_codes , " Unknown " ) , classx , pcx ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tagx ) ;
proto_item_set_expert_flags ( causex , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , causex , PI_MALFORMED , PI_WARN , " BER Error: %s Of expected " , ( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " ) ;
2007-07-05 13:14:25 +00:00
if ( decode_unexpected ) {
2008-06-27 04:52:56 +00:00
proto_tree * unknown_tree = proto_item_add_subtree ( causex , ett_ber_unknown ) ;
dissect_unknown_ber ( actx - > pinfo , tvb , hoffsetx , unknown_tree ) ;
2007-07-05 13:14:25 +00:00
}
2007-05-22 16:17:54 +00:00
return end_offset ;
}
} else {
/* the tvb length should be correct now nope we could be comming from an implicit choice or sequence, thus we
read the items we match and return the length */
2008-06-27 04:52:56 +00:00
lenx = tvb_length_remaining ( tvb , offset ) ;
end_offset = offset + lenx ;
2007-05-22 16:17:54 +00:00
}
/* count number of items */
cnt = 0 ;
2008-06-27 04:52:56 +00:00
hoffsetx = offset ;
2007-05-22 16:17:54 +00:00
/* 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 */
if ( tvb_length_remaining ( tvb , offset ) = = tvb_reported_length_remaining ( tvb , offset ) ) {
while ( offset < end_offset ) {
guint32 len ;
gint s_offset ;
s_offset = offset ;
if ( ind ) { /* this sequence of was of indefinite length, so check for EOC */
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
break ;
}
}
/* read header and len for next field */
offset = get_ber_identifier ( tvb , offset , NULL , NULL , NULL ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind ) ;
2007-05-22 16:17:54 +00:00
/* best place to get real length of implicit sequence of or set of is here... */
/* adjust end_offset if we find somthing that doesnt match */
offset + = len ;
cnt + + ;
if ( offset < = s_offset )
THROW ( ReportedBoundsError ) ;
}
}
2008-06-27 04:52:56 +00:00
offset = hoffsetx ;
2007-05-22 16:17:54 +00:00
/* create subtree */
if ( hf_id > = 0 ) {
hfi = proto_registrar_get_nth ( hf_id ) ;
if ( parent_tree ) {
if ( hfi - > type = = FT_NONE ) {
2008-06-27 04:52:56 +00:00
item = proto_tree_add_item ( parent_tree , hf_id , tvb , offset , lenx , FALSE ) ;
2007-05-22 16:17:54 +00:00
proto_item_append_text ( item , " : " ) ;
} else {
2008-06-27 04:52:56 +00:00
item = proto_tree_add_uint ( parent_tree , hf_id , tvb , offset , lenx , cnt ) ;
2007-05-22 16:17:54 +00:00
proto_item_append_text ( item , ( cnt = = 1 ) ? " item " : " items " ) ;
}
tree = proto_item_add_subtree ( item , ett_id ) ;
}
}
2004-02-20 10:04:10 +00:00
/* loop over all entries until we reach the end of the sequence */
2004-03-25 09:18:03 +00:00
while ( offset < end_offset ) {
2004-12-13 08:15:34 +00:00
gint8 class ;
2004-03-25 09:18:03 +00:00
gboolean pc ;
2004-12-13 08:15:34 +00:00
gint32 tag ;
2004-03-25 09:18:03 +00:00
guint32 len ;
int eoffset ;
2005-08-18 08:37:31 +00:00
int hoffset , count ;
2006-12-19 22:04:22 +00:00
proto_item * cause ;
2004-03-25 09:18:03 +00:00
2005-08-19 01:56:14 +00:00
hoffset = offset ;
2005-08-18 08:37:31 +00:00
if ( ind ) { /*this sequence of was of indefinite length, so check for EOC */
2004-10-24 03:51:27 +00:00
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) ) {
if ( show_internal_ber_fields ) {
2005-08-18 08:37:31 +00:00
proto_tree_add_text ( tree , tvb , hoffset , end_offset - hoffset , " SEQ OF EOC " ) ;
2004-10-24 03:51:27 +00:00
}
return offset + 2 ;
}
}
2004-03-25 09:18:03 +00:00
/* read header and len for next field */
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
2007-08-24 07:12:04 +00:00
offset = get_ber_length ( tvb , offset , & len , & ind_field ) ;
2006-07-07 15:13:11 +00:00
eoffset = offset + len ;
2006-07-07 20:11:06 +00:00
/* Make sure we move forward */
2006-07-09 22:12:02 +00:00
if ( eoffset < = hoffset )
THROW ( ReportedBoundsError ) ;
2004-03-25 09:18:03 +00:00
2006-09-24 21:04:53 +00:00
if ( ( class = = BER_CLASS_UNI ) & & ( tag = = BER_UNI_TAG_EOC ) ) {
/* This is a zero length sequence of*/
2007-05-13 20:58:29 +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 ) ;
2006-09-24 21:04:53 +00:00
return eoffset ;
}
2004-03-25 09:18:03 +00:00
/* verify that this one is the one we want */
2005-08-18 08:37:31 +00:00
/* ahup if we are implicit then we return to the uper layer how much we have used */
2004-11-14 09:45:04 +00:00
if ( seq - > class ! = BER_CLASS_ANY ) {
2005-08-18 08:37:31 +00:00
if ( ( seq - > class ! = class )
2004-03-25 09:18:03 +00:00
| | ( seq - > tag ! = tag ) ) {
2005-08-18 08:37:31 +00:00
if ( ! ( seq - > flags & BER_FLAGS_NOTCHKTAG ) ) {
2006-12-19 22:04:22 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: Wrong field in SQ OF " ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-13 20:58:29 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: Wrong field in Sequence Of " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2004-03-25 09:18:03 +00:00
offset = eoffset ;
continue ;
2005-08-18 08:37:31 +00:00
/* wrong.... */
2004-03-25 09:18:03 +00:00
}
2004-11-14 09:45:04 +00:00
}
2004-03-25 09:18:03 +00:00
}
2005-08-18 08:37:31 +00:00
if ( ! ( seq - > flags & BER_FLAGS_NOOWNTAG ) & & ! ( seq - > flags & BER_FLAGS_IMPLTAG ) ) {
2004-03-25 09:18:03 +00:00
/* dissect header and len for field */
2007-05-13 20:58:29 +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 ) ;
2004-03-25 09:18:03 +00:00
}
2007-01-10 22:59:40 +00:00
if ( ( seq - > flags = = BER_FLAGS_IMPLTAG ) & & ( seq - > class = = BER_CLASS_CON ) ) {
/* Constructed sequence of with a tag */
/* dissect header and len for field */
2007-05-13 20:58:29 +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 ) ;
2007-01-10 22:59:40 +00:00
}
2006-03-09 16:00:33 +00:00
2008-10-16 10:50:12 +00:00
length_remaining = tvb_length_remaining ( tvb , hoffset ) ;
if ( length_remaining > eoffset - hoffset )
length_remaining = eoffset - hoffset ;
next_tvb = tvb_new_subset ( tvb , hoffset , length_remaining , eoffset - hoffset ) ;
2004-02-20 10:04:10 +00:00
/* call the dissector for this field */
2007-05-13 20:58:29 +00:00
count = seq - > func ( tree , tvb , hoffset , actx ) - hoffset ;
2006-03-09 16:00:33 +00:00
/* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
2005-08-18 08:37:31 +00:00
doesnt match the next item , thus this implicit sequence is over , return the number of bytes
we have eaten to allow the possible upper sequence continue . . . */
2005-08-29 08:24:15 +00:00
cnt + + ; /* rubbish*/
2006-07-07 15:13:11 +00:00
offset = eoffset ;
2004-02-20 10:04:10 +00:00
}
/* if we didnt end up at exactly offset, then we ate too many bytes */
2005-08-18 08:37:31 +00:00
if ( offset ! = end_offset ) {
2005-04-14 20:01:14 +00:00
tvb_ensure_bytes_exist ( tvb , offset - 2 , 2 ) ;
2008-06-27 04:52:56 +00:00
causex = proto_tree_add_text ( tree , tvb , offset - 2 , 2 , " BER Error: %s Of ate %d too many bytes " ,
2004-03-25 09:18:03 +00:00
( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " , offset - end_offset ) ;
2008-06-27 04:52:56 +00:00
proto_item_set_expert_flags ( causex , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , causex , PI_MALFORMED , PI_WARN , " BER Error:too many byte in %s " , ( type = = BER_UNI_TAG_SEQUENCE ) ? " Set " : " Sequence " ) ;
2004-02-20 10:04:10 +00:00
}
return end_offset ;
}
2009-12-18 15:18:31 +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 ) {
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 ) ;
}
2007-05-13 20:58:29 +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 ) {
2009-12-18 15:18:31 +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 ) ;
}
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 ) {
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
}
2007-05-13 20:58:29 +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 ) {
2009-12-18 15:18:31 +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
2007-05-22 16:17:54 +00:00
int dissect_ber_old_sequence_of ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_old_sequence_t * seq , gint hf_id , gint ett_id ) {
return dissect_ber_old_sq_of ( implicit_tag , BER_UNI_TAG_SEQUENCE , actx , parent_tree , tvb , offset , seq , hf_id , ett_id ) ;
}
int dissect_ber_old_set_of ( gboolean implicit_tag , asn1_ctx_t * actx , proto_tree * parent_tree , tvbuff_t * tvb , int offset , const ber_old_sequence_t * seq , gint hf_id , gint ett_id ) {
return dissect_ber_old_sq_of ( implicit_tag , BER_UNI_TAG_SET , actx , parent_tree , tvb , offset , seq , hf_id , ett_id ) ;
}
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
{
2008-01-12 12:06:56 +00:00
char str [ 35 ] ;
2004-02-20 10:04:10 +00:00
const guint8 * tmpstr ;
2008-01-12 12:06:56 +00:00
char * strptr ;
char first_delim [ 2 ] ;
int first_digits ;
char second_delim [ 2 ] ;
int second_digits ;
2004-12-13 08:15:34 +00:00
gint8 class ;
2004-02-20 10:04:10 +00:00
gboolean pc ;
2004-12-13 08:15:34 +00:00
gint32 tag ;
2004-02-20 10:04:10 +00:00
guint32 len ;
int end_offset ;
2007-07-05 13:14:25 +00:00
int hoffset ;
2006-12-19 22:04:22 +00:00
proto_item * cause ;
2004-02-20 10:04:10 +00:00
2004-12-12 22:47:24 +00:00
if ( ! implicit_tag ) {
2007-07-05 13:14:25 +00:00
hoffset = offset ;
2007-05-15 05:49:43 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
2004-12-12 22:47:24 +00:00
end_offset = offset + len ;
2004-02-20 10:04:10 +00:00
2004-12-12 22:47:24 +00:00
/* sanity check. we only handle universal/generalized time */
if ( ( class ! = BER_CLASS_UNI )
2004-03-25 23:57:10 +00:00
| | ( tag ! = BER_UNI_TAG_GeneralizedTime ) ) {
2007-07-05 13:14:25 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( tree , tvb , offset , len , " BER Error: GeneralizedTime expected but class:%s(%d) %s tag:%d was unexpected " , val_to_str ( class , ber_class_codes , " Unknown " ) , class , pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-15 05:49:43 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: GeneralizedTime expected " ) ;
2007-07-05 13:14:25 +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 ) ;
}
2004-02-20 10:04:10 +00:00
return end_offset ;
2004-12-12 22:47:24 +00:00
}
} else {
len = tvb_length_remaining ( tvb , offset ) ;
end_offset = offset + len ;
2004-02-20 10:04:10 +00:00
}
2006-03-09 16:00:33 +00:00
2004-02-20 10:04:10 +00:00
tmpstr = tvb_get_ptr ( tvb , offset , len ) ;
2008-01-12 12:06: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 ) ;
first_delim [ 0 ] = 0 ;
second_delim [ 0 ] = 0 ;
sscanf ( tmpstr , " %*14d%1[.,+-Z]%4d%1[+-Z]%4d " , first_delim , & first_digits , second_delim , & second_digits ) ;
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 ;
}
2006-03-09 16:00:33 +00:00
2005-09-01 19:35:23 +00:00
if ( hf_id > = 0 ) {
2004-02-20 10:04:10 +00:00
proto_tree_add_string ( tree , hf_id , tvb , offset , len , str ) ;
}
offset + = len ;
return offset ;
}
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 )
{
char outstr [ 33 ] ;
char * outstrptr = outstr ;
const guint8 * instr ;
gint8 class ;
gboolean pc ;
gint32 tag ;
guint32 len , i , n ;
int hoffset ;
proto_item * cause ;
if ( ! implicit_tag ) {
hoffset = offset ;
offset = dissect_ber_identifier ( actx - > pinfo , tree , tvb , offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , tree , tvb , offset , & len , NULL ) ;
/* sanity check: we only handle UTCTime */
if ( ( class ! = BER_CLASS_UNI ) | | ( tag ! = BER_UNI_TAG_UTCTime ) ) {
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
cause = proto_tree_add_text ( tree , tvb , offset , len ,
" BER Error: UTCTime expected but class:%s(%d) %s tag:%d was unexpected " ,
val_to_str ( class , ber_class_codes , " Unknown " ) , class ,
pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tag ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: UTCTime expected " ) ;
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 {
len = tvb_length_remaining ( tvb , offset ) ;
}
instr = tvb_get_ptr ( tvb , offset , len ) ;
/* YYMMDDhhmm */
for ( i = 0 ; i < 10 ; i + + ) {
if ( instr [ i ] < ' 0 ' | | instr [ i ] > ' 9 ' ) {
cause = proto_tree_add_text ( tree , tvb , offset , len ,
" BER Error: malformed UTCTime encoding, "
" first 10 octets have to contain YYMMDDhhmm in digits " ) ;
goto malformed ;
}
}
g_snprintf ( outstrptr , 15 , " %.2s-%.2s-%.2s %.2s:%.2s " , instr , instr + 2 , instr + 4 , instr + 6 , instr + 8 ) ;
outstrptr + = 14 ;
/* (ss)? */
if ( len > = 12 ) {
if ( instr [ i ] > = ' 0 ' & & instr [ i ] < = ' 9 ' ) {
i + + ;
if ( instr [ i ] > = ' 0 ' & & instr [ i ] < = ' 9 ' ) {
i + + ;
g_snprintf ( outstrptr , 4 , " :%.2s " , instr + 10 ) ;
outstrptr + = 3 ;
} else {
cause = proto_tree_add_text ( tree , tvb , offset , len ,
" BER Error: malformed UTCTime encoding, "
" if 11th octet is a digit for seconds, "
" the 12th octet has to be a digit, too " ) ;
goto malformed ;
}
}
}
/* Z|([+-]hhmm) */
switch ( instr [ i ] ) {
case ' Z ' :
if ( len ! = i + 1 ) {
cause = proto_tree_add_text ( tree , tvb , offset , len ,
" BER Error: malformed UTCTime encoding, "
" there must be no further octets after \' Z \' " ) ;
goto malformed ;
}
g_snprintf ( outstrptr , 7 , " (UTC) " ) ;
i + + ;
break ;
case ' - ' :
case ' + ' :
if ( len ! = i + 5 ) {
cause = proto_tree_add_text ( tree , tvb , offset , len ,
" BER Error: malformed UTCTime encoding, "
" 4 digits must follow on \' + \' resp. \' - \' " ) ;
goto malformed ;
}
for ( n = i + 1 ; n < i + 5 ; n + + ) {
if ( instr [ n ] < ' 0 ' | | instr [ n ] > ' 9 ' ) {
cause = proto_tree_add_text ( tree , tvb , offset , len ,
" BER Error: malformed UTCTime encoding, "
" 4 digits must follow on \' + \' resp. \' - \' " ) ;
goto malformed ;
}
}
g_snprintf ( outstrptr , 12 , " (UTC%c%.4s) " , instr [ i ] , instr + i + 1 ) ;
i + = 5 ;
break ;
default :
cause = proto_tree_add_text ( tree , tvb , offset , len ,
" BER Error: malformed UTCTime encoding, "
" unexpected character in %dth octet, "
" must be \' Z \' , \' + \' or \' - \' " , i + 1 ) ;
goto malformed ;
break ;
}
if ( len ! = i ) {
cause = proto_tree_add_text ( tree , tvb , offset , len ,
" BER Error: malformed UTCTime encoding, "
" %d unexpected character%s after %dth octet " ,
len - i , ( len = = i - 1 ? " s " : " " ) , i ) ;
goto malformed ;
}
if ( hf_id > = 0 ) {
proto_tree_add_string ( tree , hf_id , tvb , offset , len , outstr ) ;
}
return offset + len ;
malformed :
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: malformed UTCTime encoding " ) ;
g_snprintf ( outstr , ( len > 29 ) ? 31 : len + 1 , " %s " , instr ) ;
if ( hf_id > = 0 ) {
proto_tree_add_string ( tree , hf_id , tvb , offset , len , outstr ) ;
}
return offset + len ;
}
2004-03-25 09:18:03 +00:00
/* 8.6 Encoding of a bitstring value */
2010-01-19 08:54:13 +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
{
2004-12-13 08:15:34 +00:00
gint8 class ;
2004-03-25 09:18:03 +00:00
gboolean pc , ind ;
2004-12-13 08:15:34 +00:00
gint32 tag ;
2010-01-18 20:08:56 +00:00
guint32 len , byteno ;
guint8 pad = 0 , b0 , b1 , val , * bitstring ;
2004-02-20 10:04:10 +00:00
int end_offset ;
2007-07-05 13:14:25 +00:00
int hoffset ;
2004-03-25 09:18:03 +00:00
proto_item * item = NULL ;
2006-12-19 22:04:22 +00:00
proto_item * cause ;
2004-03-25 09:18:03 +00:00
proto_tree * tree = NULL ;
2004-10-08 21:14:33 +00:00
const asn_namedbit * nb ;
2007-04-23 10:59:26 +00:00
const char * sep ;
2004-05-11 07:26:45 +00:00
gboolean term ;
2004-02-20 10:04:10 +00:00
2004-11-14 05:10:44 +00:00
if ( ! implicit_tag ) {
2007-07-05 13:14:25 +00:00
hoffset = offset ;
2004-11-14 05:10:44 +00:00
/* read header and len for the octet string */
2007-05-15 05:49:43 +00:00
offset = dissect_ber_identifier ( actx - > pinfo , parent_tree , tvb , offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( actx - > pinfo , parent_tree , tvb , offset , & len , & ind ) ;
2004-11-14 05:10:44 +00:00
end_offset = offset + len ;
2004-02-20 10:04:10 +00:00
2010-01-05 11:38:33 +00:00
/* sanity check: we only handle Universal BitStrings */
2006-03-25 16:32:46 +00:00
/* 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 . */
2006-07-05 21:33:01 +00:00
2006-03-25 16:32:46 +00:00
if ( ! implicit_tag & & ( class ! = BER_CLASS_APP ) ) {
2004-03-25 09:18:03 +00:00
if ( ( class ! = BER_CLASS_UNI )
| | ( tag ! = BER_UNI_TAG_BITSTRING ) ) {
2007-07-05 13:14:25 +00:00
tvb_ensure_bytes_exist ( tvb , hoffset , 2 ) ;
2007-11-19 20:23:49 +00:00
cause = proto_tree_add_text ( parent_tree , tvb , offset , len , " BER Error: BitString expected but class:%s(%d) %s tag:%d was unexpected " , val_to_str ( class , ber_class_codes , " Unknown " ) , class , pc ? ber_pc_codes_short . true_string : ber_pc_codes_short . false_string , tag ) ;
2006-12-19 22:04:22 +00:00
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2007-05-15 05:49:43 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN , " BER Error: BitString expected " ) ;
2007-07-05 13:14:25 +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 ;
2004-02-20 10:04:10 +00:00
}
2004-11-14 05:10:44 +00:00
}
} else {
pc = 0 ;
len = tvb_length_remaining ( tvb , offset ) ;
end_offset = offset + len ;
2004-02-20 10:04:10 +00:00
}
2008-01-04 13:39:24 +00:00
actx - > created_item = NULL ;
2004-02-20 10:04:10 +00:00
2005-08-18 08:37:31 +00:00
if ( pc ) {
2004-03-25 09:18:03 +00:00
/* constructed */
/* TO DO */
} else {
/* primitive */
pad = tvb_get_guint8 ( tvb , offset ) ;
2007-02-17 14:23:09 +00:00
if ( pad = = 0 & & len = = 1 ) {
/* empty */
proto_tree_add_item ( parent_tree , hf_ber_bitstring_empty , tvb , offset , 1 , FALSE ) ;
} else {
/* padding */
proto_tree_add_item ( parent_tree , hf_ber_bitstring_padding , tvb , offset , 1 , FALSE ) ;
}
2004-02-20 10:04:10 +00:00
offset + + ;
2004-03-25 09:18:03 +00:00
len - - ;
2010-01-05 11:38:33 +00:00
if ( hf_id > = 0 ) {
2004-03-25 09:18:03 +00:00
item = proto_tree_add_item ( parent_tree , hf_id , tvb , offset , len , FALSE ) ;
2010-01-05 11:38:33 +00:00
actx - > created_item = item ;
2005-08-18 08:37:31 +00:00
if ( ett_id ! = - 1 ) {
2004-03-25 09:18:03 +00:00
tree = proto_item_add_subtree ( item , ett_id ) ;
2004-02-20 10:04:10 +00:00
}
}
2005-08-18 08:37:31 +00:00
if ( out_tvb ) {
2004-12-13 08:15:34 +00:00
if ( len < = ( guint32 ) tvb_length_remaining ( tvb , offset ) ) {
2004-11-30 03:39:34 +00:00
* out_tvb = tvb_new_subset ( tvb , offset , len , len ) ;
} else {
2009-08-16 12:36:22 +00:00
* out_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
2004-11-30 03:39:34 +00:00
}
2004-03-25 09:18:03 +00:00
}
}
2004-02-20 10:04:10 +00:00
2005-08-18 08:37:31 +00:00
if ( named_bits ) {
2004-05-11 07:26:45 +00:00
sep = " ( " ;
term = FALSE ;
2004-03-25 09:18:03 +00:00
nb = named_bits ;
2010-01-18 20:08:56 +00:00
bitstring = tvb_get_ephemeral_string ( tvb , offset , len ) ;
2004-03-25 09:18:03 +00:00
while ( nb - > p_id ) {
2005-08-18 08:37:31 +00:00
if ( nb - > bit < ( 8 * len - pad ) ) {
2004-03-25 09:18:03 +00:00
val = tvb_get_guint8 ( tvb , offset + nb - > bit / 8 ) ;
2010-01-18 20:08:56 +00:00
bitstring [ ( nb - > bit / 8 ) ] & = ~ ( 0x80 > > ( nb - > bit % 8 ) ) ;
2004-03-25 09:18:03 +00:00
val & = 0x80 > > ( nb - > bit % 8 ) ;
2004-05-03 22:55:36 +00:00
b0 = ( nb - > gb0 = = - 1 ) ? nb - > bit / 8 :
( ( guint32 ) nb - > gb0 ) / 8 ;
b1 = ( nb - > gb1 = = - 1 ) ? nb - > bit / 8 :
( ( guint32 ) nb - > gb1 ) / 8 ;
2004-03-25 09:18:03 +00:00
proto_tree_add_item ( tree , * ( nb - > p_id ) , tvb , offset + b0 , b1 - b0 + 1 , FALSE ) ;
} else { /* 8.6.2.4 */
val = 0 ;
proto_tree_add_boolean ( tree , * ( nb - > p_id ) , tvb , offset + len , 0 , 0x00 ) ;
2004-02-20 10:04:10 +00:00
}
2005-08-18 08:37:31 +00:00
if ( val ) {
2005-08-27 18:16:35 +00:00
if ( item & & nb - > tstr ) {
2004-05-11 07:26:45 +00:00
proto_item_append_text ( item , " %s%s " , sep , nb - > tstr ) ;
2005-08-27 18:44:57 +00:00
sep = " , " ;
2005-08-27 18:16:35 +00:00
term = TRUE ;
}
2004-03-25 09:18:03 +00:00
} else {
2005-08-27 18:16:35 +00:00
if ( item & & nb - > fstr ) {
2004-05-11 07:26:45 +00:00
proto_item_append_text ( item , " %s%s " , sep , nb - > fstr ) ;
2005-08-27 18:44:57 +00:00
sep = " , " ;
2005-08-27 18:16:35 +00:00
term = TRUE ;
}
2004-03-25 09:18:03 +00:00
}
nb + + ;
2004-02-20 10:04:10 +00:00
}
2005-08-18 08:37:31 +00:00
if ( term )
2004-05-11 07:26:45 +00:00
proto_item_append_text ( item , " ) " ) ;
2010-01-18 20:08:56 +00:00
for ( byteno = 0 ; byteno < len ; byteno + + ) {
if ( bitstring [ byteno ] ) {
2010-01-19 08:11:23 +00:00
expert_add_info_format ( actx - > pinfo , item , PI_UNDECODED , PI_WARN ,
2010-01-18 20:08:56 +00:00
" Unknown bit(s): 0x%s " , bytes_to_str ( bitstring , len ) ) ;
break ;
}
}
2004-02-20 10:04:10 +00:00
}
2010-01-19 08:54:13 +00:00
ber_check_length ( 8 * len - pad , min_len , max_len , actx , item , TRUE ) ;
2004-02-20 10:04:10 +00:00
return end_offset ;
}
2010-01-05 11:38:33 +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 )
{
return dissect_ber_constrained_bitstring ( implicit_tag , actx , parent_tree , tvb , offset , - 1 , - 1 , named_bits , hf_id , ett_id , out_tvb ) ;
}
2007-05-15 05:49:43 +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
{
2005-04-15 14:18:08 +00:00
tvbuff_t * tmp_tvb = NULL ;
2004-03-25 09:18:03 +00:00
proto_tree * tree ;
guint32 val ;
int * * bf ;
header_field_info * hfi ;
2007-04-23 10:59:26 +00:00
const char * sep ;
2004-05-11 07:26:45 +00:00
gboolean term ;
2004-05-26 11:25:20 +00:00
unsigned int i , tvb_len ;
2004-02-20 10:04:10 +00:00
2007-05-15 05:49:43 +00:00
offset = dissect_ber_bitstring ( implicit_tag , actx , parent_tree , tvb , offset , NULL , hf_id , ett_id , & tmp_tvb ) ;
2006-03-09 16:00:33 +00:00
2008-01-04 13:39:24 +00:00
tree = proto_item_get_subtree ( actx - > created_item ) ;
2005-08-18 08:37:31 +00:00
if ( bit_fields & & tree & & tmp_tvb ) {
2004-05-26 11:25:20 +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 .
*/
val = 0 ;
tvb_len = tvb_length ( tmp_tvb ) ;
for ( i = 0 ; i < 4 ; i + + ) {
val < < = 8 ;
if ( i < tvb_len ) {
val | = tvb_get_guint8 ( tmp_tvb , i ) ;
}
}
2004-03-25 09:18:03 +00:00
bf = bit_fields ;
2004-05-11 07:26:45 +00:00
sep = " ( " ;
term = FALSE ;
2004-03-25 09:18:03 +00:00
while ( * bf ) {
2004-05-26 11:25:20 +00:00
proto_tree_add_boolean ( tree , * * bf , tmp_tvb , 0 , tvb_len , val ) ;
2005-09-01 19:35:23 +00:00
if ( * * bf > = 0 ) {
hfi = proto_registrar_get_nth ( * * bf ) ;
if ( val & hfi - > bitmask ) {
2008-01-04 13:39:24 +00:00
proto_item_append_text ( actx - > created_item , " %s%s " , sep , hfi - > name ) ;
2005-09-01 19:35:23 +00:00
sep = " , " ;
term = TRUE ;
}
2004-05-11 07:26:45 +00:00
}
2004-03-25 09:18:03 +00:00
bf + + ;
}
2005-08-18 08:37:31 +00:00
if ( term )
2008-01-04 13:39:24 +00:00
proto_item_append_text ( actx - > created_item , " ) " ) ;
2004-03-25 09:18:03 +00:00
}
2005-08-18 08:37:31 +00:00
if ( out_tvb )
2004-03-25 09:18:03 +00:00
* out_tvb = tmp_tvb ;
return offset ;
}
2004-02-20 10:04:10 +00:00
2007-05-03 21:52:57 +00:00
/*
2007-05-04 20:27:43 +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 :
*
* [ 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 } }
*
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
dissect_ber_INTEGER ( gboolean implicit_tag _U_ , tvbuff_t * tvb _U_ , int offset _U_ , asn1_ctx_t * actx _U_ , proto_tree * tree _U_ , int hf_index _U_ ) {
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
2007-11-21 23:33:13 +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_ )
{
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 ) ) {
offset = call_ber_oid_callback ( actx - > external . direct_reference , tvb , offset , actx - > pinfo , tree ) ;
} 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
return offset ;
}
2007-05-22 21:15:00 +00:00
static int
2007-11-21 23:33:13 +00:00
dissect_ber_OBJECT_IDENTIFIER ( 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-06-14 05:17:07 +00:00
offset = dissect_ber_object_identifier_str ( implicit_tag , actx , tree , tvb , offset , hf_index , & actx - > external . direct_reference ) ;
2007-11-14 20:57:55 +00:00
actx - > external . direct_ref_present = TRUE ;
2007-05-03 21:52:57 +00:00
return offset ;
}
2007-05-22 21:15:00 +00:00
static int
2007-11-21 23:33:13 +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-05-22 21:15:00 +00:00
offset = dissect_ber_restricted_string ( implicit_tag , BER_UNI_TAG_ObjectDescriptor ,
2007-11-21 23:33:13 +00:00
actx , tree , tvb , offset , hf_index ,
& actx - > external . data_value_descriptor ) ;
2007-05-03 21:52:57 +00:00
2007-05-22 21:15:00 +00:00
return offset ;
2007-05-03 21:52:57 +00:00
}
2007-05-22 21:15:00 +00:00
static int
2007-11-21 23:33:13 +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_ )
{
if ( actx - > external . u . ber . ber_callback ) {
offset = actx - > external . u . ber . ber_callback ( FALSE , tvb , offset , actx , tree , hf_index ) ;
} else {
offset = call_ber_oid_callback ( actx - > external . direct_reference , tvb , offset , actx - > pinfo , tree ) ;
}
2007-06-14 05:17:07 +00:00
2007-11-21 23:33:13 +00:00
return offset ;
2007-05-03 21:52:57 +00:00
}
2007-05-22 21:15:00 +00:00
static int
2007-11-21 23:33:13 +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_ )
{
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
2007-05-22 21:15:00 +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 [ ] = {
{ 0 , " single-ASN1-type " } ,
{ 1 , " octet-aligned " } ,
{ 2 , " arbitrary " } ,
{ 0 , NULL }
} ;
2007-05-22 21:15:00 +00:00
static const ber_choice_t T_encoding_choice [ ] = {
{ 0 , & hf_ber_single_ASN1_type , BER_CLASS_CON , 0 , 0 , dissect_ber_T_single_ASN1_type } ,
2007-11-21 23:33:13 +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 } ,
2007-05-22 21:15:00 +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
dissect_ber_T_encoding ( 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-05-15 05:49:43 +00:00
offset = dissect_ber_choice ( actx , tree , tvb , offset ,
2007-05-22 21:15:00 +00:00
T_encoding_choice , hf_index , ett_ber_T_encoding ,
2007-06-14 05:17:07 +00:00
& actx - > external . encoding ) ;
2007-05-03 21:52:57 +00:00
return offset ;
}
2007-05-22 21:15:00 +00:00
static const ber_sequence_t external_U_sequence [ ] = {
{ & 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 } ,
{ & hf_ber_data_value_descriptor , BER_CLASS_UNI , BER_UNI_TAG_ObjectDescriptor , BER_FLAGS_OPTIONAL | BER_FLAGS_NOOWNTAG , dissect_ber_ObjectDescriptor } ,
{ & hf_ber_encoding , BER_CLASS_ANY /*choice*/ , - 1 /*choice*/ , BER_FLAGS_NOOWNTAG | BER_FLAGS_NOTCHKTAG , dissect_ber_T_encoding } ,
{ 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
{
2007-05-22 21:15:00 +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
2007-05-22 21:15:00 +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
2007-07-13 11:25:53 +00:00
actx - > external . u . ber . ber_callback = func ;
2007-05-06 22:34:05 +00:00
2007-11-21 23:33:13 +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
asn1_ctx_clean_external ( actx ) ;
return offset ;
}
2007-06-03 19:58:59 +00:00
/* Experimental */
int
2007-06-03 21:10:29 +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
offset = dissect_ber_tagged_type ( implicit_tag , actx , tree , tvb , offset ,
2007-07-05 13:14:25 +00:00
hf_id , BER_CLASS_UNI , BER_UNI_TAG_EMBEDDED_PDV , TRUE , dissect_ber_external_U ) ;
2007-06-03 19:58:59 +00:00
return offset ;
}
2007-05-06 22:34:05 +00:00
2006-05-08 19:56:36 +00:00
static void
dissect_ber ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
{
2007-01-13 12:59:27 +00:00
const char * name ;
2006-05-08 19:56:36 +00:00
2009-08-09 06:26:46 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " BER " ) ;
2006-05-08 19:56:36 +00:00
2009-08-09 07:14:16 +00:00
col_set_str ( pinfo - > cinfo , COL_DEF_SRC , " BER encoded file " ) ;
2006-05-08 19:56:36 +00:00
2007-01-13 12:59:27 +00:00
if ( ! decode_as_syntax ) {
/* if we got here we couldn't find anything better */
2010-01-13 20:25:10 +00:00
col_set_str ( pinfo - > cinfo , COL_INFO , " Unknown BER " ) ;
2007-01-13 12:59:27 +00:00
( void ) dissect_unknown_ber ( pinfo , tvb , 0 , tree ) ;
} else {
( void ) call_ber_syntax_callback ( decode_as_syntax , tvb , 0 , pinfo , tree ) ;
2007-02-04 12:00:25 +00:00
if ( check_col ( pinfo - > cinfo , COL_INFO ) ) {
2006-05-08 19:56:36 +00:00
2007-01-13 12:59:27 +00:00
/* see if we have a better name */
name = get_ber_oid_syntax ( decode_as_syntax ) ;
2010-01-13 20:25:10 +00:00
col_add_fstr ( pinfo - > cinfo , COL_INFO , " Decoded as %s " , name ? name : decode_as_syntax ) ;
2007-01-13 12:59:27 +00:00
}
}
}
2006-05-08 19:56:36 +00:00
2004-02-20 10:04:10 +00:00
void
proto_register_ber ( void )
{
static hf_register_info hf [ ] = {
{ & 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 ,
2008-12-18 19:08:49 +00:00
NULL , 0x0 , " Number of unused bits in the last octet of the bitstring " , HFILL } } ,
2007-02-17 14:23:09 +00:00
{ & hf_ber_bitstring_empty , {
" Empty " , " ber.bitstring.empty " , FT_UINT8 , BASE_DEC ,
NULL , 0x0 , " This is an empty bitstring " , HFILL } } ,
2004-02-20 10:04:10 +00:00
{ & 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 ,
VALS ( ber_uni_tag_codes ) , 0x1f , " Universal tag type " , HFILL } } ,
2005-09-18 16:54:00 +00:00
{ & hf_ber_id_uni_tag_ext , {
" Tag " , " ber.id.uni_tag " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Universal tag type " , HFILL } } ,
2004-02-20 10:04:10 +00:00
{ & hf_ber_id_tag , {
2005-09-18 16:54:00 +00:00
" Tag " , " ber.id.tag " , FT_UINT8 , BASE_DEC ,
NULL , 0x1f , " Tag value for non-Universal classes " , HFILL } } ,
{ & hf_ber_id_tag_ext , {
2004-02-20 10:04:10 +00:00
" 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 } } ,
2004-11-25 22:27:52 +00:00
{ & hf_ber_unknown_OCTETSTRING , {
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
" OCTETSTRING " , " ber.unknown.OCTETSTRING " , FT_BYTES , BASE_NONE ,
2004-11-25 22:27:52 +00:00
NULL , 0 , " This is an unknown OCTETSTRING " , HFILL } } ,
2007-02-17 11:10:02 +00:00
{ & hf_ber_unknown_BER_OCTETSTRING , {
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
" OCTETSTRING [BER encoded] " , " ber.unknown.OCTETSTRING " , FT_NONE , BASE_NONE ,
2007-02-17 11:10:02 +00:00
NULL , 0 , " This is an BER encoded OCTETSTRING " , HFILL } } ,
2004-11-25 22:27:52 +00:00
{ & hf_ber_unknown_OID , {
2006-05-10 19:50:54 +00:00
" OID " , " ber.unknown.OID " , FT_OID , BASE_NONE ,
2004-11-25 22:27:52 +00:00
NULL , 0 , " This is an unknown Object Identifier " , HFILL } } ,
2007-02-17 11:10:02 +00:00
{ & hf_ber_unknown_GraphicString , {
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
" GRAPHICSTRING " , " ber.unknown.GRAPHICSTRING " , FT_STRING , BASE_NONE ,
2005-08-18 08:37:31 +00:00
NULL , 0 , " This is an unknown GRAPHICSTRING " , HFILL } } ,
2004-12-12 22:59:43 +00:00
{ & hf_ber_unknown_NumericString , {
" NumericString " , " ber.unknown.NumericString " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown NumericString " , HFILL } } ,
2004-11-18 10:46:27 +00:00
{ & hf_ber_unknown_PrintableString , {
2004-11-25 21:30:38 +00:00
" PrintableString " , " ber.unknown.PrintableString " , FT_STRING , BASE_NONE ,
2004-11-18 10:46:27 +00:00
NULL , 0 , " This is an unknown PrintableString " , HFILL } } ,
2005-12-14 20:45:15 +00:00
{ & hf_ber_unknown_TeletexString , {
" TeletexString " , " ber.unknown.TeletexString " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown TeletexString " , HFILL } } ,
2007-02-17 11:10:02 +00:00
{ & 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 } } ,
2007-08-18 17:39:44 +00:00
{ & 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 } } ,
2004-11-25 21:30:38 +00:00
{ & hf_ber_unknown_IA5String , {
" IA5String " , " ber.unknown.IA5String " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown IA5String " , HFILL } } ,
2005-12-14 20:45:15 +00:00
{ & hf_ber_unknown_UTCTime , {
" UTCTime " , " ber.unknown.UTCTime " , FT_STRING , BASE_NONE ,
NULL , 0 , " This is an unknown UTCTime " , HFILL } } ,
2005-10-27 11:27:40 +00:00
{ & 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 } } ,
2004-11-18 10:46:27 +00:00
{ & hf_ber_unknown_INTEGER , {
2004-11-25 21:30:38 +00:00
" INTEGER " , " ber.unknown.INTEGER " , FT_UINT32 , BASE_DEC ,
2004-11-18 10:46:27 +00:00
NULL , 0 , " This is an unknown INTEGER " , HFILL } } ,
2005-12-14 20:45:15 +00:00
{ & hf_ber_unknown_BITSTRING , {
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
" BITSTRING " , " ber.unknown.BITSTRING " , FT_BYTES , BASE_NONE ,
2005-12-14 20:45:15 +00:00
NULL , 0 , " This is an unknown BITSTRING " , HFILL } } ,
2005-10-27 11:27:40 +00:00
{ & hf_ber_unknown_BOOLEAN , {
" BOOLEAN " , " ber.unknown.BOOLEAN " , FT_UINT8 , BASE_HEX ,
NULL , 0 , " This is an unknown BOOLEAN " , HFILL } } ,
2004-12-12 22:59:43 +00:00
{ & hf_ber_unknown_ENUMERATED , {
" ENUMERATED " , " ber.unknown.ENUMERATED " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " This is an unknown ENUMERATED " , HFILL } } ,
2007-05-06 08:18:44 +00:00
{ & hf_ber_constructed_OCTETSTRING , {
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
" OCTETSTRING " , " ber.constructed.OCTETSTRING " , FT_BYTES , BASE_NONE ,
2007-05-06 08:18:44 +00:00
NULL , 0 , " This is a component of an constructed OCTETSTRING " , HFILL } } ,
2008-11-29 11:17:34 +00:00
{ & hf_ber_no_oid , {
" No OID " , " ber.no_oid " , FT_NONE , BASE_NONE ,
NULL , 0 , " No OID supplied to call_ber_oid_callback " , HFILL } } ,
{ & hf_ber_oid_not_implemented , {
" OID not implemented " , " ber.oid_not_implemented " , FT_NONE , BASE_NONE ,
NULL , 0 , " Dissector for OID not implemented " , HFILL } } ,
2007-05-03 21:52:57 +00:00
{ & 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 " ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
FT_BYTES , BASE_NONE , NULL , 0 ,
2007-11-21 23:33:13 +00:00
" ber.T_octet_aligned " , HFILL } } ,
2007-05-03 21:52:57 +00:00
{ & hf_ber_arbitrary ,
{ " arbitrary " , " ber.arbitrary " ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
FT_BYTES , BASE_NONE , NULL , 0 ,
2007-11-21 23:33:13 +00:00
" ber.T_arbitrary " , HFILL } } ,
2007-05-03 21:52:57 +00:00
{ & hf_ber_single_ASN1_type ,
{ " single-ASN1-type " , " ber.single_ASN1_type " ,
FT_NONE , BASE_NONE , NULL , 0 ,
" ber.T_single_ASN1_type " , 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 [ ] = {
& ett_ber_octet_string ,
2004-11-25 21:30:38 +00:00
& ett_ber_unknown ,
2004-11-25 22:27:52 +00:00
& ett_ber_SEQUENCE ,
2007-05-03 21:52:57 +00:00
& ett_ber_EXTERNAL ,
2007-05-22 21:15:00 +00:00
& ett_ber_T_encoding ,
2004-02-20 10:04:10 +00:00
} ;
module_t * ber_module ;
2004-03-25 23:57:10 +00:00
proto_ber = proto_register_protocol ( " Basic Encoding Rules (ASN.1 X.690) " , " BER " , " ber " ) ;
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 ) ) ;
2004-03-25 09:18:03 +00:00
proto_set_cant_toggle ( proto_ber ) ;
2004-02-20 10:04:10 +00:00
/* Register preferences */
ber_module = prefs_register_protocol ( proto_ber , NULL ) ;
prefs_register_bool_preference ( ber_module , " show_internals " ,
" 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 " ,
" 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 " ,
" 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 ) ;
2004-07-21 11:13:03 +00:00
ber_oid_dissector_table = register_dissector_table ( " ber.oid " , " BER OID Dissectors " , FT_STRING , BASE_NONE ) ;
2007-01-13 12:59:27 +00:00
ber_syntax_dissector_table = register_dissector_table ( " ber.syntax " , " BER Syntax Dissectors " , FT_STRING , BASE_NONE ) ;
syntax_table = g_hash_table_new ( g_str_hash , g_str_equal ) ; /* oid to syntax */
2009-10-17 21:42:51 +00:00
register_init_routine ( ber_defragment_init ) ;
2004-02-20 10:04:10 +00:00
}
void
proto_reg_handoff_ber ( void )
{
2006-05-08 19:56:36 +00:00
dissector_handle_t ber_handle ;
2007-08-25 01:14:24 +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
ber_handle = create_dissector_handle ( dissect_ber , proto_ber ) ;
dissector_add ( " wtap_encap " , WTAP_ENCAP_BER , ber_handle ) ;
2006-11-04 09:14:54 +00:00
}
2006-05-08 19:56:36 +00:00
2006-11-04 09:14:54 +00:00
gboolean oid_has_dissector ( const char * oid ) {
return ( dissector_get_string_handle ( ber_oid_dissector_table , oid ) ! = NULL ) ;
2004-02-20 10:04:10 +00:00
}