2 * Helpers for ASN.1/BER dissection
3 * Ronnie Sahlberg (C) 2004
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * ITU-T Recommendation X.690 (07/2002),
28 * Information technology ASN.1 encoding rules:
29 * Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)
32 /* TODO: change #.REGISTER signature to new_dissector_t and
33 * update call_ber_oid_callback() accordingly.
35 * Since we don't pass the TAG/LENGTH from the CHOICE/SEQUENCE/SEQUENCE OF/
36 * SET OF helpers through the callbacks to the next pabket-ber helper
37 * when the tags are IMPLICIT, this causes a problem when we also have
38 * indefinite length at the same time as the tags are implicit.
40 * While the proper fix is to change the signatures for packet-ber.c helpers
41 * as well as the signatures for the callbacks to include the indefinite length
42 * indication that would be a major job.
44 * Originally we used a kludge - we set a global variable in the
45 * CHOICE/SEQUENCE [OF]/SET [OF] helpers to indicate to the next helper
46 * whether the length is indefinite or not.
47 * That had currently only been implemented for {SEQUENCE|SET} [OF] but not
50 * This version attacks the problem(s) in a different way. If we see
51 * indefinite length the get_ber_length traverses the tags within the
52 * compound value and then we return the true length of the compound value
53 * including the EOC. Thus the tvb length is now always correct even for
54 * indefinite length, then if we get implicit tags they can be handled as
55 * if they were definite length.
58 /*#define DEBUG_BER 1*/
66 #include <epan/packet.h>
67 #include <epan/exceptions.h>
68 #include <epan/strutil.h>
69 #include <epan/to_str.h>
70 #include <epan/prefs.h>
71 #include <epan/reassemble.h>
72 #include <epan/oids.h>
73 #include <epan/expert.h>
75 #include <epan/asn1.h>
76 #include <epan/wmem/wmem.h>
78 #include "packet-ber.h"
81 * Set a limit on recursion so we don't blow away the stack. Another approach
82 * would be to remove recursion completely but then we'd exhaust CPU+memory
83 * trying to read a hellabyte of nested indefinite lengths.
85 * XXX - Max nesting in the ASN.1 plugin is 32. Should they match?
87 #define BER_MAX_NESTING 500
89 void proto_register_ber(void);
90 void proto_reg_handoff_ber(void);
92 static gint proto_ber
= -1;
93 static gint hf_ber_id_class
= -1;
94 static gint hf_ber_id_pc
= -1;
95 static gint hf_ber_id_uni_tag
= -1;
96 static gint hf_ber_id_uni_tag_ext
= -1;
97 static gint hf_ber_id_tag
= -1;
98 static gint hf_ber_id_tag_ext
= -1;
99 static gint hf_ber_length
= -1;
100 static gint hf_ber_bitstring_padding
= -1;
101 static gint hf_ber_bitstring_empty
= -1;
102 static gint hf_ber_unknown_OID
= -1;
103 static gint hf_ber_unknown_BOOLEAN
= -1;
104 static gint hf_ber_unknown_OCTETSTRING
= -1;
105 static gint hf_ber_unknown_BER_OCTETSTRING
= -1;
106 static gint hf_ber_unknown_BER_primitive
= -1;
107 static gint hf_ber_unknown_GraphicString
= -1;
108 static gint hf_ber_unknown_NumericString
= -1;
109 static gint hf_ber_unknown_PrintableString
= -1;
110 static gint hf_ber_unknown_TeletexString
= -1;
111 static gint hf_ber_unknown_VisibleString
= -1;
112 static gint hf_ber_unknown_GeneralString
= -1;
113 static gint hf_ber_unknown_UniversalString
= -1;
114 static gint hf_ber_unknown_BMPString
= -1;
115 static gint hf_ber_unknown_IA5String
= -1;
116 static gint hf_ber_unknown_UTCTime
= -1;
117 static gint hf_ber_unknown_UTF8String
= -1;
118 static gint hf_ber_unknown_GeneralizedTime
= -1;
119 static gint hf_ber_unknown_INTEGER
= -1;
120 static gint hf_ber_unknown_BITSTRING
= -1;
121 static gint hf_ber_unknown_ENUMERATED
= -1;
122 static gint hf_ber_error
= -1;
123 static gint hf_ber_direct_reference
= -1; /* OBJECT_IDENTIFIER */
124 static gint hf_ber_indirect_reference
= -1; /* INTEGER */
125 static gint hf_ber_data_value_descriptor
= -1; /* ObjectDescriptor */
126 static gint hf_ber_encoding
= -1; /* T_encoding */
127 static gint hf_ber_single_ASN1_type
= -1; /* T_single_ASN1_type */
128 static gint hf_ber_octet_aligned
= -1; /* OCTET_STRING */
129 static gint hf_ber_arbitrary
= -1; /* BIT_STRING */
131 static int hf_ber_fragments
= -1;
132 static int hf_ber_fragment
= -1;
133 static int hf_ber_fragment_overlap
= -1;
134 static int hf_ber_fragment_overlap_conflicts
= -1;
135 static int hf_ber_fragment_multiple_tails
= -1;
136 static int hf_ber_fragment_too_long_fragment
= -1;
137 static int hf_ber_fragment_error
= -1;
138 static int hf_ber_fragment_count
= -1;
139 static int hf_ber_reassembled_in
= -1;
140 static int hf_ber_reassembled_length
= -1;
142 static gint ett_ber_octet_string
= -1;
143 static gint ett_ber_reassembled_octet_string
= -1;
144 static gint ett_ber_primitive
= -1;
145 static gint ett_ber_unknown
= -1;
146 static gint ett_ber_SEQUENCE
= -1;
147 static gint ett_ber_EXTERNAL
= -1;
148 static gint ett_ber_T_encoding
= -1;
149 static gint ett_ber_fragment
= -1;
150 static gint ett_ber_fragments
= -1;
152 static expert_field ei_ber_size_constraint_string
= EI_INIT
;
153 static expert_field ei_ber_size_constraint_value
= EI_INIT
;
154 static expert_field ei_ber_size_constraint_items
= EI_INIT
;
155 static expert_field ei_ber_sequence_field_wrong
= EI_INIT
;
156 static expert_field ei_ber_expected_octet_string
= EI_INIT
;
157 static expert_field ei_ber_expected_null
= EI_INIT
;
158 static expert_field ei_ber_expected_null_zero_length
= EI_INIT
;
159 static expert_field ei_ber_expected_sequence
= EI_INIT
;
160 static expert_field ei_ber_expected_set
= EI_INIT
;
161 static expert_field ei_ber_expected_string
= EI_INIT
;
162 static expert_field ei_ber_expected_object_identifier
= EI_INIT
;
163 static expert_field ei_ber_expected_generalized_time
= EI_INIT
;
164 static expert_field ei_ber_expected_utc_time
= EI_INIT
;
165 static expert_field ei_ber_expected_bitstring
= EI_INIT
;
166 static expert_field ei_ber_error_length
= EI_INIT
;
167 static expert_field ei_ber_wrong_tag_in_tagged_type
= EI_INIT
;
168 static expert_field ei_ber_universal_tag_unknown
= EI_INIT
;
169 static expert_field ei_ber_no_oid
= EI_INIT
;
170 static expert_field ei_ber_syntax_not_implemented
= EI_INIT
;
171 static expert_field ei_ber_oid_not_implemented
= EI_INIT
;
172 static expert_field ei_ber_value_too_many_bytes
= EI_INIT
;
173 static expert_field ei_ber_unknown_field_sequence
= EI_INIT
;
174 static expert_field ei_ber_unknown_field_set
= EI_INIT
;
175 static expert_field ei_ber_missing_field_set
= EI_INIT
;
176 static expert_field ei_ber_empty_choice
= EI_INIT
;
177 static expert_field ei_ber_choice_not_found
= EI_INIT
;
178 static expert_field ei_ber_bits_unknown
= EI_INIT
;
179 static expert_field ei_ber_bits_set_padded
= EI_INIT
;
180 static expert_field ei_ber_illegal_padding
= EI_INIT
;
181 static expert_field ei_ber_invalid_format_generalized_time
= EI_INIT
;
182 static expert_field ei_ber_invalid_format_utctime
= EI_INIT
;
184 static dissector_handle_t ber_handle
;
186 static gboolean show_internal_ber_fields
= FALSE
;
187 static gboolean decode_octetstring_as_ber
= FALSE
;
188 static gboolean decode_primitive_as_ber
= FALSE
;
189 static gboolean decode_unexpected
= FALSE
;
190 static gboolean decode_warning_leading_zero_bits
= FALSE
;
192 static gchar
*decode_as_syntax
= NULL
;
193 static gchar
*ber_filename
= NULL
;
195 static dissector_table_t ber_oid_dissector_table
= NULL
;
196 static dissector_table_t ber_syntax_dissector_table
= NULL
;
198 static GHashTable
*syntax_table
= NULL
;
200 static gint8 last_class
;
201 static gboolean last_pc
;
202 static gint32 last_tag
;
203 static guint32 last_length
;
204 static gboolean last_ind
;
206 static const value_string ber_class_codes
[] = {
207 { BER_CLASS_UNI
, "UNIVERSAL" },
208 { BER_CLASS_APP
, "APPLICATION" },
209 { BER_CLASS_CON
, "CONTEXT" },
210 { BER_CLASS_PRI
, "PRIVATE" },
214 static const true_false_string ber_pc_codes
= {
215 "Constructed Encoding",
219 static const true_false_string ber_pc_codes_short
= {
224 static const value_string ber_uni_tag_codes
[] = {
225 { BER_UNI_TAG_EOC
, "'end-of-content'" },
226 { BER_UNI_TAG_BOOLEAN
, "BOOLEAN" },
227 { BER_UNI_TAG_INTEGER
, "INTEGER" },
228 { BER_UNI_TAG_BITSTRING
, "BIT STRING" },
229 { BER_UNI_TAG_OCTETSTRING
, "OCTET STRING" },
230 { BER_UNI_TAG_NULL
, "NULL" },
231 { BER_UNI_TAG_OID
, "OBJECT IDENTIFIER" },
232 { BER_UNI_TAG_ObjectDescriptor
, "ObjectDescriptor" },
233 { BER_UNI_TAG_EXTERNAL
, "EXTERNAL" },
234 { BER_UNI_TAG_REAL
, "REAL" },
235 { BER_UNI_TAG_ENUMERATED
, "ENUMERATED" },
236 { BER_UNI_TAG_EMBEDDED_PDV
, "EMBEDDED PDV" },
237 { BER_UNI_TAG_UTF8String
, "UTF8String" },
238 { BER_UNI_TAG_RELATIVE_OID
, "RELATIVE-OID" },
240 * Reserved for future editions of this
241 * Recommendation | International Standard
243 { 14, "Reserved for future editions" },
244 { 15 , "Reserved for future editions" },
246 { BER_UNI_TAG_SEQUENCE
, "SEQUENCE" },
247 { BER_UNI_TAG_SET
, "SET" },
248 { BER_UNI_TAG_NumericString
, "NumericString" },
249 { BER_UNI_TAG_PrintableString
, "PrintableString" },
250 { BER_UNI_TAG_TeletexString
, "TeletexString, T61String" },
251 { BER_UNI_TAG_VideotexString
, "VideotexString" },
252 { BER_UNI_TAG_IA5String
, "IA5String" },
253 { BER_UNI_TAG_UTCTime
, "UTCTime" },
254 { BER_UNI_TAG_GeneralizedTime
, "GeneralizedTime" },
255 { BER_UNI_TAG_GraphicString
, "GraphicString" },
256 { BER_UNI_TAG_VisibleString
, "VisibleString, ISO64String" },
257 { BER_UNI_TAG_GeneralString
, "GeneralString" },
258 { BER_UNI_TAG_UniversalString
, "UniversalString" },
259 { BER_UNI_TAG_CHARACTERSTRING
, "CHARACTER STRING" },
260 { BER_UNI_TAG_BMPString
, "BMPString" },
264 static value_string_ext ber_uni_tag_codes_ext
= VALUE_STRING_EXT_INIT(ber_uni_tag_codes
);
267 static const true_false_string ber_real_binary_vals
= {
272 static const true_false_string ber_real_decimal_vals
= {
278 typedef struct _da_data
{
283 typedef struct _oid_user_t
{
289 UAT_CSTRING_CB_DEF(oid_users
, oid
, oid_user_t
)
290 UAT_CSTRING_CB_DEF(oid_users
, name
, oid_user_t
)
291 UAT_VS_CSTRING_DEF(oid_users
, syntax
, oid_user_t
, 0, "")
293 static oid_user_t
*oid_users
;
294 static guint num_oid_users
;
296 #define MAX_SYNTAX_NAMES 128
297 /* Define non_const_value_string as a hack to prevent chackAPIs.pl from complaining */
298 #define non_const_value_string value_string
299 static non_const_value_string syntax_names
[MAX_SYNTAX_NAMES
+1] = {
304 static const fragment_items octet_string_frag_items
= {
305 /* Fragment subtrees */
308 /* Fragment fields */
311 &hf_ber_fragment_overlap
,
312 &hf_ber_fragment_overlap_conflicts
,
313 &hf_ber_fragment_multiple_tails
,
314 &hf_ber_fragment_too_long_fragment
,
315 &hf_ber_fragment_error
,
316 &hf_ber_fragment_count
,
317 /* Reassembled in field */
318 &hf_ber_reassembled_in
,
319 /* Reassembled length field */
320 &hf_ber_reassembled_length
,
321 /* Reassembled data field */
324 "OCTET STRING fragments"
328 oid_copy_cb(void *dest
, const void *orig
, size_t len _U_
)
330 oid_user_t
*u
= (oid_user_t
*)dest
;
331 const oid_user_t
*o
= (const oid_user_t
*)orig
;
333 u
->oid
= g_strdup(o
->oid
);
334 u
->name
= g_strdup(o
->name
);
335 u
->syntax
= o
->syntax
;
343 oid_user_t
*u
= (oid_user_t
*)r
;
350 cmp_value_string(const void *v1
, const void *v2
)
352 const value_string
*vs1
= (const value_string
*)v1
;
353 const value_string
*vs2
= (const value_string
*)v2
;
355 return strcmp(vs1
->strptr
, vs2
->strptr
);
358 static uat_field_t users_flds
[] = {
359 UAT_FLD_OID(oid_users
, oid
, "OID", "Object Identifier"),
360 UAT_FLD_CSTRING(oid_users
, name
, "Name", "Human readable name for the OID"),
361 UAT_FLD_VS(oid_users
, syntax
, "Syntax", syntax_names
, "Syntax of values associated with the OID"),
366 dissect_ber_oid_NULL_callback(tvbuff_t
*tvb _U_
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
)
373 register_ber_oid_dissector_handle(const char *oid
, dissector_handle_t dissector
, int proto _U_
, const char *name
)
375 dissector_add_string("ber.oid", oid
, dissector
);
376 oid_add_from_string(name
, oid
);
380 register_ber_oid_dissector(const char *oid
, dissector_t dissector
, int proto
, const char *name
)
382 dissector_handle_t dissector_handle
;
384 dissector_handle
= create_dissector_handle(dissector
, proto
);
385 dissector_add_string("ber.oid", oid
, dissector_handle
);
386 oid_add_from_string(name
, oid
);
390 register_ber_syntax_dissector(const char *syntax
, int proto
, dissector_t dissector
)
392 dissector_handle_t dissector_handle
;
394 dissector_handle
= create_dissector_handle(dissector
, proto
);
395 dissector_add_string("ber.syntax", syntax
, dissector_handle
);
400 register_ber_oid_syntax(const char *oid
, const char *name
, const char *syntax
)
403 if (syntax
&& *syntax
)
404 g_hash_table_insert(syntax_table
, (gpointer
)g_strdup(oid
), (gpointer
)g_strdup(syntax
));
407 register_ber_oid_name(oid
, name
);
410 /* Register the oid name to get translation in proto dissection */
412 register_ber_oid_name(const char *oid
, const char *name
)
414 oid_add_from_string(name
, oid
);
418 ber_add_syntax_name(gpointer key
, gpointer value _U_
, gpointer user_data
)
420 guint
*i
= (guint
*)user_data
;
422 if (*i
< MAX_SYNTAX_NAMES
) {
423 syntax_names
[*i
].value
= *i
;
424 syntax_names
[*i
].strptr
= (const gchar
*)key
;
432 ber_decode_as_dt(const gchar
*table_name _U_
, ftenum_t selector_type _U_
, gpointer key
, gpointer value
, gpointer user_data
)
434 da_data
*decode_as_data
;
436 decode_as_data
= (da_data
*)user_data
;
438 decode_as_data
->func(key
, value
, decode_as_data
->user_data
);
442 ber_decode_as_foreach(GHFunc func
, gpointer user_data
)
444 da_data decode_as_data
;
446 decode_as_data
.func
= func
;
447 decode_as_data
.user_data
= user_data
;
449 dissector_table_foreach("ber.syntax", ber_decode_as_dt
, &decode_as_data
);
454 ber_decode_as(const gchar
*syntax
)
457 if (decode_as_syntax
) {
458 g_free(decode_as_syntax
);
459 decode_as_syntax
= NULL
;
463 decode_as_syntax
= g_strdup(syntax
);
466 /* Get oid syntax from hash table to get translation in proto dissection(packet-per.c) */
468 get_ber_oid_syntax(const char *oid
)
470 return (const char *)g_hash_table_lookup(syntax_table
, oid
);
474 ber_set_filename(gchar
*filename
)
479 g_free(ber_filename
);
485 ber_filename
= g_strdup(filename
);
487 if ((ptr
= strrchr(ber_filename
, '.')) != NULL
) {
489 ber_decode_as(get_ber_oid_syntax(ptr
));
497 ber_update_oids(void)
501 for (i
= 0; i
< num_oid_users
; i
++)
502 register_ber_oid_syntax(oid_users
[i
].oid
, oid_users
[i
].name
, oid_users
[i
].syntax
);
506 ber_check_length (guint32 length
, gint32 min_len
, gint32 max_len
, asn1_ctx_t
*actx
, proto_item
*item
, gboolean bit
)
508 if ((min_len
!= -1) && (length
< (guint32
)min_len
)) {
509 expert_add_info_format(
510 actx
->pinfo
, item
, &ei_ber_size_constraint_string
,
511 "Size constraint: %sstring too short: %d (%d .. %d)",
512 bit
? "bit " : "", length
, min_len
, max_len
);
513 } else if ((max_len
!= -1) && (length
> (guint32
)max_len
)) {
514 expert_add_info_format(
515 actx
->pinfo
, item
, &ei_ber_size_constraint_string
,
516 "Size constraint: %sstring too long: %d (%d .. %d)",
517 bit
? "bit " : "", length
, min_len
, max_len
);
522 ber_check_value64 (gint64 value
, gint64 min_len
, gint64 max_len
, asn1_ctx_t
*actx
, proto_item
*item
)
524 if ((min_len
!= -1) && (value
< min_len
)) {
525 expert_add_info_format(
526 actx
->pinfo
, item
, &ei_ber_size_constraint_value
,
527 "Size constraint: value too small: %" G_GINT64_MODIFIER
"d (%" G_GINT64_MODIFIER
"d .. %" G_GINT64_MODIFIER
"d)",
528 value
, min_len
, max_len
);
529 } else if ((max_len
!= -1) && (value
> max_len
)) {
530 expert_add_info_format(
531 actx
->pinfo
, item
, &ei_ber_size_constraint_value
,
532 "Size constraint: value too big: %" G_GINT64_MODIFIER
"d (%" G_GINT64_MODIFIER
"d .. %" G_GINT64_MODIFIER
"d)",
533 value
, min_len
, max_len
);
538 ber_check_value (guint32 value
, gint32 min_len
, gint32 max_len
, asn1_ctx_t
*actx
, proto_item
*item
)
540 if ((min_len
!= -1) && (value
< (guint32
)min_len
)) {
541 expert_add_info_format(
542 actx
->pinfo
, item
, &ei_ber_size_constraint_value
,
543 "Size constraint: value too small: %d (%d .. %d)",
544 value
, min_len
, max_len
);
545 } else if ((max_len
!= -1) && (value
> (guint32
)max_len
)) {
546 expert_add_info_format(
547 actx
->pinfo
, item
, &ei_ber_size_constraint_value
,
548 "Size constraint: value too big: %d (%d .. %d)",
549 value
, min_len
, max_len
);
554 ber_check_items (int cnt
, gint32 min_len
, gint32 max_len
, asn1_ctx_t
*actx
, proto_item
*item
)
556 if ((min_len
!= -1) && (cnt
< min_len
)) {
557 expert_add_info_format(
558 actx
->pinfo
, item
, &ei_ber_size_constraint_items
,
559 "Size constraint: too few items: %d (%d .. %d)",
560 cnt
, min_len
, max_len
);
561 } else if ((max_len
!= -1) && (cnt
> max_len
)) {
562 expert_add_info_format(
563 actx
->pinfo
, item
, &ei_ber_size_constraint_items
,
564 "Size constraint: too many items: %d (%d .. %d)",
565 cnt
, min_len
, max_len
);
570 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
)
575 tvbuff_t
*next_tvb
= tvb
;
581 header_field_info
*hfinfo
;
583 hfinfo
= proto_registrar_get_nth(hf_id
);
588 if (tvb_length_remaining(tvb
, offset
) > 3) {
589 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));
591 printf("dissect_ber_tagged_type(%s) entered\n", name
);
597 offset
= type(tag_impl
, tvb
, offset
, actx
, tree
, hf_id
);
601 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &tmp_cls
, NULL
, &tmp_tag
);
602 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &tmp_len
, NULL
);
604 if ((tmp_cls
!= tag_cls
) || (tmp_tag
!= tag_tag
)) {
605 cause
= proto_tree_add_string_format_value(
606 tree
, hf_ber_error
, tvb
, offset
, tmp_len
, "wrong_tag",
607 "Wrong tag in tagged type - expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
608 val_to_str_const(tag_cls
, ber_class_codes
, "Unknown"),
611 val_to_str_ext_const(tag_tag
, &ber_uni_tag_codes_ext
, "Unknown"),
612 val_to_str_const(tmp_cls
, ber_class_codes
, "Unknown"),
615 expert_add_info(actx
->pinfo
, cause
, &ei_ber_wrong_tag_in_tagged_type
);
619 gint length_remaining
;
621 length_remaining
= tvb_length_remaining(tvb
, offset
);
622 if (tmp_len
> (guint32
)length_remaining
)
623 tmp_len
= length_remaining
;
624 next_tvb
= tvb_new_subset(tvb
, offset
, tmp_len
, tmp_len
);
625 type(tag_impl
, next_tvb
, 0, actx
, tree
, hf_id
);
628 offset
= type(tag_impl
, tvb
, offset
, actx
, tree
, hf_id
);
635 * Add a "length bogus" error.
638 ber_add_bad_length_error(packet_info
*pinfo
, proto_tree
*tree
,
639 const char *name
, tvbuff_t
*tvb
, const gint start
,
644 ti
= proto_tree_add_string_format(
645 tree
, hf_ber_error
, tvb
, start
, length
, "illegal_length",
646 "%s: length of item (%d) is not valid",
648 expert_add_info_format(
649 pinfo
, ti
, &ei_ber_error_length
,
650 "Length of item (%d) is not valid", length
);
655 * Like proto_tree_add_item(), but checks whether the length of the item
656 * being added is appropriate for the type of the item being added, so
657 * if it's not, we report an error rather than a dissector bug.
659 * This is for use when a field that's nominally an OCTET STRING but
660 * where we want the string further interpreted, e.g. as a number or
661 * a network address or a UN*X-style time stamp.
663 * XXX - this duplicates the length checking in proto_tree_add_item()
664 * and the routines it calls; that should really be done in one
665 * place. We *do* want to report a dissector bug in proto_tree_add_item()
666 * if the dissector explicitly says, for example, "this IPv4 address is
667 * 7 bytes long", but we don't want to report a dissector bug if the
668 * *packet* says "this IPv4 address is 7 bytes long", we want to report
669 * a malformed packet.
672 ber_proto_tree_add_item(packet_info
*pinfo
, proto_tree
*tree
,
673 const int hfindex
, tvbuff_t
*tvb
, const gint start
,
674 gint length
, const guint encoding
)
676 header_field_info
*hfinfo
;
678 hfinfo
= proto_registrar_get_nth((guint
)hfindex
);
679 if (hfinfo
!= NULL
) {
680 switch (hfinfo
->type
) {
691 if ((length
!= 1) && (length
!= 2) && (length
!= 3) &&
693 return ber_add_bad_length_error(pinfo
, tree
,
694 hfinfo
->name
, tvb
, start
, length
);
698 if (length
!= FT_IPv4_LEN
)
699 return ber_add_bad_length_error(pinfo
, tree
,
700 hfinfo
->name
, tvb
, start
, length
);
704 if (length
!= FT_IPXNET_LEN
)
705 return ber_add_bad_length_error(pinfo
, tree
,
706 hfinfo
->name
, tvb
, start
, length
);
710 if ((length
< 0) || (length
> FT_IPv6_LEN
))
711 return ber_add_bad_length_error(pinfo
, tree
,
712 hfinfo
->name
, tvb
, start
, length
);
716 if (length
!= FT_ETHER_LEN
)
717 return ber_add_bad_length_error(pinfo
, tree
,
718 hfinfo
->name
, tvb
, start
, length
);
722 if (length
!= FT_GUID_LEN
)
723 return ber_add_bad_length_error(pinfo
, tree
,
724 hfinfo
->name
, tvb
, start
, length
);
729 return ber_add_bad_length_error(pinfo
, tree
,
730 hfinfo
->name
, tvb
, start
, length
);
735 return ber_add_bad_length_error(pinfo
, tree
,
736 hfinfo
->name
, tvb
, start
, length
);
739 case FT_ABSOLUTE_TIME
:
740 case FT_RELATIVE_TIME
:
741 if ((length
!= 4) && (length
!= 8))
742 return ber_add_bad_length_error(pinfo
, tree
,
743 hfinfo
->name
, tvb
, start
, length
);
750 return proto_tree_add_item(tree
, hfindex
, tvb
, start
, length
, encoding
);
754 try_dissect_unknown_ber(packet_info
*pinfo
, tvbuff_t
*tvb
, volatile int offset
, proto_tree
*tree
, gint nest_level
)
762 proto_item
*item
= NULL
;
763 proto_tree
*next_tree
= NULL
;
766 gboolean is_printable
;
767 volatile gboolean is_decoded_as
;
768 proto_item
*pi
, *cause
;
771 if (nest_level
> BER_MAX_NESTING
) {
772 /* Assume that we have a malformed packet. */
773 THROW(ReportedBoundsError
);
776 start_offset
= offset
;
777 asn1_ctx_init(&asn1_ctx
, ASN1_ENC_BER
, TRUE
, pinfo
);
779 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
780 offset
= get_ber_length(tvb
, offset
, &len
, &ind
);
782 if (len
> (guint32
)tvb_length_remaining(tvb
, offset
)) {
783 /* hmm maybe something bad happened or the frame is short;
784 since these are not vital outputs just return instead of
785 throwing an exception.
788 if (show_internal_ber_fields
) {
789 offset
= dissect_ber_identifier(pinfo
, tree
, tvb
, start_offset
, &ber_class
, &pc
, &tag
);
790 offset
= dissect_ber_length(pinfo
, tree
, tvb
, offset
, &len
, NULL
);
792 cause
= proto_tree_add_string_format_value(
793 tree
, hf_ber_error
, tvb
, offset
, len
, "illegal_length",
794 "length:%u longer than tvb_length_remaining:%d",
796 tvb_length_remaining(tvb
, offset
));
797 expert_add_info(pinfo
, cause
, &ei_ber_error_length
);
798 return tvb_length(tvb
);
800 /* we don't care about the class only on the constructor flag */
803 case FALSE
: /* this is not constructed */
805 switch (ber_class
) { /* we do care about the class */
806 case BER_CLASS_UNI
: /* it a Universal tag - we can decode it */
808 case BER_UNI_TAG_EOC
:
809 /* XXX: shouldn't really get here */
811 case BER_UNI_TAG_INTEGER
:
812 offset
= dissect_ber_integer(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_INTEGER
, NULL
);
814 case BER_UNI_TAG_BITSTRING
:
815 offset
= dissect_ber_bitstring(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, NULL
, hf_ber_unknown_BITSTRING
, -1, NULL
);
817 case BER_UNI_TAG_ENUMERATED
:
818 offset
= dissect_ber_integer(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_ENUMERATED
, NULL
);
820 case BER_UNI_TAG_GraphicString
:
821 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_GraphicString
, NULL
);
823 case BER_UNI_TAG_OCTETSTRING
:
824 is_decoded_as
= FALSE
;
825 if (decode_octetstring_as_ber
&& (len
>= 2)) {
826 volatile int ber_offset
= 0;
829 ber_offset
= get_ber_identifier(tvb
, offset
, NULL
, &pc
, NULL
);
830 ber_offset
= get_ber_length(tvb
, ber_offset
, &ber_len
, NULL
);
834 if (pc
&& (ber_len
> 0) && (ber_len
+ (ber_offset
- offset
) == len
)) {
835 /* Decoded a constructed ASN.1 tag with a length indicating this
836 * could be BER encoded data. Try dissecting as unknown BER.
838 is_decoded_as
= TRUE
;
839 if (show_internal_ber_fields
) {
840 offset
= dissect_ber_identifier(pinfo
, tree
, tvb
, start_offset
, NULL
, NULL
, NULL
);
841 offset
= dissect_ber_length(pinfo
, tree
, tvb
, offset
, NULL
, NULL
);
843 item
= ber_proto_tree_add_item(pinfo
, tree
, hf_ber_unknown_BER_OCTETSTRING
, tvb
, offset
, len
, ENC_NA
);
844 next_tree
= proto_item_add_subtree(item
, ett_ber_octet_string
);
845 offset
= try_dissect_unknown_ber(pinfo
, tvb
, offset
, next_tree
, nest_level
+1);
848 if (!is_decoded_as
) {
849 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_OCTETSTRING
, NULL
);
852 case BER_UNI_TAG_OID
:
853 offset
= dissect_ber_object_identifier_str(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_OID
, NULL
);
855 case BER_UNI_TAG_RELATIVE_OID
:
856 offset
= dissect_ber_relative_oid_str(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_OID
, NULL
);
858 case BER_UNI_TAG_NumericString
:
859 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_NumericString
, NULL
);
861 case BER_UNI_TAG_PrintableString
:
862 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_PrintableString
, NULL
);
864 case BER_UNI_TAG_TeletexString
:
865 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_TeletexString
, NULL
);
867 case BER_UNI_TAG_VisibleString
:
868 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_VisibleString
, NULL
);
870 case BER_UNI_TAG_GeneralString
:
871 offset
= dissect_ber_GeneralString(&asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_GeneralString
, NULL
, 0);
873 case BER_UNI_TAG_BMPString
:
874 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_BMPString
, NULL
);
876 case BER_UNI_TAG_UniversalString
:
877 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_UniversalString
, NULL
);
879 case BER_UNI_TAG_IA5String
:
880 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_IA5String
, NULL
);
882 case BER_UNI_TAG_UTCTime
:
883 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_UTCTime
, NULL
);
885 case BER_UNI_TAG_NULL
:
886 proto_tree_add_text(tree
, tvb
, offset
, len
, "NULL tag");
888 case BER_UNI_TAG_UTF8String
:
889 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_UTF8String
, NULL
);
891 case BER_UNI_TAG_GeneralizedTime
:
892 offset
= dissect_ber_octet_string(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_GeneralizedTime
, NULL
);
894 case BER_UNI_TAG_BOOLEAN
:
895 offset
= dissect_ber_boolean(FALSE
, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_BOOLEAN
, NULL
);
898 offset
= dissect_ber_identifier(pinfo
, tree
, tvb
, start_offset
, &ber_class
, &pc
, &tag
);
899 offset
= dissect_ber_length(pinfo
, tree
, tvb
, offset
, &len
, NULL
);
900 cause
= proto_tree_add_string_format_value(
901 tree
, hf_ber_error
, tvb
, offset
, len
, "unknown_universal_tag",
902 "can not handle universal tag:%d",
904 expert_add_info(pinfo
, cause
, &ei_ber_universal_tag_unknown
);
912 /* we dissect again if show_internal_ber_fields is set */
913 if (show_internal_ber_fields
) {
914 offset
= dissect_ber_identifier(pinfo
, tree
, tvb
, start_offset
, &ber_class
, &pc
, &tag
);
915 offset
= dissect_ber_length(pinfo
, tree
, tvb
, offset
, &len
, NULL
);
918 /* we can't dissect this directly as it is specific */
919 pi
= proto_tree_add_none_format(tree
, hf_ber_unknown_BER_primitive
, tvb
, offset
, len
,
920 "[%s %d] ", val_to_str_const(ber_class
, ber_class_codes
, "Unknown"), tag
);
922 is_decoded_as
= FALSE
;
923 if (decode_primitive_as_ber
&& (len
>= 2)) {
924 volatile int ber_offset
= 0;
927 ber_offset
= get_ber_identifier(tvb
, offset
, NULL
, &pc
, NULL
);
928 ber_offset
= get_ber_length(tvb
, ber_offset
, &ber_len
, NULL
);
932 if (pc
&& (ber_len
> 0) && (ber_len
+ (ber_offset
- offset
) == len
)) {
933 /* Decoded a constructed ASN.1 tag with a length indicating this
934 * could be BER encoded data. Try dissecting as unknown BER.
936 is_decoded_as
= TRUE
;
937 proto_item_append_text (pi
, "[BER encoded]");
938 next_tree
= proto_item_add_subtree(pi
, ett_ber_primitive
);
939 offset
= try_dissect_unknown_ber(pinfo
, tvb
, offset
, next_tree
, nest_level
+1);
943 if (!is_decoded_as
&& len
) {
944 /* we may want to do better and show the bytes */
946 for (i
=0; i
<len
; i
++) {
947 c
= tvb_get_guint8(tvb
, offset
+i
);
949 if (is_printable
&& !g_ascii_isprint(c
))
950 is_printable
= FALSE
;
952 proto_item_append_text(pi
, "%02x", c
);
955 if (is_printable
) { /* give a nicer representation if it looks like a string */
956 proto_item_append_text(pi
, " (");
957 for (i
=0; i
<len
; i
++) {
958 proto_item_append_text(pi
, "%c", tvb_get_guint8(tvb
, offset
+i
));
960 proto_item_append_text(pi
, ")");
969 case TRUE
: /* this is constructed */
971 /* we dissect again if show_internal_ber_fields is set */
972 if (show_internal_ber_fields
) {
973 offset
= dissect_ber_identifier(pinfo
, tree
, tvb
, start_offset
, &ber_class
, &pc
, &tag
);
974 offset
= dissect_ber_length(pinfo
, tree
, tvb
, offset
, &len
, NULL
);
977 hdr_len
= offset
-start_offset
;
981 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "%s", val_to_str_ext_const(tag
, &ber_uni_tag_codes_ext
, "Unknown"));
983 next_tree
= proto_item_add_subtree(item
, ett_ber_SEQUENCE
);
985 while (offset
< (int)(start_offset
+ len
+ hdr_len
))
986 offset
= try_dissect_unknown_ber(pinfo
, tvb
, offset
, next_tree
, nest_level
+1);
992 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "[%s %d]", val_to_str_const(ber_class
, ber_class_codes
, "Unknown"), tag
);
994 next_tree
= proto_item_add_subtree(item
, ett_ber_SEQUENCE
);
996 while (offset
< (int)(start_offset
+ len
+ hdr_len
))
997 offset
= try_dissect_unknown_ber(pinfo
, tvb
, offset
, next_tree
, nest_level
+1);
1009 dissect_unknown_ber(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
)
1011 return try_dissect_unknown_ber(pinfo
, tvb
, offset
, tree
, 1);
1015 call_ber_oid_callback(const char *oid
, tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
1018 const char *syntax
= NULL
;
1024 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1026 ((((syntax
= get_ber_oid_syntax(oid
)) == NULL
) ||
1027 /* First see if a syntax has been registered for this oid (user defined) */
1028 !dissector_try_string(ber_syntax_dissector_table
, syntax
, next_tvb
, pinfo
, tree
, data
)) &&
1029 /* Then try registered oid's */
1030 (!dissector_try_string(ber_oid_dissector_table
, oid
, next_tvb
, pinfo
, tree
, data
)))) {
1031 proto_item
*item
= NULL
;
1032 proto_tree
*next_tree
= NULL
;
1033 gint length_remaining
;
1035 length_remaining
= tvb_length_remaining(tvb
, offset
);
1038 item
= proto_tree_add_expert(tree
, pinfo
, &ei_ber_no_oid
, next_tvb
, 0, length_remaining
);
1039 } else if (tvb_get_ntohs (tvb
, offset
) != 0x0500) { /* Not NULL tag */
1041 item
= proto_tree_add_expert_format(
1042 tree
, pinfo
, &ei_ber_syntax_not_implemented
, next_tvb
, 0, length_remaining
,
1043 "BER: Dissector for syntax:%s not implemented."
1044 " Contact Wireshark developers if you want this supported",
1047 item
= proto_tree_add_expert(tree
, pinfo
, &ei_ber_oid_not_implemented
, next_tvb
, 0, length_remaining
);
1052 if (decode_unexpected
) {
1057 next_tree
= proto_item_add_subtree(item
, ett_ber_unknown
);
1059 ber_offset
= get_ber_identifier(next_tvb
, 0, NULL
, NULL
, NULL
);
1060 ber_offset
= get_ber_length(next_tvb
, ber_offset
, &ber_len
, NULL
);
1061 if ((ber_len
+ ber_offset
) == length_remaining
) {
1062 /* Decoded an ASN.1 tag with a length indicating this
1063 * could be BER encoded data. Try dissecting as unknown BER.
1065 dissect_unknown_ber(pinfo
, next_tvb
, 0, next_tree
);
1067 proto_tree_add_text(next_tree
, next_tvb
, 0, length_remaining
,
1068 "Unknown Data (%d byte%s)", length_remaining
,
1069 plurality(length_remaining
, "", "s"));
1075 /*XXX until we change the #.REGISTER signature for _PDU()s
1076 * into new_dissector_t we have to do this kludge with
1077 * manually step past the content in the ANY type.
1079 offset
+= tvb_length_remaining(tvb
, offset
);
1085 call_ber_syntax_callback(const char *syntax
, tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
)
1089 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1090 if (syntax
== NULL
||
1091 !dissector_try_string(ber_syntax_dissector_table
, syntax
, next_tvb
, pinfo
, tree
, NULL
)) {
1092 proto_item
*item
= NULL
;
1093 proto_tree
*next_tree
= NULL
;
1095 if (syntax
== NULL
) {
1096 item
= proto_tree_add_expert_format(
1097 tree
, pinfo
, &ei_ber_no_oid
, next_tvb
, 0, tvb_length_remaining(tvb
, offset
),
1098 "BER: No syntax supplied to call_ber_syntax_callback");
1100 item
= proto_tree_add_expert_format(
1101 tree
, pinfo
, &ei_ber_syntax_not_implemented
, next_tvb
, 0, tvb_length_remaining(tvb
, offset
),
1102 "BER: Dissector for syntax:%s not implemented."
1103 " Contact Wireshark developers if you want this supported",
1107 next_tree
= proto_item_add_subtree(item
, ett_ber_unknown
);
1109 dissect_unknown_ber(pinfo
, next_tvb
, 0, next_tree
);
1112 /*XXX until we change the #.REGISTER signature for _PDU()s
1113 * into new_dissector_t we have to do this kludge with
1114 * manually step past the content in the ANY type.
1116 offset
+=tvb_length_remaining(tvb
, offset
);
1122 /* 8.1 General rules for encoding */
1124 /* 8.1.2 Identifier octets */
1126 get_ber_identifier(tvbuff_t
*tvb
, int offset
, gint8
*ber_class
, gboolean
*pc
, gint32
*tag
) {
1132 id
= tvb_get_guint8(tvb
, offset
);
1135 printf ("BER ID=%02x", id
);
1138 tmp_class
= (id
>> 6) & 0x03;
1139 tmp_pc
= (id
>> 5) & 0x01;
1140 tmp_tag
= id
& 0x1F;
1142 if (tmp_tag
== 0x1F) {
1144 while (tvb_length_remaining(tvb
, offset
) > 0) {
1145 t
= tvb_get_guint8(tvb
, offset
);
1147 printf (" %02x", t
);
1151 tmp_tag
|= t
& 0x7F;
1161 *ber_class
= tmp_class
;
1167 last_class
= tmp_class
;
1175 get_last_ber_identifier(gint8
*ber_class
, gboolean
*pc
, gint32
*tag
)
1178 *ber_class
= last_class
;
1187 dissect_ber_identifier(packet_info
*pinfo _U_
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint8
*ber_class
, gboolean
*pc
, gint32
*tag
)
1189 int old_offset
= offset
;
1194 offset
= get_ber_identifier(tvb
, offset
, &tmp_class
, &tmp_pc
, &tmp_tag
);
1196 if (show_internal_ber_fields
) {
1197 proto_tree_add_uint(tree
, hf_ber_id_class
, tvb
, old_offset
, 1, tmp_class
<< 6);
1198 proto_tree_add_boolean(tree
, hf_ber_id_pc
, tvb
, old_offset
, 1, (tmp_pc
) ? 0x20 : 0x00);
1199 if (tmp_tag
> 0x1F) {
1200 if (tmp_class
== BER_CLASS_UNI
) {
1201 proto_tree_add_uint(tree
, hf_ber_id_uni_tag_ext
, tvb
, old_offset
+ 1, offset
- (old_offset
+ 1), tmp_tag
);
1203 proto_tree_add_uint(tree
, hf_ber_id_tag_ext
, tvb
, old_offset
+ 1, offset
- (old_offset
+ 1), tmp_tag
);
1206 if (tmp_class
== BER_CLASS_UNI
) {
1207 proto_tree_add_uint(tree
, hf_ber_id_uni_tag
, tvb
, old_offset
, 1, tmp_tag
);
1209 proto_tree_add_uint(tree
, hf_ber_id_tag
, tvb
, old_offset
, 1, tmp_tag
);
1215 *ber_class
= tmp_class
;
1224 /** Try to get the length octets of the BER TLV.
1225 * Only (TAGs and) LENGTHs that fit inside 32 bit integers are supported.
1227 * @return TRUE if we have the entire length, FALSE if we're in the middle of
1228 * an indefinite length and haven't reached EOC.
1230 /* 8.1.3 Length octets */
1233 try_get_ber_length(tvbuff_t
*tvb
, int offset
, guint32
*length
, gboolean
*ind
, gint nest_level
) {
1238 int tmp_offset
, s_offset
;
1246 if (nest_level
> BER_MAX_NESTING
) {
1247 /* Assume that we have a malformed packet. */
1248 THROW(ReportedBoundsError
);
1251 oct
= tvb_get_guint8(tvb
, offset
);
1254 if (!(oct
& 0x80)) {
1262 oct
= tvb_get_guint8(tvb
, offset
);
1264 tmp_length
= (tmp_length
<<8) + oct
;
1269 tmp_offset
= offset
;
1270 /* ok in here we can traverse the BER to find the length, this will fix most indefinite length issues */
1271 /* Assumption here is that indefinite length is always used on constructed types*/
1273 while (tvb_get_guint8(tvb
, offset
) || tvb_get_guint8(tvb
, offset
+1)) {
1274 /* not an EOC at offset */
1276 offset
= get_ber_identifier(tvb
, offset
, &tclass
, &tpc
, &ttag
);
1277 offset
= try_get_ber_length(tvb
, offset
, &indef_len
, NULL
, nest_level
+1);
1278 tmp_length
+= indef_len
+(offset
-s_offset
); /* length + tag and length */
1279 offset
+= indef_len
;
1280 /* Make sure we've moved forward in the packet */
1281 if (offset
<= s_offset
)
1282 THROW(ReportedBoundsError
);
1286 offset
= tmp_offset
;
1291 *length
= tmp_length
;
1296 printf("get BER length %d, offset %d (remaining %d)\n", tmp_length
, offset
, tvb_length_remaining(tvb
, offset
));
1303 get_ber_length(tvbuff_t
*tvb
, int offset
, guint32
*length
, gboolean
*ind
)
1305 return try_get_ber_length(tvb
, offset
, length
, ind
, 1);
1309 get_last_ber_length(guint32
*length
, gboolean
*ind
)
1312 *length
= last_length
;
1317 /* this function dissects the length octets of the BER TLV.
1318 * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
1321 dissect_ber_length(packet_info
*pinfo _U_
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, guint32
*length
, gboolean
*ind
)
1323 int old_offset
= offset
;
1327 offset
= get_ber_length(tvb
, offset
, &tmp_length
, &tmp_ind
);
1329 if (show_internal_ber_fields
) {
1331 proto_tree_add_text(tree
, tvb
, old_offset
, 1, "Length: Indefinite length %d", tmp_length
);
1333 proto_tree_add_uint(tree
, hf_ber_length
, tvb
, old_offset
, offset
- old_offset
, tmp_length
);
1337 *length
= tmp_length
;
1342 printf("dissect BER length %d, offset %d (remaining %d)\n", tmp_length
, offset
, tvb_length_remaining(tvb
, offset
));
1345 last_length
= tmp_length
;
1351 static reassembly_table octet_segment_reassembly_table
;
1353 static void ber_defragment_init(void) {
1354 reassembly_table_init(&octet_segment_reassembly_table
,
1355 &addresses_reassembly_table_functions
);
1359 reassemble_octet_string(asn1_ctx_t
*actx
, proto_tree
*tree
, gint hf_id
, tvbuff_t
*tvb
, int offset
, guint32 con_len
, gboolean ind
, tvbuff_t
**out_tvb
)
1361 fragment_head
*fd_head
= NULL
;
1362 tvbuff_t
*next_tvb
= NULL
;
1363 tvbuff_t
*reassembled_tvb
= NULL
;
1364 guint16 dst_ref
= 0;
1365 int start_offset
= offset
;
1366 gboolean fragment
= TRUE
;
1367 gboolean firstFragment
= TRUE
;
1369 /* so we need to consume octet strings for the given length */
1374 if (con_len
== 0) /* Zero encodings (8.7.3) */
1377 /* not sure we need this */
1378 actx
->pinfo
->fragmented
= TRUE
;
1382 offset
= dissect_ber_octet_string(FALSE
, actx
, NULL
, tvb
, offset
, hf_id
, &next_tvb
);
1384 if (next_tvb
== NULL
) {
1385 /* Assume that we have a malformed packet. */
1386 THROW(ReportedBoundsError
);
1390 /* this was indefinite length - so check for EOC */
1392 if ((tvb_get_guint8(tvb
, offset
) == 0) && (tvb_get_guint8(tvb
, offset
+1) == 0)) {
1399 if ((guint32
)(offset
- start_offset
) >= con_len
)
1403 if (!fragment
&& firstFragment
) {
1404 /* there is only one fragment (I'm sure there's a reason it was constructed) */
1405 /* anyway, we can get out of here */
1407 get_ber_identifier(tvb
, start_offset
, NULL
, &pc
, NULL
);
1409 /* Only display here if not constructed */
1410 dissect_ber_octet_string(FALSE
, actx
, tree
, tvb
, start_offset
, hf_id
, NULL
);
1412 reassembled_tvb
= next_tvb
;
1417 if (tvb_length(next_tvb
) < 1) {
1418 /* Don't cause an assertion in the reassembly code. */
1419 THROW(ReportedBoundsError
);
1421 fd_head
= fragment_add_seq_next(&octet_segment_reassembly_table
,
1422 next_tvb
, 0, actx
->pinfo
, dst_ref
, NULL
,
1423 tvb_length(next_tvb
),
1426 firstFragment
= FALSE
;
1430 if (fd_head
->next
) {
1431 /* not sure I really want to do this here - should be nearer the application where we can give it a better name*/
1432 proto_tree
*next_tree
;
1433 proto_item
*frag_tree_item
;
1435 reassembled_tvb
= tvb_new_chain(next_tvb
, fd_head
->tvb_data
);
1437 actx
->created_item
= proto_tree_add_item(tree
, hf_id
, reassembled_tvb
, 0, -1, ENC_BIG_ENDIAN
);
1438 next_tree
= proto_item_add_subtree (actx
->created_item
, ett_ber_reassembled_octet_string
);
1440 add_new_data_source(actx
->pinfo
, reassembled_tvb
, "Reassembled OCTET STRING");
1441 show_fragment_seq_tree(fd_head
, &octet_string_frag_items
, next_tree
, actx
->pinfo
, reassembled_tvb
, &frag_tree_item
);
1446 *out_tvb
= reassembled_tvb
;
1448 /* again - not sure we need this */
1449 actx
->pinfo
->fragmented
= FALSE
;
1455 /* 8.7 Encoding of an octetstring value */
1457 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
) {
1464 proto_item
*it
, *cause
;
1471 header_field_info
*hfinfo
;
1473 hfinfo
= proto_registrar_get_nth(hf_id
);
1474 name
= hfinfo
->name
;
1478 if (tvb_length_remaining(tvb
, offset
) > 3) {
1479 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));
1481 printf("OCTET STRING dissect_ber_octet_string(%s) entered\n", name
);
1489 if (!implicit_tag
) {
1491 /* read header and len for the octet string */
1492 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
1493 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, &ind
);
1494 end_offset
= offset
+len
;
1496 /* sanity check: we only handle Constructed Universal Sequences */
1497 if ((ber_class
!= BER_CLASS_APP
) && (ber_class
!= BER_CLASS_PRI
)) {
1498 if ( (ber_class
!= BER_CLASS_UNI
)
1499 || ((tag
< BER_UNI_TAG_NumericString
) && (tag
!= BER_UNI_TAG_OCTETSTRING
) && (tag
!= BER_UNI_TAG_UTF8String
)) ) {
1500 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
1501 cause
= proto_tree_add_string_format_value(
1502 tree
, hf_ber_error
, tvb
, offset
, len
, "octetstring_expected",
1503 "OctetString expected but class:%s(%d) %s tag:%d was unexpected",
1504 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
1506 pc
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
1508 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_octet_string
);
1509 if (decode_unexpected
) {
1510 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
1511 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
1517 /* implicit tag so get from last tag/length */
1519 get_last_ber_identifier(&ber_class
, &pc
, &tag
);
1520 get_last_ber_length(&len
, &ind
);
1522 end_offset
= offset
+len
;
1524 /* caller may have created new buffer for indefinite length data Verify via length */
1525 len_remain
= (guint32
)tvb_length_remaining(tvb
, offset
);
1526 if (ind
&& (len_remain
== (len
- 2))) {
1527 /* new buffer received so adjust length and indefinite flag */
1531 } else if (len_remain
< len
) {
1533 * error - short frame, or this item runs past the
1534 * end of the item containing it
1536 cause
= proto_tree_add_string_format_value(
1537 tree
, hf_ber_error
, tvb
, offset
, len
, "illegal_length",
1538 "length:%u longer than tvb_length_remaining:%d",
1541 expert_add_info(actx
->pinfo
, cause
, &ei_ber_error_length
);
1547 actx
->created_item
= NULL
;
1551 end_offset
= reassemble_octet_string(actx
, tree
, hf_id
, tvb
, offset
, len
, ind
, out_tvb
);
1554 gint length_remaining
;
1556 length_remaining
= tvb_length_remaining(tvb
, offset
);
1558 if (length_remaining
< 1) {
1563 if (len
<= (guint32
)length_remaining
) {
1564 length_remaining
= len
;
1567 it
= ber_proto_tree_add_item(actx
->pinfo
, tree
, hf_id
, tvb
, offset
, length_remaining
, ENC_BIG_ENDIAN
);
1568 actx
->created_item
= it
;
1569 ber_check_length(length_remaining
, min_len
, max_len
, actx
, it
, FALSE
);
1573 pi
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Unknown OctetString: Length: 0x%02x, Value: 0x", len
);
1575 for (i
=0; i
<len
; i
++) {
1576 proto_item_append_text(pi
, "%02x", tvb_get_guint8(tvb
, offset
));
1583 if (len
> (guint32
)length_remaining
)
1584 len
= length_remaining
;
1585 *out_tvb
= tvb_new_subset(tvb
, offset
, len
, len
);
1592 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
) {
1593 return dissect_ber_constrained_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, NO_BOUND
, NO_BOUND
, hf_id
, out_tvb
);
1597 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
)
1599 tvbuff_t
*out_tvb
= NULL
;
1601 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, (func
) ? &out_tvb
: NULL
);
1602 if (func
&& out_tvb
&& (tvb_length(out_tvb
) > 0)) {
1604 tree
= proto_item_add_subtree(actx
->created_item
, ett_ber_octet_string
);
1605 /* TODO Should hf_id2 be pased as last parameter???*/
1606 func(FALSE
, out_tvb
, 0, actx
, tree
, -1);
1612 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
)
1614 tvbuff_t
*out_tvb
= NULL
;
1616 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, (func
) ? &out_tvb
: NULL
);
1617 if (func
&& out_tvb
&& (tvb_length(out_tvb
) > 0)) {
1619 tree
= proto_item_add_subtree(actx
->created_item
, ett_ber_octet_string
);
1620 /* TODO Should hf_id2 be pased as last parameter???*/
1621 func(tree
, out_tvb
, 0, actx
);
1625 /* 8.8 Encoding of a null value */
1627 dissect_ber_null(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
) {
1635 if (!implicit_tag
) {
1636 offset_old
= offset
;
1637 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
1639 (!implicit_tag
&& ((ber_class
!= BER_CLASS_UNI
) || (tag
!= BER_UNI_TAG_NULL
)))) {
1640 cause
= proto_tree_add_string_format_value(
1641 tree
, hf_ber_error
, tvb
, offset_old
, offset
- offset_old
, "null_expected",
1642 "NULL expected but class:%s(%d) %s tag:%d was unexpected",
1643 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
1645 pc
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
1647 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_null
);
1650 offset_old
= offset
;
1651 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
1653 proto_tree_add_string_format_value(
1654 tree
, hf_ber_error
, tvb
, offset_old
, offset
- offset_old
, "illegal_length",
1655 "NULL expect zero length but Length=%d",
1657 cause
= proto_tree_add_string_format_value(
1658 tree
, hf_ber_error
, tvb
, offset
, len
, "unexpected_data",
1659 "unexpected data in NULL type");
1660 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_null_zero_length
);
1665 proto_tree_add_item(tree
, hf_id
, tvb
, offset
, 0, ENC_BIG_ENDIAN
);
1670 dissect_ber_integer64(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
, gint64
*value
)
1678 gboolean used_too_many_bytes
= FALSE
;
1683 header_field_info
*hfinfo
;
1685 hfinfo
= proto_registrar_get_nth(hf_id
);
1686 name
= hfinfo
->name
;
1690 if (tvb_length_remaining(tvb
, offset
) > 3) {
1691 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));
1693 printf("INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d \n", name
, implicit_tag
);
1703 if (!implicit_tag
) {
1704 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
1705 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
1707 gint32 remaining
= tvb_length_remaining(tvb
, offset
);
1708 len
= remaining
>0 ? remaining
: 0;
1711 first
= tvb_get_guint8(tvb
, offset
);
1712 /* we can't handle integers > 64 bits */
1713 /* take into account the use case of a 64bits unsigned integer: you will have a 9th byte set to 0 */
1714 if ((len
> 9) || ((len
== 9) && (first
!= 0))) {
1715 header_field_info
*hfinfo
;
1716 proto_item
*pi
= NULL
;
1719 hfinfo
= proto_registrar_get_nth(hf_id
);
1720 pi
= proto_tree_add_text(tree
, tvb
, offset
, len
, "%s : 0x", hfinfo
->name
);
1723 for (i
=0; i
<len
; i
++) {
1724 proto_item_append_text(pi
, "%02x", tvb_get_guint8(tvb
, offset
));
1735 /* extend sign bit for signed fields */
1736 enum ftenum type
= FT_INT32
; /* Default to signed, is this correct? */
1738 type
= proto_registrar_get_ftype(hf_id
);
1740 if (first
& 0x80 && IS_FT_INT(type
)) {
1743 if ((len
> 1) && decode_warning_leading_zero_bits
) {
1744 guint8 second
= tvb_get_guint8(tvb
, offset
+1);
1745 if (((first
== 0x00) && ((second
& 0x80) == 0)) ||
1746 ((first
== 0xff) && ((second
& 0x80) != 0))) {
1747 used_too_many_bytes
= TRUE
;
1750 for (i
=0; i
<len
; i
++) {
1751 val
= (val
<<8) | tvb_get_guint8(tvb
, offset
);
1756 actx
->created_item
= NULL
;
1760 if ((len
< 1) || (len
> 9) || ((len
== 9) && (first
!= 0))) {
1761 proto_item
*pi
= proto_tree_add_string_format_value(
1762 tree
, hf_ber_error
, tvb
, offset
-len
, len
, "invalid length",
1763 "Can't handle integer length: %u",
1765 expert_add_info_format(actx
->pinfo
, pi
, &ei_ber_error_length
,
1766 "BER Error: Illegal integer length: %u", len
);
1768 header_field_info
* hfi
;
1770 hfi
= proto_registrar_get_nth(hf_id
);
1771 switch (hfi
->type
) {
1776 actx
->created_item
= proto_tree_add_uint(tree
, hf_id
, tvb
, offset
-len
, len
, (guint32
)val
);
1782 actx
->created_item
= proto_tree_add_int(tree
, hf_id
, tvb
, offset
-len
, len
, (gint32
)val
);
1785 actx
->created_item
= proto_tree_add_int64(tree
, hf_id
, tvb
, offset
-len
, len
, val
);
1788 actx
->created_item
= proto_tree_add_uint64(tree
, hf_id
, tvb
, offset
-len
, len
, (guint64
)val
);
1791 DISSECTOR_ASSERT_NOT_REACHED();
1794 if (used_too_many_bytes
) {
1795 expert_add_info_format(
1796 actx
->pinfo
, actx
->created_item
, &ei_ber_value_too_many_bytes
,
1797 "Value is encoded with too many bytes(9 leading zero or one bits), hf_abbr: %s",
1811 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
)
1815 offset
= dissect_ber_integer64(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, &val
);
1820 ber_check_value64 (val
, min_len
, max_len
, actx
, actx
->created_item
);
1826 dissect_ber_integer(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
, guint32
*value
)
1830 offset
= dissect_ber_integer64(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, &val
);
1832 *value
= (guint32
)val
;
1839 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
)
1843 offset
= dissect_ber_integer64(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, &val
);
1845 *value
= (guint32
)val
;
1848 ber_check_value ((guint32
)val
, min_len
, max_len
, actx
, actx
->created_item
);
1854 dissect_ber_boolean(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
, gboolean
*value
)
1861 header_field_info
*hfi
;
1863 if (!implicit_tag
) {
1864 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
1865 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
1866 /*if (ber_class != BER_CLASS_UNI)*/
1868 /* nothing to do here, yet */
1871 val
= tvb_get_guint8(tvb
, offset
);
1874 actx
->created_item
= NULL
;
1877 hfi
= proto_registrar_get_nth(hf_id
);
1878 if (hfi
->type
== FT_BOOLEAN
)
1879 actx
->created_item
= proto_tree_add_boolean(tree
, hf_id
, tvb
, offset
-1, 1, val
);
1881 actx
->created_item
= proto_tree_add_uint(tree
, hf_id
, tvb
, offset
-1, 1, val
? 1 : 0);
1885 *value
= (val
? TRUE
: FALSE
);
1892 /* 8.5 Encoding of a real value */
1895 dissect_ber_real(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id _U_
, double *value
)
1900 guint32 val_length
= 0, end_offset
;
1903 if (!implicit_tag
) {
1904 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
1905 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &val_length
, NULL
);
1907 /* 8.5.1 The encoding of a real value shall be primitive. */
1908 DISSECTOR_ASSERT_NOT_REACHED();
1910 /* 8.5.2 If the real value is the value zero,
1911 * there shall be no contents octets in the encoding.
1913 if (val_length
== 0) {
1918 end_offset
= offset
+ val_length
;
1920 val
= asn1_get_real(tvb_get_ptr(tvb
, offset
, val_length
), val_length
);
1921 actx
->created_item
= proto_tree_add_double(tree
, hf_id
, tvb
, offset
, val_length
, val
);
1929 /* this function dissects a BER sequence
1932 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
) {
1934 gboolean pcx
, ind
= 0, ind_field
, imp_tag
= FALSE
;
1937 proto_tree
*tree
= parent_tree
;
1938 proto_item
*item
= NULL
;
1942 gint length_remaining
;
1948 header_field_info
*hfinfo
;
1950 hfinfo
= proto_registrar_get_nth(hf_id
);
1951 name
= hfinfo
->name
;
1955 if (tvb_length_remaining(tvb
, offset
) > 3) {
1956 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));
1958 printf("SEQUENCE dissect_ber_sequence(%s) entered\n", name
);
1963 if (!implicit_tag
) {
1964 offset
= get_ber_identifier(tvb
, offset
, NULL
, NULL
, NULL
);
1965 offset
= get_ber_length(tvb
, offset
, &lenx
, NULL
);
1967 /* was implicit tag so just use the length of the tvb */
1968 lenx
= tvb_length_remaining(tvb
, offset
);
1969 end_offset
= offset
+lenx
;
1971 /* create subtree */
1974 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, hoffset
, lenx
+ offset
- hoffset
, ENC_BIG_ENDIAN
);
1975 tree
= proto_item_add_subtree(item
, ett_id
);
1980 if (!implicit_tag
) {
1981 /* first we must read the sequence header */
1982 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &classx
, &pcx
, &tagx
);
1983 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &lenx
, &ind
);
1985 /* Fixed the length is correctly returned from dissect ber_length
1986 end_offset = tvb_length(tvb);*/
1987 end_offset
= offset
+ lenx
-2;
1989 end_offset
= offset
+ lenx
;
1992 /* sanity check: we only handle Constructed Universal Sequences */
1993 if ((classx
!= BER_CLASS_APP
) && (classx
!= BER_CLASS_PRI
)) {
1995 || (!implicit_tag
&& ((classx
!= BER_CLASS_UNI
) || (tagx
!= BER_UNI_TAG_SEQUENCE
)))) {
1996 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
1997 cause
= proto_tree_add_string_format_value(
1998 tree
, hf_ber_error
, tvb
, offset
, lenx
, "sequence_expected",
1999 "Sequence expected but class:%s(%d) %s tag:%d was unexpected",
2000 val_to_str_const(classx
, ber_class_codes
, "Unknown"),
2002 pcx
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
2004 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_sequence
);
2005 if (decode_unexpected
) {
2006 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2007 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2013 if(offset
== end_offset
){
2014 proto_item_append_text(item
, " [0 length]");
2016 /* loop over all entries until we reach the end of the sequence */
2017 while (offset
< end_offset
) {
2024 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2025 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2026 if ((tvb_get_guint8(tvb
, offset
) == 0) && (tvb_get_guint8(tvb
, offset
+1) == 0)) {
2027 /* If the first bytes is 00 00 of a indefenert length field it's a zero length field*/
2028 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
2029 dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, &ind
);
2030 proto_item_append_text(item
, " 0 items");
2033 if (show_internal_ber_fields) {
2034 proto_tree_add_text(tree, tvb, s_offset, offset+2, "ERROR WRONG SEQ EOC");
2041 /* read header and len for next field */
2042 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
2043 offset
= get_ber_length(tvb
, offset
, &len
, &ind_field
);
2044 eoffset
= offset
+ len
;
2045 /* Make sure we move forward */
2046 if (eoffset
<= hoffset
)
2047 THROW(ReportedBoundsError
);
2049 /*if (ind_field && (len == 2)) {
2050 / disgusting indefinite length zero length field, what are these people doing /
2056 ber_sequence_try_again
:
2057 /* have we run out of known entries in the sequence ?*/
2059 /* it was not, move to the next one and try again */
2060 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2061 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, NULL
, NULL
);
2062 cause
= proto_tree_add_string_format_value(
2063 tree
, hf_ber_error
, tvb
, offset
, len
, "unknown_field",
2064 "This field lies beyond the end of the known sequence definition.");
2065 expert_add_info(actx
->pinfo
, cause
, &ei_ber_unknown_field_sequence
);
2066 if (decode_unexpected
) {
2067 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2068 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2074 /* Verify that this one is the one we want.
2075 * Skip check completely if ber_class == ANY
2076 * of if NOCHKTAG is set
2078 /* XXX Bug in asn2eth,
2079 * for scope [7] Scope OPTIONAL,
2081 * { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_scope },
2082 * and there should not be a NOTCHKTAG here
2084 if ( ((seq
->ber_class
== BER_CLASS_CON
) || (seq
->ber_class
== BER_CLASS_APP
) || (seq
->ber_class
== BER_CLASS_PRI
))
2085 && (!(seq
->flags
& BER_FLAGS_NOOWNTAG
)) ) {
2086 if ( (seq
->ber_class
!= BER_CLASS_ANY
)
2088 && ( (seq
->ber_class
!= ber_class
)
2089 || (seq
->tag
!= tag
) ) ) {
2090 /* it was not, move to the next one and try again */
2091 if (seq
->flags
& BER_FLAGS_OPTIONAL
) {
2092 /* well this one was optional so just skip to the next one and try again. */
2094 goto ber_sequence_try_again
;
2096 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2097 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, NULL
, NULL
);
2098 if (seq
->ber_class
== BER_CLASS_UNI
) {
2099 cause
= proto_tree_add_string_format_value(
2100 tree
, hf_ber_error
, tvb
, offset
, len
, "wrong_field",
2101 "Wrong field in SEQUENCE expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
2102 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2105 val_to_str_ext_const(seq
->tag
, &ber_uni_tag_codes_ext
, "Unknown"),
2106 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2109 expert_add_info(actx
->pinfo
, cause
, &ei_ber_sequence_field_wrong
);
2111 cause
= proto_tree_add_string_format_value(
2112 tree
, hf_ber_error
, tvb
, offset
, len
, "wrong_field",
2113 "Wrong field in SEQUENCE expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2114 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2117 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2120 expert_add_info(actx
->pinfo
, cause
, &ei_ber_sequence_field_wrong
);
2122 if (decode_unexpected
) {
2123 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2124 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2130 } else if (!(seq
->flags
& BER_FLAGS_NOTCHKTAG
)) {
2131 if ( (seq
->ber_class
!= BER_CLASS_ANY
)
2133 && ( (seq
->ber_class
!= ber_class
)
2134 || (seq
->tag
!= tag
) ) ) {
2135 /* it was not, move to the next one and try again */
2136 if (seq
->flags
& BER_FLAGS_OPTIONAL
) {
2137 /* well this one was optional so just skip to the next one and try again. */
2139 goto ber_sequence_try_again
;
2142 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2143 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, NULL
, NULL
);
2144 if ( seq
->ber_class
== BER_CLASS_UNI
) {
2145 cause
= proto_tree_add_string_format_value(
2146 tree
, hf_ber_error
, tvb
, offset
, len
, "wrong_field",
2147 "Wrong field in sequence expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d",
2148 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2151 val_to_str_ext_const(seq
->tag
, &ber_uni_tag_codes_ext
, "Unknown"),
2152 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2154 expert_add_info(actx
->pinfo
, cause
, &ei_ber_sequence_field_wrong
);
2156 cause
= proto_tree_add_string_format_value(
2157 tree
, hf_ber_error
, tvb
, offset
, len
, "wrong_field",
2158 "Wrong field in sequence expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2159 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2162 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2165 expert_add_info(actx
->pinfo
, cause
, &ei_ber_sequence_field_wrong
);
2167 if (decode_unexpected
) {
2168 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2169 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2177 if (!(seq
->flags
& BER_FLAGS_NOOWNTAG
) ) {
2178 /* dissect header and len for field */
2179 if (ind_field
&& (len
== 2)) {
2180 /* This is a Zero length field */
2181 next_tvb
= tvb_new_subset(tvb
, offset
, len
, len
);
2184 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2185 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
2186 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
2187 if (length_remaining
> (eoffset
- hoffset
- (2 * ind_field
)))
2188 length_remaining
= eoffset
- hoffset
- (2 * ind_field
);
2189 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, length_remaining
);
2192 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
2193 if (length_remaining
> (eoffset
- hoffset
))
2194 length_remaining
= eoffset
- hoffset
;
2195 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, length_remaining
);
2199 /* call the dissector for this field */
2200 if ((eoffset
-hoffset
) > length_remaining
) {
2201 /* If the field is indefinite (i.e. we don't know the
2202 * length) of if the tvb is short, then just
2203 * give it all of the tvb and hope for the best.
2205 next_tvb
= tvb_new_subset_remaining(tvb
, hoffset
);
2214 header_field_info
*hfinfo
;
2216 hfinfo
= proto_registrar_get_nth(hf_id
);
2217 name
= hfinfo
->name
;
2221 if (tvb_length_remaining(next_tvb
, 0) > 3) {
2222 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));
2224 printf("SEQUENCE dissect_ber_sequence(%s) calling subdissector\n", name
);
2228 if (next_tvb
== NULL
) {
2229 /* Assume that we have a malformed packet. */
2230 THROW(ReportedBoundsError
);
2233 if (seq
->flags
& BER_FLAGS_IMPLTAG
) {
2237 count
= seq
->func(imp_tag
, next_tvb
, 0, actx
, tree
, *seq
->p_id
);
2242 header_field_info
*hfinfo
;
2244 hfinfo
= proto_registrar_get_nth(hf_id
);
2245 name
= hfinfo
->name
;
2249 printf("SEQUENCE dissect_ber_sequence(%s) subdissector ate %d bytes\n", name
, count
);
2252 /* if it was optional and no bytes were eaten and it was */
2253 /* supposed to (len <> 0), just try again. */
2254 if ((len
!= 0) && (count
== 0) && (seq
->flags
& BER_FLAGS_OPTIONAL
)) {
2256 goto ber_sequence_try_again
;
2257 /* move the offset to the beginning of the next sequenced item */
2260 if (!(seq
->flags
& BER_FLAGS_NOOWNTAG
) ) {
2261 /* if we stripped the tag and length we should also strip the EOC is ind_len
2262 * Unless it's a zero length field (len = 2)
2264 if ((ind_field
== 1) && (len
> 2))
2267 if (show_internal_ber_fields
) {
2268 proto_tree_add_text(tree
, tvb
, offset
, count
, "SEQ FIELD EOC");
2275 /* if we didnt end up at exactly offset, then we ate too many bytes */
2276 if (offset
!= end_offset
) {
2277 tvb_ensure_bytes_exist(tvb
, offset
-2, 2);
2278 cause
= proto_tree_add_string_format_value(
2279 tree
, hf_ber_error
, tvb
, offset
-2, 2, "illegal_length",
2280 "Sequence ate %d too many bytes",
2281 offset
- end_offset
);
2282 expert_add_info_format(actx
->pinfo
, cause
, &ei_ber_error_length
,
2283 "BER Error: too many bytes in Sequence");
2286 /* need to eat this EOC
2287 end_offset = tvb_length(tvb);*/
2289 if (show_internal_ber_fields
) {
2290 proto_tree_add_text(tree
, tvb
, end_offset
-2, 2 , "SEQ EOC");
2296 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
) {
2298 gboolean pcx
, ind
= 0, ind_field
;
2301 proto_tree
*tree
= parent_tree
;
2302 proto_item
*item
= NULL
;
2306 gint length_remaining
;
2312 header_field_info
*hfinfo
;
2314 hfinfo
= proto_registrar_get_nth(hf_id
);
2315 name
= hfinfo
->name
;
2319 if (tvb_length_remaining(tvb
, offset
) > 3) {
2320 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));
2322 printf("SEQUENCE dissect_ber_old_sequence(%s) entered\n", name
);
2327 if (!implicit_tag
) {
2328 offset
= get_ber_identifier(tvb
, offset
, NULL
, NULL
, NULL
);
2329 offset
= get_ber_length(tvb
, offset
, &lenx
, NULL
);
2331 /* was implicit tag so just use the length of the tvb */
2332 lenx
= tvb_length_remaining(tvb
, offset
);
2333 end_offset
= offset
+lenx
;
2335 /* create subtree */
2338 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, hoffset
, lenx
+ offset
- hoffset
, ENC_BIG_ENDIAN
);
2339 tree
= proto_item_add_subtree(item
, ett_id
);
2344 if (!implicit_tag
) {
2345 /* first we must read the sequence header */
2346 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &classx
, &pcx
, &tagx
);
2347 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &lenx
, &ind
);
2349 /* Fixed the length is correctly returned from dissect ber_length
2350 end_offset = tvb_length(tvb);*/
2351 end_offset
= offset
+ lenx
-2;
2353 end_offset
= offset
+ lenx
;
2356 /* sanity check: we only handle Constructed Universal Sequences */
2357 if ((classx
!= BER_CLASS_APP
) && (classx
!= BER_CLASS_PRI
)) {
2359 || (!implicit_tag
&& ((classx
!= BER_CLASS_UNI
) || (tagx
!= BER_UNI_TAG_SEQUENCE
)))) {
2360 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
2361 cause
= proto_tree_add_string_format_value(
2362 tree
, hf_ber_error
, tvb
, offset
, lenx
, "sequence_expected",
2363 "Sequence expected but class:%s(%d) %s tag:%d was unexpected",
2364 val_to_str_const(classx
, ber_class_codes
, "Unknown"),
2366 pcx
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
2369 actx
->pinfo
, cause
, &ei_ber_expected_sequence
);
2370 if (decode_unexpected
) {
2371 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2372 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2378 /* loop over all entries until we reach the end of the sequence */
2379 while (offset
< end_offset
) {
2386 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2387 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2388 if ((tvb_get_guint8(tvb
, offset
) == 0) && (tvb_get_guint8(tvb
, offset
+1) == 0)) {
2389 /* If the first bytes are 00 00 in an indefinite length field, it's a zero length field */
2390 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
2391 dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, &ind
);
2392 proto_item_append_text(item
, " 0 items");
2395 if (show_internal_ber_fields) {
2396 proto_tree_add_text(tree, tvb, s_offset, offset+2, "ERROR WRONG SEQ EOC");
2403 /* read header and len for next field */
2404 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
2405 offset
= get_ber_length(tvb
, offset
, &len
, &ind_field
);
2406 eoffset
= offset
+ len
;
2407 /* Make sure we move forward */
2408 if (eoffset
<= hoffset
)
2409 THROW(ReportedBoundsError
);
2411 /*if (ind_field && (len == 2)) {
2412 / disgusting indefinite length zero length field, what are these people doing /
2418 ber_old_sequence_try_again
:
2419 /* have we run out of known entries in the sequence ?*/
2421 /* it was not, move to the next one and try again */
2422 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2423 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, NULL
, NULL
);
2424 cause
= proto_tree_add_string_format_value(
2425 tree
, hf_ber_error
, tvb
, offset
, len
, "illegal_length",
2426 "This field lies beyond the end of the known sequence definition.");
2427 expert_add_info(actx
->pinfo
, cause
, &ei_ber_unknown_field_sequence
);
2428 if (decode_unexpected
) {
2429 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2430 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2436 /* Verify that this one is the one we want.
2437 * Skip check completely if ber_class == ANY
2438 * of if NOCHKTAG is set
2440 /* XXX Bug in asn2eth,
2441 * for scope [7] Scope OPTIONAL,
2443 * { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_scope },
2444 * and there should not be a NOTCHKTAG here
2446 if ( ((seq
->ber_class
== BER_CLASS_CON
) || (seq
->ber_class
== BER_CLASS_APP
) || (seq
->ber_class
== BER_CLASS_PRI
))
2447 && (!(seq
->flags
& BER_FLAGS_NOOWNTAG
)) ) {
2448 if ( (seq
->ber_class
!= BER_CLASS_ANY
)
2450 && ( (seq
->ber_class
!= ber_class
)
2451 || (seq
->tag
!= tag
) ) ) {
2452 /* it was not, move to the next one and try again */
2453 if (seq
->flags
& BER_FLAGS_OPTIONAL
) {
2454 /* well this one was optional so just skip to the next one and try again. */
2456 goto ber_old_sequence_try_again
;
2458 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2459 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, NULL
, NULL
);
2460 if ( seq
->ber_class
== BER_CLASS_UNI
) {
2461 cause
= proto_tree_add_string_format_value(
2462 tree
, hf_ber_error
, tvb
, offset
, len
, "wrong_field",
2463 "Wrong field in SEQUENCE expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
2464 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2467 val_to_str_ext_const(seq
->tag
, &ber_uni_tag_codes_ext
, "Unknown"),
2468 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2471 expert_add_info(actx
->pinfo
, cause
, &ei_ber_sequence_field_wrong
);
2473 cause
= proto_tree_add_string_format_value(
2474 tree
, hf_ber_error
, tvb
, offset
, len
, "wrong_field"
2475 "Wrong field in SEQUENCE expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2476 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2479 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2482 expert_add_info(actx
->pinfo
, cause
, &ei_ber_sequence_field_wrong
);
2484 if (decode_unexpected
) {
2485 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2486 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2492 } else if (!(seq
->flags
& BER_FLAGS_NOTCHKTAG
)) {
2493 if ( (seq
->ber_class
!= BER_CLASS_ANY
)
2495 && ( (seq
->ber_class
!= ber_class
)
2496 || (seq
->tag
!= tag
) ) ) {
2497 /* it was not, move to the next one and try again */
2498 if (seq
->flags
& BER_FLAGS_OPTIONAL
) {
2499 /* well this one was optional so just skip to the next one and try again. */
2501 goto ber_old_sequence_try_again
;
2504 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2505 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, NULL
, NULL
);
2506 if ( seq
->ber_class
== BER_CLASS_UNI
) {
2507 cause
= proto_tree_add_string_format_value(
2508 tree
, hf_ber_error
, tvb
, offset
, len
, "wrong_field",
2509 "Wrong field in sequence expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d",
2510 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2513 val_to_str_ext_const(seq
->tag
, &ber_uni_tag_codes_ext
, "Unknown"),
2514 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2517 expert_add_info(actx
->pinfo
, cause
, &ei_ber_sequence_field_wrong
);
2519 cause
= proto_tree_add_string_format_value(
2520 tree
, hf_ber_error
, tvb
, offset
, len
, "wrong_field",
2521 "Wrong field in sequence expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2522 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2525 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2528 expert_add_info(actx
->pinfo
, cause
, &ei_ber_sequence_field_wrong
);
2530 if (decode_unexpected
) {
2531 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2532 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2540 if (!(seq
->flags
& BER_FLAGS_NOOWNTAG
) ) {
2541 /* dissect header and len for field */
2542 if (ind_field
&& (len
== 2)) {
2543 /* This is a Zero length field */
2544 next_tvb
= tvb_new_subset(tvb
, offset
, len
, len
);
2547 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2548 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
2549 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
2550 if (length_remaining
> (eoffset
- hoffset
- (2 * ind_field
)))
2551 length_remaining
= eoffset
- hoffset
- (2 * ind_field
);
2552 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, eoffset
- hoffset
- (2 * ind_field
));
2556 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
2557 if (length_remaining
> (eoffset
- hoffset
))
2558 length_remaining
= eoffset
- hoffset
;
2559 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, eoffset
- hoffset
);
2563 /* call the dissector for this field */
2564 if ((eoffset
-hoffset
) > length_remaining
) {
2565 /* If the field is indefinite (i.e. we don't know the
2566 * length) of if the tvb is short, then just
2567 * give it all of the tvb and hope for the best.
2569 next_tvb
= tvb_new_subset_remaining(tvb
, hoffset
);
2578 header_field_info
*hfinfo
;
2580 hfinfo
= proto_registrar_get_nth(hf_id
);
2581 name
= hfinfo
->name
;
2585 if (tvb_length_remaining(next_tvb
, 0) > 3) {
2586 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));
2588 printf("SEQUENCE dissect_ber_old_sequence(%s) calling subdissector\n", name
);
2592 if (next_tvb
== NULL
) {
2593 /* Assume that we have a malformed packet. */
2594 THROW(ReportedBoundsError
);
2596 count
= seq
->func(tree
, next_tvb
, 0, actx
);
2601 header_field_info
*hfinfo
;
2603 hfinfo
= proto_registrar_get_nth(hf_id
);
2604 name
= hfinfo
->name
;
2608 printf("SEQUENCE dissect_ber_old_sequence(%s) subdissector ate %d bytes\n", name
, count
);
2611 /* if it was optional and no bytes were eaten and it was */
2612 /* supposed to (len<>0), just try again. */
2613 if ((len
!= 0) && (count
== 0) && (seq
->flags
& BER_FLAGS_OPTIONAL
)) {
2615 goto ber_old_sequence_try_again
;
2616 /* move the offset to the beginning of the next sequenced item */
2620 if (!(seq
->flags
& BER_FLAGS_NOOWNTAG
) ) {
2621 /* if we stripped the tag and length we should also strip the EOC is ind_len
2622 * Unless it's a zero length field (len = 2)
2624 if ((ind_field
== 1) && (len
> 2))
2627 if (show_internal_ber_fields
) {
2628 proto_tree_add_text(tree
, tvb
, offset
, count
, "SEQ FIELD EOC");
2634 /* if we didnt end up at exactly offset, then we ate too many bytes */
2635 if (offset
!= end_offset
) {
2636 tvb_ensure_bytes_exist(tvb
, offset
-2, 2);
2637 cause
= proto_tree_add_string_format_value(
2638 tree
, hf_ber_error
, tvb
, offset
-2, 2, "illegal_length",
2639 "Sequence ate %d too many bytes",
2640 offset
- end_offset
);
2641 expert_add_info_format(actx
->pinfo
, cause
, &ei_ber_error_length
,
2642 "BER Error: too many bytes in Sequence");
2645 /* need to eat this EOC
2646 end_offset = tvb_length(tvb);*/
2648 if (show_internal_ber_fields
) {
2649 proto_tree_add_text(tree
, tvb
, end_offset
-2, 2 , "SEQ EOC");
2655 /* This function dissects a BER set
2658 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
) {
2660 gboolean pcx
, ind
= 0, ind_field
, imp_tag
= FALSE
;
2663 proto_tree
*tree
= parent_tree
;
2664 proto_item
*item
= NULL
;
2666 int end_offset
, s_offset
;
2668 gint length_remaining
;
2670 guint32 mandatory_fields
= 0;
2672 gboolean first_pass
;
2673 const ber_sequence_t
*cset
= NULL
;
2675 #define MAX_SET_ELEMENTS 32
2682 header_field_info
*hfinfo
;
2684 hfinfo
= proto_registrar_get_nth(hf_id
);
2685 name
= hfinfo
->name
;
2689 if (tvb_length_remaining(tvb
, offset
) > 3) {
2690 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));
2692 printf("SET dissect_ber_set(%s) entered\n", name
);
2697 if (!implicit_tag
) {
2699 /* first we must read the sequence header */
2700 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &classx
, &pcx
, &tagx
);
2701 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &lenx
, &ind
);
2703 /* Fixed the length is correctly returned from dissect ber_length
2704 end_offset = tvb_length(tvb);*/
2705 end_offset
= offset
+ lenx
-2;
2707 end_offset
= offset
+ lenx
;
2710 /* sanity check: we only handle Constructed Universal Sets */
2711 if ((classx
!= BER_CLASS_APP
) && (classx
!= BER_CLASS_PRI
)) {
2713 || (!implicit_tag
&& ((classx
!= BER_CLASS_UNI
)
2714 || (tagx
!= BER_UNI_TAG_SET
)))) {
2715 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
2716 cause
= proto_tree_add_string_format_value(
2717 tree
, hf_ber_error
, tvb
, offset
, lenx
, "set_expected",
2718 "SET expected but class:%s(%d) %s tag:%d was found",
2719 val_to_str_const(classx
, ber_class_codes
, "Unknown"),
2721 pcx
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
2723 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_set
);
2724 if (decode_unexpected
) {
2725 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2726 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2732 /* was implicit tag so just use the length of the tvb */
2733 lenx
= tvb_length_remaining(tvb
, offset
);
2734 end_offset
= offset
+lenx
;
2737 /* create subtree */
2740 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, offset
, lenx
, ENC_BIG_ENDIAN
);
2741 tree
= proto_item_add_subtree(item
, ett_id
);
2745 /* record the mandatory elements of the set so we can check we found everything at the end
2746 we can only record 32 elements for now ... */
2747 for (set_idx
= 0; (cset
= &set
[set_idx
])->func
&& (set_idx
< MAX_SET_ELEMENTS
); set_idx
++) {
2749 if (!(cset
->flags
& BER_FLAGS_OPTIONAL
))
2750 mandatory_fields
|= 1 << set_idx
;
2754 /* loop over all entries until we reach the end of the set */
2755 while (offset
< end_offset
) {
2762 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2763 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2765 if ((tvb_get_guint8(tvb
, offset
) == 0) && (tvb_get_guint8(tvb
, offset
+1) == 0)) {
2766 if (show_internal_ber_fields
) {
2767 proto_tree_add_text(tree
, tvb
, s_offset
, offset
+2, "SEQ EOC");
2773 /* read header and len for next field */
2774 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
2775 offset
= get_ber_length(tvb
, offset
, &len
, &ind_field
);
2776 eoffset
= offset
+ len
;
2778 /* Look through the Set to see if this class/id exists and
2779 * hasn't been seen before
2780 * Skip check completely if ber_class == ANY
2781 * of if NOCHKTAG is set
2785 for (first_pass
= TRUE
, cset
= set
, set_idx
= 0; cset
->func
|| first_pass
; cset
++, set_idx
++) {
2787 /* we reset for a second pass when we will look for choices */
2791 cset
= set
; /* reset to the beginning */
2795 if ((first_pass
&& ((cset
->ber_class
== ber_class
) && (cset
->tag
== tag
))) ||
2796 (!first_pass
&& ((cset
->ber_class
== BER_CLASS_ANY
) && (cset
->tag
== -1))) ) /* choices */
2798 if (!(cset
->flags
& BER_FLAGS_NOOWNTAG
) ) {
2799 /* dissect header and len for field */
2800 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2801 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
2802 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
2803 if (length_remaining
> (eoffset
- hoffset
- (2 * ind_field
)))
2804 length_remaining
= eoffset
- hoffset
- (2 * ind_field
);
2805 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, eoffset
- hoffset
- (2 * ind_field
));
2807 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
2808 if (length_remaining
> (eoffset
- hoffset
))
2809 length_remaining
= eoffset
- hoffset
;
2810 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, eoffset
- hoffset
);
2815 /* call the dissector for this field */
2816 if ((eoffset
-hoffset
)>length_remaining
) {
2817 /* If the field is indefinite (i.e. we don't know the
2818 * length) of if the tvb is short, then just
2819 * give it all of the tvb and hope for the best.
2821 next_tvb
= tvb_new_subset_remaining(tvb
, hoffset
);
2830 header_field_info
*hfinfo
;
2832 hfinfo
= proto_registrar_get_nth(hf_id
);
2833 name
= hfinfo
->name
;
2837 if (tvb_length_remaining(next_tvb
, 0) > 3) {
2838 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));
2840 printf("SET dissect_ber_set(%s) calling subdissector\n", name
);
2844 if (next_tvb
== NULL
) {
2845 /* Assume that we have a malformed packet. */
2846 THROW(ReportedBoundsError
);
2849 if ((cset
->flags
& BER_FLAGS_IMPLTAG
))
2851 count
= cset
->func(imp_tag
, next_tvb
, 0, actx
, tree
, *cset
->p_id
);
2853 /* if we consumed some bytes,
2854 or we knew the length was zero (during the first pass only) */
2855 if (count
|| (first_pass
&& ((len
== 0) || ((ind_field
== 1) && (len
== 2))))) {
2857 if (set_idx
< MAX_SET_ELEMENTS
)
2858 mandatory_fields
&= ~(1 << set_idx
);
2862 if (!(cset
->flags
& BER_FLAGS_NOOWNTAG
) ) {
2863 /* if we stripped the tag and length we should also strip the EOC is ind_len */
2864 if (ind_field
== 1) {
2866 if (show_internal_ber_fields
) {
2867 proto_tree_add_text(tree
, tvb
, offset
, count
, "SET FIELD EOC");
2877 /* we didn't find a match */
2878 cause
= proto_tree_add_string_format_value(
2879 tree
, hf_ber_error
, tvb
, offset
, len
, "unknown_field",
2880 "Unknown field in SET class:%s(%d) tag:%d",
2881 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2884 expert_add_info(actx
->pinfo
, cause
, &ei_ber_unknown_field_set
);
2885 if (decode_unexpected
) {
2886 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2887 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2893 if (mandatory_fields
) {
2895 /* OK - we didn't find some of the elements we expected */
2897 for (set_idx
= 0; (cset
= &set
[set_idx
])->func
&& (set_idx
< MAX_SET_ELEMENTS
); set_idx
++) {
2898 if (mandatory_fields
& (1 << set_idx
)) {
2899 /* here is something we should have seen - but didn't! */
2900 cause
= proto_tree_add_string_format_value(
2901 tree
, hf_ber_error
, tvb
, offset
, lenx
, "missing_field",
2902 "Missing field in SET class:%s(%d) tag:%d expected",
2903 val_to_str_const(cset
->ber_class
, ber_class_codes
, "Unknown"),
2906 expert_add_info(actx
->pinfo
, cause
, &ei_ber_missing_field_set
);
2913 /* if we didnt end up at exactly offset, then we ate too many bytes */
2914 if (offset
!= end_offset
) {
2915 tvb_ensure_bytes_exist(tvb
, offset
-2, 2);
2916 cause
= proto_tree_add_string_format_value(
2917 tree
, hf_ber_error
, tvb
, offset
-2, 2, "illegal_length",
2918 "SET ate %d too many bytes",
2919 offset
- end_offset
);
2920 expert_add_info_format(actx
->pinfo
, cause
, &ei_ber_error_length
,
2921 "BER Error: too many bytes in SET");
2925 /* need to eat this EOC
2926 end_offset = tvb_length(tvb);*/
2928 if (show_internal_ber_fields
) {
2929 proto_tree_add_text(tree
, tvb
, end_offset
-2, 2 , "SET EOC");
2938 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
) {
2940 gboolean pcx
, ind
= 0, ind_field
;
2943 proto_tree
*tree
= parent_tree
;
2944 proto_item
*item
= NULL
;
2946 int end_offset
, s_offset
;
2948 gint length_remaining
;
2950 guint32 mandatory_fields
= 0;
2952 gboolean first_pass
;
2953 const ber_old_sequence_t
*cset
= NULL
;
2957 #define MAX_SET_ELEMENTS 32
2962 header_field_info
*hfinfo
;
2964 hfinfo
= proto_registrar_get_nth(hf_id
);
2965 name
= hfinfo
->name
;
2969 if (tvb_length_remaining(tvb
, offset
) > 3) {
2970 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));
2972 printf("SET dissect_old_ber_set(%s) entered\n", name
);
2977 if (!implicit_tag
) {
2979 /* first we must read the sequence header */
2980 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &classx
, &pcx
, &tagx
);
2981 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &lenx
, &ind
);
2983 /* Fixed the length is correctly returned from dissect ber_length
2984 end_offset = tvb_length(tvb);*/
2985 end_offset
= offset
+ lenx
-2;
2987 end_offset
= offset
+ lenx
;
2990 /* sanity check: we only handle Constructed Universal Sets */
2991 if ((classx
!= BER_CLASS_APP
) && (classx
!= BER_CLASS_PRI
)) {
2993 || (!implicit_tag
&& ((classx
!= BER_CLASS_UNI
)
2994 || (tagx
!= BER_UNI_TAG_SET
)))) {
2995 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
2996 cause
= proto_tree_add_string_format_value(
2997 tree
, hf_ber_error
, tvb
, offset
, lenx
, "set_expected",
2998 "SET expected but class:%s(%d) %s tag:%d was found",
2999 val_to_str_const(classx
, ber_class_codes
, "Unknown"),
3001 pcx
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
3003 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_set
);
3004 if (decode_unexpected
) {
3005 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3006 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3012 /* was implicit tag so just use the length of the tvb */
3013 lenx
= tvb_length_remaining(tvb
, offset
);
3014 end_offset
= offset
+lenx
;
3017 /* create subtree */
3020 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, offset
, lenx
, ENC_BIG_ENDIAN
);
3021 tree
= proto_item_add_subtree(item
, ett_id
);
3025 /* record the mandatory elements of the set so we can check we found everything at the end
3026 we can only record 32 elements for now ... */
3027 for (set_idx
= 0; (cset
= &set
[set_idx
])->func
&& (set_idx
< MAX_SET_ELEMENTS
); set_idx
++) {
3029 if (!(cset
->flags
& BER_FLAGS_OPTIONAL
))
3030 mandatory_fields
|= 1 << set_idx
;
3034 /* loop over all entries until we reach the end of the set */
3035 while (offset
< end_offset
) {
3042 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
3043 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
3045 if ((tvb_get_guint8(tvb
, offset
) == 0) && (tvb_get_guint8(tvb
, offset
+1) == 0)) {
3046 if (show_internal_ber_fields
) {
3047 proto_tree_add_text(tree
, tvb
, s_offset
, offset
+2, "SEQ EOC");
3053 /* read header and len for next field */
3054 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
3055 offset
= get_ber_length(tvb
, offset
, &len
, &ind_field
);
3056 eoffset
= offset
+ len
;
3058 /* Look through the Set to see if this class/id exists and
3059 * hasn't been seen before
3060 * Skip check completely if class == ANY
3061 * of if NOCHKTAG is set
3065 for (first_pass
=TRUE
, cset
=set
, set_idx
=0; cset
->func
|| first_pass
; cset
++, set_idx
++) {
3067 /* we reset for a second pass when we will look for choices */
3071 cset
= set
; /* reset to the beginning */
3075 if ((first_pass
&& ((cset
->ber_class
== ber_class
) && (cset
->tag
== tag
))) ||
3076 (!first_pass
&& ((cset
->ber_class
== BER_CLASS_ANY
) && (cset
->tag
== -1))) ) /* choices */
3078 if (!(cset
->flags
& BER_FLAGS_NOOWNTAG
) ) {
3079 /* dissect header and len for field */
3080 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
3081 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
3082 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
3083 if (length_remaining
> (eoffset
- hoffset
- (2 * ind_field
)))
3084 length_remaining
= eoffset
- hoffset
- (2 * ind_field
);
3085 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, eoffset
- hoffset
- (2 * ind_field
));
3087 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
3088 if (length_remaining
> (eoffset
- hoffset
))
3089 length_remaining
= eoffset
- hoffset
;
3090 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, eoffset
- hoffset
);
3094 /* call the dissector for this field */
3095 if ((eoffset
-hoffset
)>length_remaining
) {
3096 /* If the field is indefinite (i.e. we don't know the
3097 * length) of if the tvb is short, then just
3098 * give it all of the tvb and hope for the best.
3100 next_tvb
= tvb_new_subset_remaining(tvb
, hoffset
);
3109 header_field_info
*hfinfo
;
3111 hfinfo
= proto_registrar_get_nth(hf_id
);
3112 name
= hfinfo
->name
;
3116 if (tvb_length_remaining(next_tvb
, 0) > 3) {
3117 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));
3119 printf("SET dissect_old_ber_set(%s) calling subdissector\n", name
);
3123 if (next_tvb
== NULL
) {
3124 /* Assume that we have a malformed packet. */
3125 THROW(ReportedBoundsError
);
3127 count
= cset
->func(tree
, next_tvb
, 0, actx
);
3129 /* if we consumed some bytes,
3130 or we knew the length was zero (during the first pass only) */
3131 if (count
|| (first_pass
&& ((len
== 0) || ((ind_field
== 1) && (len
== 2))))) {
3133 if (set_idx
< MAX_SET_ELEMENTS
)
3134 mandatory_fields
&= ~(1 << set_idx
);
3138 if (!(cset
->flags
& BER_FLAGS_NOOWNTAG
) ) {
3139 /* if we stripped the tag and length we should also strip the EOC is ind_len */
3140 if (ind_field
== 1) {
3142 if (show_internal_ber_fields
) {
3143 proto_tree_add_text(tree
, tvb
, offset
, count
, "SET FIELD EOC");
3153 /* we didn't find a match */
3154 cause
= proto_tree_add_string_format_value(
3155 tree
, hf_ber_error
, tvb
, offset
, len
, "unknown_field",
3156 "Unknown field in SET class:%s(%d) tag:%d",
3157 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3160 expert_add_info(actx
->pinfo
, cause
, &ei_ber_unknown_field_set
);
3161 if (decode_unexpected
) {
3162 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3163 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3169 if (mandatory_fields
) {
3171 /* OK - we didn't find some of the elements we expected */
3173 for (set_idx
= 0; (cset
= &set
[set_idx
])->func
&& (set_idx
< MAX_SET_ELEMENTS
); set_idx
++) {
3174 if (mandatory_fields
& (1 << set_idx
)) {
3175 /* here is something we should have seen - but didn't! */
3176 cause
= proto_tree_add_string_format_value(
3177 tree
, hf_ber_error
, tvb
, offset
, lenx
, "missing_field",
3178 "Missing field in SET class:%s(%d) tag:%d expected",
3179 val_to_str_const(cset
->ber_class
, ber_class_codes
, "Unknown"),
3182 expert_add_info(actx
->pinfo
, cause
, &ei_ber_missing_field_set
);
3187 /* if we didnt end up at exactly offset, then we ate too many bytes */
3188 if (offset
!= end_offset
) {
3189 tvb_ensure_bytes_exist(tvb
, offset
-2, 2);
3190 cause
= proto_tree_add_string_format_value(
3191 tree
, hf_ber_error
, tvb
, offset
-2, 2, "illegal_length",
3192 "SET ate %d too many bytes",
3193 offset
- end_offset
);
3194 expert_add_info_format(actx
->pinfo
, cause
, &ei_ber_error_length
,
3195 "BER Error: too many bytes in SET");
3199 /* need to eat this EOC
3200 end_offset = tvb_length(tvb);*/
3202 if (show_internal_ber_fields
) {
3203 proto_tree_add_text(tree
, tvb
, end_offset
-2, 2 , "SET EOC");
3210 /* this function dissects a BER choice
3211 * If we did not find a matching choice, just return offset unchanged
3212 * in case it was a CHOICE { } OPTIONAL
3215 #define DEBUG_BER_CHOICE
3219 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
)
3222 gboolean pc
, ind
, imp_tag
= FALSE
;
3225 proto_tree
*tree
= parent_tree
;
3226 proto_item
*item
= NULL
;
3227 int end_offset
, start_offset
, count
;
3228 int hoffset
= offset
;
3229 gint length
, length_remaining
;
3231 gboolean first_pass
;
3232 header_field_info
*hfinfo
;
3233 const ber_choice_t
*ch
;
3235 #ifdef DEBUG_BER_CHOICE
3239 hfinfo
= proto_registrar_get_nth(hf_id
);
3240 name
= hfinfo
->name
;
3244 if (tvb_length_remaining(tvb
, offset
) > 3) {
3245 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));
3247 printf("CHOICE dissect_ber_choice(%s) entered len:%d\n", name
, tvb_length_remaining(tvb
, offset
));
3252 start_offset
= offset
;
3258 if (tvb_length_remaining(tvb
, offset
) == 0) {
3259 item
= proto_tree_add_string_format_value(
3260 parent_tree
, hf_ber_error
, tvb
, offset
, 0, "empty_choice",
3261 "Empty choice was found");
3262 expert_add_info(actx
->pinfo
, item
, &ei_ber_empty_choice
);
3266 /* read header and len for choice field */
3267 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
3268 offset
= get_ber_length(tvb
, offset
, &len
, &ind
);
3269 end_offset
= offset
+ len
;
3271 /* Some sanity checks.
3272 * The hf field passed to us MUST be an integer type
3275 hfinfo
= proto_registrar_get_nth(hf_id
);
3276 switch (hfinfo
->type
) {
3283 proto_tree_add_text(
3284 tree
, tvb
, offset
, len
,
3285 "dissect_ber_choice(): Was passed a HF field that was not integer type : %s",
3287 g_warning("dissect_ber_choice(): frame:%u offset:%d Was passed a HF field that was not integer type : %s",
3288 actx
->pinfo
->fd
->num
, offset
, hfinfo
->abbrev
);
3293 /* loop over all entries until we find the right choice or
3294 run out of entries */
3297 while (ch
->func
|| first_pass
) {
3301 /* we reset for a second pass when we will look for choices */
3304 ch
= choice
; /* reset to the beginning */
3311 #ifdef DEBUG_BER_CHOICE
3312 printf("CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d:(expected)%d flags:%d\n", ch
, ber_class
, ch
->ber_class
, tag
, ch
->tag
, ch
->flags
);
3315 && (((ch
->ber_class
== ber_class
) && (ch
->tag
== tag
))
3316 || ((ch
->ber_class
== ber_class
) && (ch
->tag
== -1) && (ch
->flags
& BER_FLAGS_NOOWNTAG
))))
3317 || (!first_pass
&& (((ch
->ber_class
== BER_CLASS_ANY
) && (ch
->tag
== -1)))) /* we failed on the first pass so now try any choices */
3319 if (!(ch
->flags
& BER_FLAGS_NOOWNTAG
)) {
3320 /* dissect header and len for field */
3321 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, start_offset
, NULL
, NULL
, NULL
);
3322 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
3323 start_offset
= hoffset
;
3330 length
= end_offset
- hoffset
;
3332 /* create subtree */
3335 item
= proto_tree_add_uint(parent_tree
, hf_id
, tvb
, hoffset
, end_offset
- hoffset
, ch
->value
);
3336 tree
= proto_item_add_subtree(item
, ett_id
);
3340 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
3341 if (length_remaining
>length
)
3342 length_remaining
= length
;
3345 /* This is bogus and makes the OID_1.0.9506.1.1.cap file
3346 * in Steven J Schaeffer's email of 2005-09-12 fail to dissect
3347 * properly. Maybe we should get rid of 'first_pass'
3349 * It was added as a qad workaround for some problem CMIP
3351 * God, this file is a mess and it is my fault. /ronnie
3354 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, length
);
3356 next_tvb
= tvb
; /* we didn't make selection on this class/tag so pass it on */
3358 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, length
);
3361 #ifdef DEBUG_BER_CHOICE
3365 hfinfo
= proto_registrar_get_nth(hf_id
);
3366 name
= hfinfo
->name
;
3370 if (tvb_length_remaining(next_tvb
, 0) > 3) {
3371 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));
3373 printf("CHOICE dissect_ber_choice(%s) calling subdissector len:%d\n", name
, tvb_length(next_tvb
));
3377 if (next_tvb
== NULL
) {
3378 /* Assume that we have a malformed packet. */
3379 THROW(ReportedBoundsError
);
3382 if ((ch
->flags
& BER_FLAGS_IMPLTAG
))
3384 count
= ch
->func(imp_tag
, next_tvb
, 0, actx
, tree
, *ch
->p_id
);
3385 #ifdef DEBUG_BER_CHOICE
3389 hfinfo
= proto_registrar_get_nth(hf_id
);
3390 name
= hfinfo
->name
;
3394 printf("CHOICE dissect_ber_choice(%s) subdissector ate %d bytes\n", name
, count
);
3397 if ((count
== 0) && (((ch
->ber_class
== ber_class
) && (ch
->tag
== -1) && (ch
->flags
& BER_FLAGS_NOOWNTAG
)) || !first_pass
)) {
3398 /* wrong one, break and try again */
3400 #ifdef DEBUG_BER_CHOICE
3404 hfinfo
= proto_registrar_get_nth(hf_id
);
3405 name
= hfinfo
->name
;
3409 printf("CHOICE dissect_ber_choice(%s) trying again\n", name
);
3412 goto choice_try_again
;
3414 if (!(ch
->flags
& BER_FLAGS_NOOWNTAG
)) {
3416 /* we are traversing a indfinite length choice where we did not pass the tag length */
3417 /* we need to eat the EOC */
3418 if (show_internal_ber_fields
) {
3419 proto_tree_add_text(tree
, tvb
, start_offset
, count
+2, "CHOICE EOC");
3428 /* none of the branches were taken so set the param
3434 /*XXX here we should have another flag to the CHOICE to distinguish
3435 * between the case when we know it is a mandatory or if the CHOICE is optional == no arm matched */
3437 /* oops no more entries and we still havent found
3440 item
= proto_tree_add_string_format_value(
3441 tree
, hf_ber_error
, tvb
, offset
, len
, "missing_choice_field",
3442 "This choice field was not found.");
3443 expert_add_info(actx
->pinfo
, item
, &ei_ber_choice_not_found
);
3447 return start_offset
;
3451 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
)
3457 proto_tree
*tree
= parent_tree
;
3458 proto_item
*item
= NULL
;
3459 int end_offset
, start_offset
, count
;
3460 int hoffset
= offset
;
3461 gint length
, length_remaining
;
3463 gboolean first_pass
;
3464 header_field_info
*hfinfo
;
3465 const ber_old_choice_t
*ch
;
3467 #ifdef DEBUG_BER_CHOICE
3471 hfinfo
= proto_registrar_get_nth(hf_id
);
3472 name
= hfinfo
->name
;
3476 if (tvb_length_remaining(tvb
, offset
) > 3) {
3477 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));
3479 printf("CHOICE dissect_ber_old_choice(%s) entered len:%d\n", name
, tvb_length_remaining(tvb
, offset
));
3483 start_offset
= offset
;
3485 if (tvb_length_remaining(tvb
, offset
) == 0) {
3486 item
= proto_tree_add_string_format_value(
3487 parent_tree
, hf_ber_error
, tvb
, offset
, 0, "empty_choice",
3488 "Empty choice was found");
3489 expert_add_info(actx
->pinfo
, item
, &ei_ber_empty_choice
);
3493 /* read header and len for choice field */
3494 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
3495 offset
= get_ber_length(tvb
, offset
, &len
, &ind
);
3496 end_offset
= offset
+ len
;
3498 /* Some sanity checks.
3499 * The hf field passed to us MUST be an integer type
3502 hfinfo
= proto_registrar_get_nth(hf_id
);
3503 switch (hfinfo
->type
) {
3510 proto_tree_add_text(
3511 tree
, tvb
, offset
, len
,
3512 "dissect_ber_old_choice(): Was passed a HF field that was not integer type : %s",
3514 g_warning("dissect_ber_old_choice(): frame:%u offset:%d Was passed a HF field that was not integer type : %s",
3515 actx
->pinfo
->fd
->num
, offset
, hfinfo
->abbrev
);
3522 /* loop over all entries until we find the right choice or
3523 run out of entries */
3529 while (ch
->func
|| first_pass
) {
3533 /* we reset for a second pass when we will look for choices */
3536 ch
= choice
; /* reset to the beginning */
3543 #ifdef DEBUG_BER_CHOICE
3544 printf("CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d:(expected)%d flags:%d\n", ch
, ber_class
, ch
->ber_class
, tag
, ch
->tag
, ch
->flags
);
3547 && (((ch
->ber_class
== ber_class
) && (ch
->tag
== tag
))
3548 || ((ch
->ber_class
== ber_class
) && (ch
->tag
== -1) && (ch
->flags
& BER_FLAGS_NOOWNTAG
))))
3549 || (!first_pass
&& (((ch
->ber_class
== BER_CLASS_ANY
) && (ch
->tag
== -1)))) /* we failed on the first pass so now try any choices */
3551 if (!(ch
->flags
& BER_FLAGS_NOOWNTAG
)) {
3552 /* dissect header and len for field */
3553 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, start_offset
, NULL
, NULL
, NULL
);
3554 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
3555 start_offset
= hoffset
;
3562 length
= end_offset
- hoffset
;
3564 /* create subtree */
3567 item
= proto_tree_add_uint(parent_tree
, hf_id
, tvb
, hoffset
, end_offset
- hoffset
, ch
->value
);
3568 tree
= proto_item_add_subtree(item
, ett_id
);
3572 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
3573 if (length_remaining
>length
)
3574 length_remaining
= length
;
3577 /* This is bogus and makes the OID_1.0.9506.1.1.cap file
3578 * in Steven J Schaeffer's email of 2005-09-12 fail to dissect
3579 * properly. Maybe we should get rid of 'first_pass'
3581 * It was added as a qad workaround for some problem CMIP
3583 * God, this file is a mess and it is my fault. /ronnie
3586 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, length
);
3588 next_tvb
= tvb
; /* we didn't make selection on this class/tag so pass it on */
3590 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, length_remaining
);
3593 #ifdef DEBUG_BER_CHOICE
3597 hfinfo
= proto_registrar_get_nth(hf_id
);
3598 name
= hfinfo
->name
;
3602 if (tvb_length_remaining(next_tvb
, 0) > 3) {
3603 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));
3605 printf("CHOICE dissect_ber_old_choice(%s) calling subdissector len:%d\n", name
, tvb_length(next_tvb
));
3609 if (next_tvb
== NULL
) {
3610 /* Assume that we have a malformed packet. */
3611 THROW(ReportedBoundsError
);
3613 count
= ch
->func(tree
, next_tvb
, 0, actx
);
3614 #ifdef DEBUG_BER_CHOICE
3618 hfinfo
= proto_registrar_get_nth(hf_id
);
3619 name
= hfinfo
->name
;
3623 printf("CHOICE dissect_ber_old_choice(%s) subdissector ate %d bytes\n", name
, count
);
3626 if ((count
== 0) && (((ch
->ber_class
== ber_class
) && (ch
->tag
== -1) && (ch
->flags
& BER_FLAGS_NOOWNTAG
)) || !first_pass
)) {
3627 /* wrong one, break and try again */
3629 #ifdef DEBUG_BER_CHOICE
3633 hfinfo
= proto_registrar_get_nth(hf_id
);
3634 name
= hfinfo
->name
;
3638 printf("CHOICE dissect_ber_old_choice(%s) trying again\n", name
);
3641 goto choice_try_again
;
3643 if (!(ch
->flags
& BER_FLAGS_NOOWNTAG
)) {
3645 /* we are traversing a indfinite length choice where we did not pass the tag length */
3646 /* we need to eat the EOC */
3647 if (show_internal_ber_fields
) {
3648 proto_tree_add_text(tree
, tvb
, start_offset
, count
+2, "CHOICE EOC");
3657 /* none of the branches were taken so set the param
3663 /*XXX here we should have another flag to the CHOICE to distinguish
3664 * between the case when we know it is a mandatory or if the CHOICE is optional == no arm matched */
3666 /* oops no more entries and we still havent found
3669 cause
= proto_tree_add_string_format_value(
3670 tree
, hf_ber_error
, tvb
, offset
, len
, "missing_choice_field",
3671 "This choice field was not found.");
3672 expert_add_info(actx
->pinfo
, item
, &ei_ber_choice_not_found
);
3676 return start_offset
;
3680 /* this function dissects a BER GeneralString
3683 dissect_ber_GeneralString(asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
, char *name_string
, int name_len
)
3704 /* first we must read the GeneralString header */
3705 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
3706 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
3707 end_offset
= offset
+ len
;
3709 /* sanity check: we only handle Universal GeneralString*/
3710 if ( (ber_class
!= BER_CLASS_UNI
)
3711 || (tag
!= BER_UNI_TAG_GENSTR
) ) {
3712 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
3713 cause
= proto_tree_add_string_format_value(
3714 tree
, hf_ber_error
, tvb
, offset
, len
, "generalstring_expected",
3715 "GeneralString expected but class:%s(%d) %s tag:%d was unexpected",
3716 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3717 ber_class
, pc
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
3719 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_general_string
,
3720 "BER Error: GeneralString expected");
3721 if (decode_unexpected
) {
3722 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3723 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3728 if (len
>= (max_len
- 1)) {
3732 tvb_memcpy(tvb
, str
, offset
, len
);
3736 proto_tree_add_string(tree
, hf_id
, tvb
, offset
, len
, str
);
3744 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
) {
3750 int hoffset
= offset
;
3756 header_field_info
*hfinfo
;
3758 hfinfo
= proto_registrar_get_nth(hf_id
);
3759 name
= hfinfo
->name
;
3763 if (tvb_length_remaining(tvb
, offset
) > 3) {
3764 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));
3766 printf("RESTRICTED STRING dissect_ber_octet_string(%s) entered\n", name
);
3771 if (!implicit_tag
) {
3772 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
3773 offset
= get_ber_length(tvb
, offset
, &len
, NULL
);
3774 eoffset
= offset
+ len
;
3777 if ( (ber_class
!= BER_CLASS_UNI
)
3778 || (tag
!= type
) ) {
3779 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
3780 cause
= proto_tree_add_string_format_value(
3781 tree
, hf_ber_error
, tvb
, offset
, len
, "string_expected",
3782 "String with tag=%d expected but class:%s(%d) %s tag:%d was unexpected",
3784 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3785 ber_class
, pc
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
3787 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_string
);
3788 if (decode_unexpected
) {
3789 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3790 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3797 return dissect_ber_constrained_octet_string(implicit_tag
, actx
, tree
, tvb
, hoffset
, min_len
, max_len
, hf_id
, out_tvb
);
3800 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
)
3802 return dissect_ber_constrained_restricted_string(implicit_tag
, type
, actx
, tree
, tvb
, offset
, NO_BOUND
, NO_BOUND
, hf_id
, out_tvb
);
3806 dissect_ber_GeneralString(asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
, char *name_string
, guint name_len
)
3808 tvbuff_t
*out_tvb
= NULL
;
3811 offset
= dissect_ber_restricted_string(FALSE
, BER_UNI_TAG_GeneralString
, actx
, tree
, tvb
, offset
, hf_id
, (name_string
) ? &out_tvb
: NULL
);
3815 * XXX - do we want to just get what's left in the tvbuff
3816 * if the full length isn't available in the tvbuff, or
3817 * do we want to throw an exception?
3820 tvb_len
= tvb_length(out_tvb
);
3821 if ((guint
)tvb_len
>= name_len
) {
3822 tvb_memcpy(out_tvb
, (guint8
*)name_string
, 0, name_len
-1);
3823 name_string
[name_len
-1] = '\0';
3825 tvb_memcpy(out_tvb
, (guint8
*)name_string
, 0, tvb_len
);
3826 name_string
[tvb_len
] = '\0';
3834 /* 8.19 Encoding of a relative or absolute object identifier value.
3837 dissect_ber_any_oid(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
, tvbuff_t
**value_tvb
, gboolean is_absolute
)
3848 header_field_info
*hfi
;
3852 header_field_info
*hfinfo
;
3854 hfinfo
= proto_registrar_get_nth(hf_id
);
3855 name
= hfinfo
->name
;
3859 if (tvb_length_remaining(tvb
, offset
) > 3) {
3860 printf("OBJECT IDENTIFIER dissect_ber_any_oid(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name
, implicit_tag
, offset
, tvb_length_remaining(tvb
, offset
), tvb_get_guint8(tvb
, offset
), tvb_get_guint8(tvb
, offset
+1), tvb_get_guint8(tvb
, offset
+2));
3862 printf("OBJECT IDENTIFIER dissect_ber_any_oid(%s) entered\n", name
);
3867 if (!implicit_tag
) {
3870 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
3871 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
3872 eoffset
= offset
+ len
;
3873 if ( (ber_class
!= BER_CLASS_UNI
)
3874 || (is_absolute
&& tag
!= BER_UNI_TAG_OID
)
3875 || (!is_absolute
&& tag
!= BER_UNI_TAG_RELATIVE_OID
) ) {
3876 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
3877 cause
= proto_tree_add_string_format_value(
3878 tree
, hf_ber_error
, tvb
, offset
, len
, "oid_expected",
3879 "Object Identifier expected but class:%s(%d) %s tag:%d was unexpected",
3880 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3882 pc
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
3884 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_object_identifier
);
3885 if (decode_unexpected
) {
3886 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3887 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3892 len
= tvb_length_remaining(tvb
, offset
);
3893 eoffset
= offset
+len
;
3896 actx
->created_item
= NULL
;
3897 hfi
= proto_registrar_get_nth(hf_id
);
3898 if ((is_absolute
&& hfi
->type
== FT_OID
) || (!is_absolute
&& hfi
->type
== FT_REL_OID
)) {
3899 actx
->created_item
= proto_tree_add_item(tree
, hf_id
, tvb
, offset
, len
, ENC_BIG_ENDIAN
);
3900 } else if (IS_FT_STRING(hfi
->type
)) {
3901 str
= oid_encoded2string(tvb_get_ptr(tvb
, offset
, len
), len
);
3902 actx
->created_item
= proto_tree_add_string(tree
, hf_id
, tvb
, offset
, len
, str
);
3903 if (actx
->created_item
) {
3904 /* see if we know the name of this oid */
3905 name
= oid_resolved_from_encoded(tvb_get_ptr(tvb
, offset
, len
), len
);
3907 proto_item_append_text(actx
->created_item
, " (%s)", name
);
3911 DISSECTOR_ASSERT_NOT_REACHED();
3915 *value_tvb
= tvb_new_subset(tvb
, offset
, len
, len
);
3921 dissect_ber_any_oid_str(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
, const char **value_stringx
, gboolean is_absolute
)
3923 tvbuff_t
*value_tvb
= NULL
;
3926 offset
= dissect_ber_any_oid(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, (value_stringx
) ? &value_tvb
: NULL
, is_absolute
);
3928 if (value_stringx
) {
3929 if (value_tvb
&& (length
= tvb_length(value_tvb
))) {
3930 *value_stringx
= oid_encoded2string(tvb_get_ptr(value_tvb
, 0, length
), length
);
3932 *value_stringx
= "";
3939 /* 8.19 Encoding of a relative object identifier value.
3942 dissect_ber_relative_oid(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
, tvbuff_t
**value_tvb
)
3944 return dissect_ber_any_oid(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, value_tvb
, FALSE
);
3948 dissect_ber_relative_oid_str(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
, const char **value_stringx
)
3950 return dissect_ber_any_oid_str(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, value_stringx
, FALSE
);
3953 /* 8.19 Encoding of an object identifier value.
3956 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
)
3958 return dissect_ber_any_oid(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, value_tvb
, TRUE
);
3962 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
)
3964 return dissect_ber_any_oid_str(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, value_stringx
, TRUE
);
3968 #define DEBUG_BER_SQ_OF
3972 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
) {
3974 gboolean pcx
, ind
= FALSE
, ind_field
;
3978 proto_tree
*tree
= parent_tree
;
3979 proto_item
*item
= NULL
;
3981 int cnt
, hoffsetx
, end_offset
;
3982 header_field_info
*hfi
;
3983 gint length_remaining
;
3986 #ifdef DEBUG_BER_SQ_OF
3989 header_field_info
*hfinfo
;
3991 hfinfo
= proto_registrar_get_nth(hf_id
);
3992 name
= hfinfo
->name
;
3996 if (tvb_length_remaining(tvb
,offset
) > 3) {
3997 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));
3999 printf("SQ OF dissect_ber_sq_of(%s) entered\n", name
);
4004 if (!implicit_tag
) {
4006 /* first we must read the sequence header */
4007 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &classx
, &pcx
, &tagx
);
4008 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &lenx
, &ind
);
4010 /* if the length is indefinite we don't really know (yet) where the
4011 * object ends so assume it spans the rest of the tvb for now.
4013 end_offset
= offset
+ lenx
;
4015 end_offset
= offset
+ lenx
;
4018 /* sanity check: we only handle Constructed Universal Sequences */
4019 if ((classx
!= BER_CLASS_APP
) && (classx
!= BER_CLASS_PRI
)) {
4021 || (!implicit_tag
&& ((classx
!= BER_CLASS_UNI
)
4022 || (tagx
!= type
)))) {
4023 tvb_ensure_bytes_exist(tvb
, hoffsetx
, 2);
4024 causex
= proto_tree_add_string_format_value(
4025 tree
, hf_ber_error
, tvb
, offset
, lenx
,
4026 (type
== BER_UNI_TAG_SEQUENCE
) ? "set_of_expected" : "sequence_of_expected",
4027 "%s Of expected but class:%s(%d) %s tag:%d was unexpected",
4028 (type
== BER_UNI_TAG_SEQUENCE
) ? "Set" : "Sequence",
4029 val_to_str_const(classx
, ber_class_codes
, "Unknown"),
4030 classx
, pcx
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
4032 if (type
== BER_UNI_TAG_SEQUENCE
) {
4033 expert_add_info_format(
4034 actx
->pinfo
, causex
, &ei_ber_expected_set
,
4035 "BER Error: Set Of expected");
4037 expert_add_info_format(
4038 actx
->pinfo
, causex
, &ei_ber_expected_sequence
,
4039 "BER Error: Sequence Of expected");
4041 if (decode_unexpected
) {
4042 proto_tree
*unknown_tree
= proto_item_add_subtree(causex
, ett_ber_unknown
);
4043 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffsetx
, unknown_tree
);
4049 /* the tvb length should be correct now nope we could be coming from an implicit choice or sequence, thus we
4050 read the items we match and return the length*/
4051 lenx
= tvb_length_remaining(tvb
, offset
);
4052 end_offset
= offset
+ lenx
;
4055 /* count number of items */
4058 /* only count the number of items IFF we have the full blob,
4059 * else this will just generate a [short frame] before we even start
4060 * dissecting a single item.
4062 /* XXX Do we really need to count them at all ? ronnie */
4063 if (tvb_length_remaining(tvb
, offset
) == tvb_reported_length_remaining(tvb
, offset
)) {
4064 while (offset
< end_offset
) {
4070 /*if (ind) { this sequence of was of indefinite length, if this is implicit indefinite impossible maybe
4071 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
4072 if ((tvb_get_guint8(tvb
, offset
) == 0) && (tvb_get_guint8(tvb
, offset
+1) == 0)) {
4077 /* read header and len for next field */
4078 offset
= get_ber_identifier(tvb
, offset
, NULL
, NULL
, NULL
);
4079 offset
= get_ber_length(tvb
, offset
, &len
, &ind
);
4080 /* best place to get real length of implicit sequence of or set of is here... */
4081 /* adjust end_offset if we find somthing that doesnt match */
4084 if (offset
<= s_offset
)
4085 THROW(ReportedBoundsError
);
4090 /* create subtree */
4092 hfi
= proto_registrar_get_nth(hf_id
);
4094 if (hfi
->type
== FT_NONE
) {
4095 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, offset
, lenx
, ENC_BIG_ENDIAN
);
4096 proto_item_append_text(item
, ":");
4098 item
= proto_tree_add_uint(parent_tree
, hf_id
, tvb
, offset
, lenx
, cnt
);
4099 proto_item_append_text(item
, (cnt
== 1) ? " item" : " items");
4101 tree
= proto_item_add_subtree(item
, ett_id
);
4102 ber_check_items (cnt
, min_len
, max_len
, actx
, item
);
4106 /* loop over all entries until we reach the end of the sequence */
4107 while (offset
< end_offset
) {
4118 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
4119 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
4120 if ((tvb_get_guint8(tvb
, offset
) == 0) && (tvb_get_guint8(tvb
, offset
+1) == 0)) {
4121 if (show_internal_ber_fields
) {
4122 proto_tree_add_text(tree
, tvb
, hoffset
, end_offset
-hoffset
, "SEQ OF EOC");
4127 /* read header and len for next field */
4128 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
4129 offset
= get_ber_length(tvb
, offset
, &len
, &ind_field
);
4130 eoffset
= offset
+ len
;
4131 /* Make sure we move forward */
4132 if (eoffset
<= hoffset
)
4133 THROW(ReportedBoundsError
);
4135 if ((ber_class
== BER_CLASS_UNI
) && (tag
== BER_UNI_TAG_EOC
)) {
4136 /* This is a zero length sequence of*/
4137 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
4138 dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
4141 /* verify that this one is the one we want */
4142 /* ahup if we are implicit then we return to the upper layer how much we have used */
4143 if (seq
->ber_class
!= BER_CLASS_ANY
) {
4144 if ((seq
->ber_class
!= ber_class
)
4145 || (seq
->tag
!= tag
) ) {
4146 if (!(seq
->flags
& BER_FLAGS_NOTCHKTAG
)) {
4147 cause
= proto_tree_add_string_format_value(
4148 tree
, hf_ber_error
, tvb
, offset
, len
, "wrong_field",
4149 "Wrong field in SQ OF(tag %u expected %u)",
4152 expert_add_info_format(
4153 actx
->pinfo
, cause
, &ei_ber_sequence_field_wrong
,
4154 "BER Error: Wrong field in Sequence Of");
4155 if (decode_unexpected
) {
4156 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
4157 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
4166 if (!(seq
->flags
& BER_FLAGS_NOOWNTAG
) && !(seq
->flags
& BER_FLAGS_IMPLTAG
)) {
4167 /* dissect header and len for field */
4168 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
4169 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
4171 if ((seq
->flags
== BER_FLAGS_IMPLTAG
) && (seq
->ber_class
== BER_CLASS_CON
)) {
4172 /* Constructed sequence of with a tag */
4173 /* dissect header and len for field */
4174 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
4175 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
4176 /* Function has IMPLICIT TAG */
4179 length_remaining
= tvb_length_remaining(tvb
, hoffset
);
4180 if (length_remaining
>eoffset
-hoffset
)
4181 length_remaining
= eoffset
-hoffset
;
4182 next_tvb
= tvb_new_subset(tvb
, hoffset
, length_remaining
, length_remaining
);
4185 if (seq
->flags
== BER_FLAGS_IMPLTAG
)
4187 /* call the dissector for this field */
4188 seq
->func(imp_tag
, next_tvb
, 0, actx
, tree
, *seq
->p_id
);
4189 /* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
4190 doesnt match the next item, thus this implicit sequence is over, return the number of bytes
4191 we have eaten to allow the possible upper sequence continue... */
4196 /* if we didnt end up at exactly offset, then we ate too many bytes */
4197 if (offset
!= end_offset
) {
4198 tvb_ensure_bytes_exist(tvb
, offset
-2, 2);
4199 causex
= proto_tree_add_string_format_value(
4200 tree
, hf_ber_error
, tvb
, offset
-2, 2, "illegal_length",
4201 "%s Of ate %d too many bytes",
4202 (type
== BER_UNI_TAG_SEQUENCE
) ? "Set" : "Sequence",
4203 offset
- end_offset
);
4204 expert_add_info_format(actx
->pinfo
, causex
, &ei_ber_error_length
,
4205 "BER Error:too many byte in %s",
4206 (type
== BER_UNI_TAG_SEQUENCE
) ? "Set" : "Sequence");
4213 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
) {
4215 gboolean pcx
, ind
= FALSE
, ind_field
;
4219 proto_tree
*tree
= parent_tree
;
4220 proto_item
*item
= NULL
;
4222 int cnt
, hoffsetx
, end_offset
;
4223 header_field_info
*hfi
;
4224 /*gint length_remaining;*/
4226 #ifdef DEBUG_BER_SQ_OF
4229 header_field_info
*hfinfo
;
4231 hfinfo
= proto_registrar_get_nth(hf_id
);
4232 name
= hfinfo
->name
;
4236 if (tvb_length_remaining(tvb
, offset
) > 3) {
4237 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));
4239 printf("SQ OF dissect_ber_old_sq_of(%s) entered\n", name
);
4244 if (!implicit_tag
) {
4246 /* first we must read the sequence header */
4247 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &classx
, &pcx
, &tagx
);
4248 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &lenx
, &ind
);
4250 /* if the length is indefinite we don't really know (yet) where the
4251 * object ends so assume it spans the rest of the tvb for now.
4253 end_offset
= offset
+ lenx
;
4255 end_offset
= offset
+ lenx
;
4258 /* sanity check: we only handle Constructed Universal Sequences */
4259 if ((classx
!= BER_CLASS_APP
) && (classx
!= BER_CLASS_PRI
)) {
4261 || (!implicit_tag
&& ((classx
!= BER_CLASS_UNI
)
4262 || (tagx
!= type
)))) {
4263 tvb_ensure_bytes_exist(tvb
, hoffsetx
, 2);
4264 causex
= proto_tree_add_string_format_value(
4265 tree
, hf_ber_error
, tvb
, offset
, lenx
,
4266 (type
== BER_UNI_TAG_SEQUENCE
) ? "set_of_expected" : "sequence_of_expected",
4267 "%s Of expected but class:%s(%d) %s tag:%d was unexpected",
4268 (type
== BER_UNI_TAG_SEQUENCE
) ? "Set" : "Sequence",
4269 val_to_str_const(classx
, ber_class_codes
, "Unknown"),
4271 pcx
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
4273 if (type
== BER_UNI_TAG_SEQUENCE
) {
4274 expert_add_info_format(
4275 actx
->pinfo
, causex
, &ei_ber_expected_set
,
4276 "BER Error: Set Of expected");
4278 expert_add_info_format(
4279 actx
->pinfo
, causex
, &ei_ber_expected_sequence
,
4280 "BER Error: Sequence Of expected");
4282 if (decode_unexpected
) {
4283 proto_tree
*unknown_tree
= proto_item_add_subtree(causex
, ett_ber_unknown
);
4284 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffsetx
, unknown_tree
);
4290 /* the tvb length should be correct now nope we could be coming from an implicit choice or sequence, thus we
4291 read the items we match and return the length*/
4292 lenx
= tvb_length_remaining(tvb
, offset
);
4293 end_offset
= offset
+ lenx
;
4296 /* count number of items */
4299 /* only count the number of items IFF we have the full blob,
4300 * else this will just generate a [short frame] before we even start
4301 * dissecting a single item.
4303 /* XXX Do we really need to count them at all ? ronnie */
4304 if (tvb_length_remaining(tvb
, offset
) == tvb_reported_length_remaining(tvb
, offset
)) {
4305 while (offset
< end_offset
) {
4311 if (ind
) { /* this sequence of was of indefinite length, so check for EOC */
4312 if ((tvb_get_guint8(tvb
, offset
) == 0) && (tvb_get_guint8(tvb
, offset
+1) == 0)) {
4317 /* read header and len for next field */
4318 offset
= get_ber_identifier(tvb
, offset
, NULL
, NULL
, NULL
);
4319 offset
= get_ber_length(tvb
, offset
, &len
, &ind
);
4320 /* best place to get real length of implicit sequence of or set of is here... */
4321 /* adjust end_offset if we find somthing that doesn't match */
4324 if (offset
<= s_offset
)
4325 THROW(ReportedBoundsError
);
4330 /* create subtree */
4332 hfi
= proto_registrar_get_nth(hf_id
);
4334 if (hfi
->type
== FT_NONE
) {
4335 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, offset
, lenx
, ENC_BIG_ENDIAN
);
4336 proto_item_append_text(item
, ":");
4338 item
= proto_tree_add_uint(parent_tree
, hf_id
, tvb
, offset
, lenx
, cnt
);
4339 proto_item_append_text(item
, (cnt
== 1) ? " item" : " items");
4341 tree
= proto_item_add_subtree(item
, ett_id
);
4345 /* loop over all entries until we reach the end of the sequence */
4346 while (offset
< end_offset
) {
4356 if (ind
) { /*this 'sequence of' was of indefinite length, so check for EOC */
4357 if ((tvb_get_guint8(tvb
, offset
) == 0) && (tvb_get_guint8(tvb
, offset
+1) == 0)) {
4358 if (show_internal_ber_fields
) {
4359 proto_tree_add_text(tree
, tvb
, hoffset
, end_offset
-hoffset
, "SEQ OF EOC");
4364 /* read header and len for next field */
4365 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
4366 offset
= get_ber_length(tvb
, offset
, &len
, &ind_field
);
4367 eoffset
= offset
+ len
;
4368 /* Make sure we move forward */
4369 if (eoffset
<= hoffset
)
4370 THROW(ReportedBoundsError
);
4372 if ((ber_class
== BER_CLASS_UNI
) && (tag
== BER_UNI_TAG_EOC
)) {
4373 /* This is a zero length sequence of*/
4374 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
4375 dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
4378 /* verify that this one is the one we want */
4379 /* ahup if we are implicit then we return to the upper layer how much we have used */
4380 if (seq
->ber_class
!= BER_CLASS_ANY
) {
4381 if ((seq
->ber_class
!= ber_class
)
4382 || (seq
->tag
!= tag
) ) {
4383 if (!(seq
->flags
& BER_FLAGS_NOTCHKTAG
)) {
4384 cause
= proto_tree_add_string_format_value(
4385 tree
, hf_ber_error
, tvb
, offset
, len
, "wrong_field",
4386 "Wrong field in SQ OF");
4387 expert_add_info_format(
4388 actx
->pinfo
, cause
, &ei_ber_sequence_field_wrong
,
4389 "BER Error: Wrong field in Sequence Of");
4390 if (decode_unexpected
) {
4391 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
4392 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
4401 if (!(seq
->flags
& BER_FLAGS_NOOWNTAG
) && !(seq
->flags
& BER_FLAGS_IMPLTAG
)) {
4402 /* dissect header and len for field */
4403 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
4404 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
4406 if ((seq
->flags
== BER_FLAGS_IMPLTAG
) && (seq
->ber_class
== BER_CLASS_CON
)) {
4407 /* Constructed sequence of with a tag */
4408 /* dissect header and len for field */
4409 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
4410 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
4413 /*length_remaining = tvb_length_remaining(tvb, hoffset);
4414 if (length_remaining > (eoffset - hoffset))
4415 length_remaining = eoffset - hoffset;*/
4418 /* call the dissector for this field */
4419 seq
->func(tree
, tvb
, hoffset
, actx
);
4420 /* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
4421 doesnt match the next item, thus this implicit sequence is over, return the number of bytes
4422 we have eaten to allow the possible upper sequence continue... */
4427 /* if we didn't end up at exactly offset, then we ate too many bytes */
4428 if (offset
!= end_offset
) {
4429 tvb_ensure_bytes_exist(tvb
, offset
-2, 2);
4430 causex
=proto_tree_add_string_format_value(
4431 tree
, hf_ber_error
, tvb
, offset
-2, 2, "illegal_length",
4432 "%s Of ate %d too many bytes",
4433 (type
== BER_UNI_TAG_SEQUENCE
) ? "Set" : "Sequence",
4435 expert_add_info_format(actx
->pinfo
, causex
, &ei_ber_error_length
,
4436 "BER Error:too many byte in %s",
4437 (type
== BER_UNI_TAG_SEQUENCE
) ? "Set" : "Sequence");
4444 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
) {
4445 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
);
4449 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
) {
4450 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
);
4454 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
) {
4455 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
);
4459 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
) {
4460 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
);
4464 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
) {
4465 return dissect_ber_old_sq_of(implicit_tag
, BER_UNI_TAG_SEQUENCE
, actx
, parent_tree
, tvb
, offset
, seq
, hf_id
, ett_id
);
4469 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
) {
4470 return dissect_ber_old_sq_of(implicit_tag
, BER_UNI_TAG_SET
, actx
, parent_tree
, tvb
, offset
, seq
, hf_id
, ett_id
);
4474 dissect_ber_GeneralizedTime(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
)
4478 const guint8
*tmpstr
;
4480 char first_delim
[2];
4482 char second_delim
[2];
4493 if (!implicit_tag
) {
4495 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
4496 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
4497 end_offset
= offset
+len
;
4499 /* sanity check. we only handle universal/generalized time */
4500 if ( (ber_class
!= BER_CLASS_UNI
)
4501 || (tag
!= BER_UNI_TAG_GeneralizedTime
)) {
4502 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
4503 cause
= proto_tree_add_string_format_value(
4504 tree
, hf_ber_error
, tvb
, offset
, len
, "generalized_time_expected",
4505 "GeneralizedTime expected but class:%s(%d) %s tag:%d was unexpected",
4506 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
4508 pc
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
4510 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_generalized_time
);
4511 if (decode_unexpected
) {
4512 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
4513 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
4518 len
= tvb_length_remaining(tvb
, offset
);
4519 end_offset
= offset
+len
;
4522 if ((len
< 14) || (len
> 23)) {
4523 cause
= proto_tree_add_string_format_value(
4524 tree
, hf_ber_error
, tvb
, offset
, len
, "illegal_length",
4525 "GeneralizedTime invalid length: %u",
4527 expert_add_info_format(actx
->pinfo
, cause
, &ei_ber_error_length
,
4528 "BER Error: GeneralizedTime invalid length");
4529 if (decode_unexpected
) {
4530 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
4531 dissect_unknown_ber(actx
->pinfo
, tvb
, offset
, unknown_tree
);
4536 tmpstr
= tvb_get_string(wmem_packet_scope(), tvb
, offset
, len
);
4538 /* those fields are allways present */
4539 strptr
+= g_snprintf(str
, 20, "%.4s-%.2s-%.2s %.2s:%.2s:%.2s",
4540 tmpstr
, tmpstr
+4, tmpstr
+6, tmpstr
+8,
4541 tmpstr
+10, tmpstr
+12);
4544 second_delim
[0] = 0;
4545 ret
= sscanf( tmpstr
, "%14d%1[.,+-Z]%4d%1[+-Z]%4d", &tmp_int
, first_delim
, &first_digits
, second_delim
, &second_digits
);
4546 /* tmp_int does not contain valid value bacause of overflow but we use it just for format checking */
4548 cause
= proto_tree_add_string_format_value(
4549 tree
, hf_ber_error
, tvb
, offset
, len
, "invalid_generalized_time",
4550 "GeneralizedTime invalid format: %s",
4552 expert_add_info(actx
->pinfo
, cause
, &ei_ber_invalid_format_generalized_time
);
4553 if (decode_unexpected
) {
4554 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
4555 dissect_unknown_ber(actx
->pinfo
, tvb
, offset
, unknown_tree
);
4560 switch (first_delim
[0]) {
4563 strptr
+= g_snprintf(strptr
, 5, "%c%.3d", first_delim
[0], first_digits
);
4564 switch (second_delim
[0]) {
4567 g_snprintf(strptr
, 12, " (UTC%c%.4d)", second_delim
[0], second_digits
);
4570 g_snprintf(strptr
, 7, " (UTC)");
4575 /* handle the malformed field */
4581 g_snprintf(strptr
, 12, " (UTC%c%.4d)", first_delim
[0], first_digits
);
4584 g_snprintf(strptr
, 7, " (UTC)");
4589 /* handle the malformed field */
4594 proto_tree_add_string(tree
, hf_id
, tvb
, offset
, len
, str
);
4603 dissect_ber_UTCTime(gboolean implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gint hf_id
)
4606 char *outstrptr
= outstr
;
4607 const guint8
*instr
;
4614 proto_tree
*error_tree
;
4615 const gchar
*error_str
= NULL
;
4617 if (!implicit_tag
) {
4619 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
4620 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
4622 /* sanity check: we only handle UTCTime */
4623 if ( (ber_class
!= BER_CLASS_UNI
) || (tag
!= BER_UNI_TAG_UTCTime
) ) {
4624 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
4625 cause
= proto_tree_add_string_format_value(
4626 tree
, hf_ber_error
, tvb
, offset
, len
, "utctime_expected",
4627 "UTCTime expected but class:%s(%d) %s tag:%d was unexpected",
4628 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
4630 pc
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
4632 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_utc_time
);
4633 if (decode_unexpected
) {
4634 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
4635 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
4640 len
= tvb_length_remaining(tvb
, offset
);
4643 if ((len
< 10) || (len
> 19)) {
4644 error_str
= wmem_strdup_printf(wmem_packet_scope(), "BER Error: UTCTime invalid length: %u", len
);
4645 instr
= tvb_get_string(wmem_packet_scope(), tvb
, offset
, len
> 19 ? 19 : len
);
4649 instr
= tvb_get_string(wmem_packet_scope(), tvb
, offset
, len
);
4652 for (i
=0; i
<10; i
++) {
4653 if ((instr
[i
] < '0') || (instr
[i
] > '9')) {
4654 error_str
= "BER Error: malformed UTCTime encoding, "
4655 "first 10 octets have to contain YYMMDDhhmm in digits";
4659 g_snprintf(outstrptr
, 15, "%.2s-%.2s-%.2s %.2s:%.2s", instr
, instr
+2, instr
+4, instr
+6, instr
+8);
4664 if ((instr
[i
] >= '0') && (instr
[i
] <= '9')) {
4666 if ((instr
[i
] >= '0') && (instr
[i
] <= '9')) {
4668 g_snprintf(outstrptr
, 4, ":%.2s", instr
+10);
4671 error_str
= "BER Error: malformed UTCTime encoding, "
4672 "if 11th octet is a digit for seconds, "
4673 "the 12th octet has to be a digit, too";
4683 error_str
= "BER Error: malformed UTCTime encoding, "
4684 "there must be no further octets after \'Z\'";
4687 g_snprintf(outstrptr
, 7, " (UTC)");
4693 error_str
= "BER Error: malformed UTCTime encoding, "
4694 "4 digits must follow on \'+\' resp. \'-\'";
4697 for (n
=i
+1; n
<i
+5; n
++) {
4698 if ((instr
[n
] < '0') || (instr
[n
] > '9')) {
4699 error_str
= "BER Error: malformed UTCTime encoding, "
4700 "4 digits must follow on \'+\' resp. \'-\'";
4704 g_snprintf(outstrptr
, 12, " (UTC%c%.4s)", instr
[i
], instr
+i
+1);
4708 error_str
= wmem_strdup_printf(wmem_packet_scope(),
4709 "BER Error: malformed UTCTime encoding, "
4710 "unexpected character in %dth octet, "
4711 "must be \'Z\', \'+\' or \'-\'", i
+1);
4717 error_str
= wmem_strdup_printf(wmem_packet_scope(),
4718 "BER Error: malformed UTCTime encoding, %d unexpected character%s after %dth octet",
4720 (len
== (i
- 1) ? "s" : ""),
4726 proto_tree_add_string(tree
, hf_id
, tvb
, offset
, len
, outstr
);
4732 cause
= proto_tree_add_string(tree
, hf_id
, tvb
, offset
, len
, instr
);
4733 error_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
4738 cause
= proto_tree_add_string_format(
4739 error_tree
, hf_ber_error
, tvb
, offset
, len
, "invalid_utctime",
4742 expert_add_info(actx
->pinfo
, cause
, &ei_ber_invalid_format_utctime
);
4748 /* 8.6 Encoding of a bitstring value */
4750 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
)
4755 guint32 len
, byteno
;
4756 guint8 pad
= 0, b0
, b1
, val
, *bitstring
;
4759 proto_item
*item
= NULL
;
4761 proto_tree
*tree
= NULL
;
4764 const asn_namedbit
*nb
;
4766 if (!implicit_tag
) {
4768 /* read header and len for the octet string */
4769 offset
= dissect_ber_identifier(actx
->pinfo
, parent_tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
4770 offset
= dissect_ber_length(actx
->pinfo
, parent_tree
, tvb
, offset
, &len
, &ind
);
4771 end_offset
= offset
+ len
;
4773 /* sanity check: we only handle Universal BitStrings */
4775 /* for an IMPLICIT APPLICATION tag asn2eth seems to call this
4776 function with implicit_tag = FALSE. BER_FLAGS_NOOWNTAG was
4777 set so the APPLICATION tag was still present.
4778 So here we relax it for APPLICATION tags. CONTEXT tags may
4779 still cause a problem. */
4781 if (!implicit_tag
&& (ber_class
!= BER_CLASS_APP
)) {
4782 if ( (ber_class
!= BER_CLASS_UNI
)
4783 || (tag
!= BER_UNI_TAG_BITSTRING
) ) {
4784 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
4785 cause
= proto_tree_add_string_format_value(
4786 parent_tree
, hf_ber_error
, tvb
, offset
, len
, "bitstring_expected",
4787 "BitString expected but class:%s(%d) %s tag:%d was unexpected",
4788 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
4789 ber_class
, pc
? ber_pc_codes_short
.true_string
: ber_pc_codes_short
.false_string
,
4791 expert_add_info(actx
->pinfo
, cause
, &ei_ber_expected_bitstring
);
4792 if (decode_unexpected
) {
4793 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
4794 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
4801 len
= tvb_length_remaining(tvb
, offset
);
4802 end_offset
= offset
+len
;
4805 actx
->created_item
= NULL
;
4812 pad
= tvb_get_guint8(tvb
, offset
);
4813 if ((pad
== 0) && (len
== 1)) {
4815 proto_tree_add_item(parent_tree
, hf_ber_bitstring_empty
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4818 proto_item
*pad_item
= proto_tree_add_item(parent_tree
, hf_ber_bitstring_padding
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4820 expert_add_info_format(
4821 actx
->pinfo
, pad_item
, &ei_ber_illegal_padding
,
4822 "Illegal padding (0 .. 7): %d", pad
);
4828 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, offset
, len
, ENC_BIG_ENDIAN
);
4829 actx
->created_item
= item
;
4831 tree
= proto_item_add_subtree(item
, ett_id
);
4835 if (len
<= (guint32
)tvb_length_remaining(tvb
, offset
)) {
4836 *out_tvb
= tvb_new_subset(tvb
, offset
, len
, len
);
4838 *out_tvb
= tvb_new_subset_remaining(tvb
, offset
);
4847 bitstring
= tvb_get_string(wmem_packet_scope(), tvb
, offset
, len
);
4850 if ((len
> 0) && (nb
->bit
< (8*len
-pad
))) {
4851 val
= tvb_get_guint8(tvb
, offset
+ nb
->bit
/8);
4852 bitstring
[(nb
->bit
/8)] &= ~(0x80 >> (nb
->bit
%8));
4853 val
&= 0x80 >> (nb
->bit
%8);
4854 b0
= (nb
->gb0
== -1) ? nb
->bit
/8 :
4855 ((guint32
)nb
->gb0
)/8;
4856 b1
= (nb
->gb1
== -1) ? nb
->bit
/8 :
4857 ((guint32
)nb
->gb1
)/8;
4858 proto_tree_add_item(tree
, *(nb
->p_id
), tvb
, offset
+ b0
, b1
- b0
+ 1, ENC_BIG_ENDIAN
);
4859 } else { /* 8.6.2.4 */
4861 proto_tree_add_boolean(tree
, *(nb
->p_id
), tvb
, offset
+ len
, 0, 0x00);
4864 if (item
&& nb
->tstr
) {
4865 proto_item_append_text(item
, "%s%s", sep
, nb
->tstr
);
4870 if (item
&& nb
->fstr
) {
4871 proto_item_append_text(item
, "%s%s", sep
, nb
->fstr
);
4879 proto_item_append_text(item
, ")");
4881 for (byteno
= 0; byteno
< len
; byteno
++) {
4882 if (bitstring
[byteno
]) {
4883 expert_add_info_format(
4884 actx
->pinfo
, item
, &ei_ber_bits_unknown
,
4885 "Unknown bit(s): 0x%s", bytes_to_str(bitstring
, len
));
4891 if ((pad
> 0) && (pad
< 8) && (len
> 0)) {
4892 guint8 bits_in_pad
= tvb_get_guint8(tvb
, offset
+ len
- 1) & (0xFF >> (8-pad
));
4894 expert_add_info_format(
4895 actx
->pinfo
, item
, &ei_ber_bits_set_padded
,
4896 "Bits set in padded area: 0x%02x", bits_in_pad
);
4900 ber_check_length(8*len
-pad
, min_len
, max_len
, actx
, item
, TRUE
);
4906 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
)
4908 return dissect_ber_constrained_bitstring(implicit_tag
, actx
, parent_tree
, tvb
, offset
, -1, -1, named_bits
, hf_id
, ett_id
, out_tvb
);
4912 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
)
4914 tvbuff_t
*tmp_tvb
= NULL
;
4918 header_field_info
*hfi
;
4921 unsigned int i
, tvb_len
;
4923 offset
= dissect_ber_bitstring(implicit_tag
, actx
, parent_tree
, tvb
, offset
, NULL
, hf_id
, ett_id
, &tmp_tvb
);
4925 tree
= proto_item_get_subtree(actx
->created_item
);
4926 if (bit_fields
&& tree
&& tmp_tvb
) {
4927 /* tmp_tvb points to the actual bitstring (including any pad bits at the end.
4928 * note that this bitstring is not neccessarily always encoded as 4 bytes
4929 * so we have to read it byte by byte.
4932 tvb_len
= tvb_length(tmp_tvb
);
4933 for (i
=0; i
<4; i
++) {
4936 val
|= tvb_get_guint8(tmp_tvb
, i
);
4944 proto_tree_add_boolean(tree
, **bf
, tmp_tvb
, 0, tvb_len
, val
);
4945 hfi
= proto_registrar_get_nth(**bf
);
4946 if (val
& hfi
->bitmask
) {
4947 proto_item_append_text(actx
->created_item
, "%s%s", sep
, hfi
->name
);
4955 proto_item_append_text(actx
->created_item
, ")");
4965 * 8.18 Encoding of a value of the external type
4966 * 8.18.1 The encoding of a value of the external type shall be the BER encoding of the following
4967 * sequence type, assumed to be defined in an environment of EXPLICIT TAGS,
4968 * with a value as specified in the subclauses below:
4970 * [UNIVERSAL 8] IMPLICIT SEQUENCE {
4971 * direct-reference OBJECT IDENTIFIER OPTIONAL,
4972 * indirect-reference INTEGER OPTIONAL,
4973 * data-value-descriptor ObjectDescriptor OPTIONAL,
4975 * single-ASN1-type [0] ABSTRACT-SYNTAX.&Type,
4976 * octet-aligned [1] IMPLICIT OCTET STRING,
4977 * arbitrary [2] IMPLICIT BIT STRING } }
4982 dissect_ber_INTEGER(gboolean implicit_tag
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
) {
4983 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
4984 &actx
->external
.indirect_reference
);
4985 actx
->external
.indirect_ref_present
= TRUE
;
4991 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_
)
4993 if (actx
->external
.u
.ber
.ber_callback
) {
4994 offset
= actx
->external
.u
.ber
.ber_callback(FALSE
, tvb
, offset
, actx
, tree
, hf_index
);
4995 } else if (actx
->external
.direct_ref_present
&&
4996 dissector_get_string_handle(ber_oid_dissector_table
, actx
->external
.direct_reference
)) {
4997 offset
= call_ber_oid_callback(actx
->external
.direct_reference
, tvb
, offset
, actx
->pinfo
, tree
, NULL
);
4999 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, &actx
->external
.octet_aligned
);
5005 dissect_ber_OBJECT_IDENTIFIER(gboolean implicit_tag
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
)
5007 offset
= dissect_ber_object_identifier_str(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, &actx
->external
.direct_reference
);
5008 actx
->external
.direct_ref_present
= TRUE
;
5014 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_
)
5016 offset
= dissect_ber_restricted_string(implicit_tag
, BER_UNI_TAG_ObjectDescriptor
,
5017 actx
, tree
, tvb
, offset
, hf_index
,
5018 &actx
->external
.data_value_descriptor
);
5024 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_
)
5026 if (actx
->external
.u
.ber
.ber_callback
) {
5027 offset
= actx
->external
.u
.ber
.ber_callback(FALSE
, tvb
, offset
, actx
, tree
, hf_index
);
5029 offset
= call_ber_oid_callback(actx
->external
.direct_reference
, tvb
, offset
, actx
->pinfo
, tree
, NULL
);
5036 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_
)
5038 if (actx
->external
.u
.ber
.ber_callback
) {
5039 offset
= actx
->external
.u
.ber
.ber_callback(FALSE
, tvb
, offset
, actx
, tree
, hf_index
);
5041 offset
= dissect_ber_bitstring(implicit_tag
, actx
, tree
, tvb
, offset
,
5042 NULL
, hf_index
, -1, &actx
->external
.arbitrary
);
5048 static const value_string ber_T_encoding_vals
[] = {
5049 { 0, "single-ASN1-type" },
5050 { 1, "octet-aligned" },
5055 static const ber_choice_t T_encoding_choice
[] = {
5056 { 0, &hf_ber_single_ASN1_type
, BER_CLASS_CON
, 0, 0, dissect_ber_T_single_ASN1_type
},
5057 { 1, &hf_ber_octet_aligned
, BER_CLASS_CON
, 1, BER_FLAGS_IMPLTAG
, dissect_ber_T_octet_aligned
},
5058 { 2, &hf_ber_arbitrary
, BER_CLASS_CON
, 2, BER_FLAGS_IMPLTAG
, dissect_ber_T_arbitrary
},
5059 { 0, NULL
, 0, 0, 0, NULL
}
5064 dissect_ber_T_encoding(gboolean implicit_tag _U_
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
) {
5065 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
5066 T_encoding_choice
, hf_index
, ett_ber_T_encoding
,
5067 &actx
->external
.encoding
);
5073 static const ber_sequence_t external_U_sequence
[] = {
5074 { &hf_ber_direct_reference
, BER_CLASS_UNI
, BER_UNI_TAG_OID
, BER_FLAGS_OPTIONAL
|BER_FLAGS_NOOWNTAG
, dissect_ber_OBJECT_IDENTIFIER
},
5075 { &hf_ber_indirect_reference
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_OPTIONAL
|BER_FLAGS_NOOWNTAG
, dissect_ber_INTEGER
},
5076 { &hf_ber_data_value_descriptor
, BER_CLASS_UNI
, BER_UNI_TAG_ObjectDescriptor
, BER_FLAGS_OPTIONAL
|BER_FLAGS_NOOWNTAG
, dissect_ber_ObjectDescriptor
},
5077 { &hf_ber_encoding
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
|BER_FLAGS_NOTCHKTAG
, dissect_ber_T_encoding
},
5078 { NULL
, 0, 0, 0, NULL
}
5081 dissect_ber_external_U(gboolean implicit_tag
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx _U_
, proto_tree
*tree
, int hf_index _U_
)
5083 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
5084 external_U_sequence
, hf_index
, ett_ber_EXTERNAL
);
5089 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
) {
5091 actx
->external
.u
.ber
.ber_callback
= func
;
5093 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
5094 hf_id
, BER_CLASS_UNI
, BER_UNI_TAG_EXTERNAL
, TRUE
, dissect_ber_external_U
);
5096 asn1_ctx_clean_external(actx
);
5102 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_
) {
5105 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
5106 hf_id
, BER_CLASS_UNI
, BER_UNI_TAG_EMBEDDED_PDV
, TRUE
, dissect_ber_external_U
);
5112 dissect_ber_syntax(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
5114 (void) dissect_unknown_ber(pinfo
, tvb
, 0, tree
);
5118 dissect_ber(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
5122 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "BER");
5124 col_set_str(pinfo
->cinfo
, COL_DEF_SRC
, "BER encoded file");
5126 if (!decode_as_syntax
) {
5128 /* if we got here we couldn't find anything better */
5129 col_set_str(pinfo
->cinfo
, COL_INFO
, "Unknown BER");
5131 (void) dissect_unknown_ber(pinfo
, tvb
, 0, tree
);
5135 (void) call_ber_syntax_callback(decode_as_syntax
, tvb
, 0, pinfo
, tree
);
5137 /* see if we have a better name */
5138 name
= get_ber_oid_syntax(decode_as_syntax
);
5139 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Decoded as %s", name
? name
: decode_as_syntax
);
5144 oid_has_dissector(const char *oid
) {
5145 return(dissector_get_string_handle(ber_oid_dissector_table
, oid
) != NULL
);
5149 proto_register_ber(void)
5151 static hf_register_info hf
[] = {
5152 { &hf_ber_id_class
, {
5153 "Class", "ber.id.class", FT_UINT8
, BASE_DEC
,
5154 VALS(ber_class_codes
), 0xc0, "Class of BER TLV Identifier", HFILL
}},
5155 { &hf_ber_bitstring_padding
, {
5156 "Padding", "ber.bitstring.padding", FT_UINT8
, BASE_DEC
,
5157 NULL
, 0x0, "Number of unused bits in the last octet of the bitstring", HFILL
}},
5158 { &hf_ber_bitstring_empty
, {
5159 "Empty", "ber.bitstring.empty", FT_UINT8
, BASE_DEC
,
5160 NULL
, 0x0, "This is an empty bitstring", HFILL
}},
5162 "P/C", "ber.id.pc", FT_BOOLEAN
, 8,
5163 TFS(&ber_pc_codes
), 0x20, "Primitive or Constructed BER encoding", HFILL
}},
5164 { &hf_ber_id_uni_tag
, {
5165 "Tag", "ber.id.uni_tag", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
,
5166 &ber_uni_tag_codes_ext
, 0x1f, "Universal tag type", HFILL
}},
5167 { &hf_ber_id_uni_tag_ext
, {
5168 "Tag", "ber.id.uni_tag", FT_UINT32
, BASE_DEC
,
5169 NULL
, 0, "Universal tag type", HFILL
}},
5171 "Tag", "ber.id.tag", FT_UINT8
, BASE_DEC
,
5172 NULL
, 0x1f, "Tag value for non-Universal classes", HFILL
}},
5173 { &hf_ber_id_tag_ext
, {
5174 "Tag", "ber.id.tag", FT_UINT32
, BASE_DEC
,
5175 NULL
, 0, "Tag value for non-Universal classes", HFILL
}},
5177 "Length", "ber.length", FT_UINT32
, BASE_DEC
,
5178 NULL
, 0, "Length of contents", HFILL
}},
5179 { &hf_ber_unknown_OCTETSTRING
, {
5180 "OCTETSTRING", "ber.unknown.OCTETSTRING", FT_BYTES
, BASE_NONE
,
5181 NULL
, 0, "This is an unknown OCTETSTRING", HFILL
}},
5182 { &hf_ber_unknown_BER_OCTETSTRING
, {
5183 "OCTETSTRING [BER encoded]", "ber.unknown.OCTETSTRING", FT_NONE
, BASE_NONE
,
5184 NULL
, 0, "This is an BER encoded OCTETSTRING", HFILL
}},
5185 { &hf_ber_unknown_BER_primitive
, {
5186 "Primitive [BER encoded]", "ber.unknown.primitive", FT_NONE
, BASE_NONE
,
5187 NULL
, 0, "This is a BER encoded Primitive", HFILL
}},
5188 { &hf_ber_unknown_OID
, {
5189 "OID", "ber.unknown.OID", FT_OID
, BASE_NONE
,
5190 NULL
, 0, "This is an unknown Object Identifier", HFILL
}},
5191 { &hf_ber_unknown_GraphicString
, {
5192 "GRAPHICSTRING", "ber.unknown.GRAPHICSTRING", FT_STRING
, BASE_NONE
,
5193 NULL
, 0, "This is an unknown GRAPHICSTRING", HFILL
}},
5194 { &hf_ber_unknown_NumericString
, {
5195 "NumericString", "ber.unknown.NumericString", FT_STRING
, BASE_NONE
,
5196 NULL
, 0, "This is an unknown NumericString", HFILL
}},
5197 { &hf_ber_unknown_PrintableString
, {
5198 "PrintableString", "ber.unknown.PrintableString", FT_STRING
, BASE_NONE
,
5199 NULL
, 0, "This is an unknown PrintableString", HFILL
}},
5200 { &hf_ber_unknown_TeletexString
, {
5201 "TeletexString", "ber.unknown.TeletexString", FT_STRING
, BASE_NONE
,
5202 NULL
, 0, "This is an unknown TeletexString", HFILL
}},
5203 { &hf_ber_unknown_VisibleString
, {
5204 "VisibleString", "ber.unknown.VisibleString", FT_STRING
, BASE_NONE
,
5205 NULL
, 0, "This is an unknown VisibleString", HFILL
}},
5206 { &hf_ber_unknown_GeneralString
, {
5207 "GeneralString", "ber.unknown.GeneralString", FT_STRING
, BASE_NONE
,
5208 NULL
, 0, "This is an unknown GeneralString", HFILL
}},
5209 { &hf_ber_unknown_UniversalString
, {
5210 "UniversalString", "ber.unknown.UniversalString", FT_STRING
, BASE_NONE
,
5211 NULL
, 0, "This is an unknown UniversalString", HFILL
}},
5212 { &hf_ber_unknown_BMPString
, {
5213 "BMPString", "ber.unknown.BMPString", FT_STRING
, BASE_NONE
,
5214 NULL
, 0, "This is an unknown BMPString", HFILL
}},
5215 { &hf_ber_unknown_IA5String
, {
5216 "IA5String", "ber.unknown.IA5String", FT_STRING
, BASE_NONE
,
5217 NULL
, 0, "This is an unknown IA5String", HFILL
}},
5218 { &hf_ber_unknown_UTCTime
, {
5219 "UTCTime", "ber.unknown.UTCTime", FT_STRING
, BASE_NONE
,
5220 NULL
, 0, "This is an unknown UTCTime", HFILL
}},
5221 { &hf_ber_unknown_UTF8String
, {
5222 "UTF8String", "ber.unknown.UTF8String", FT_STRING
, BASE_NONE
,
5223 NULL
, 0, "This is an unknown UTF8String", HFILL
}},
5224 { &hf_ber_unknown_GeneralizedTime
, {
5225 "GeneralizedTime", "ber.unknown.GeneralizedTime", FT_STRING
, BASE_NONE
,
5226 NULL
, 0, "This is an unknown GeneralizedTime", HFILL
}},
5227 { &hf_ber_unknown_INTEGER
, {
5228 "INTEGER", "ber.unknown.INTEGER", FT_INT64
, BASE_DEC
,
5229 NULL
, 0, "This is an unknown INTEGER", HFILL
}},
5230 { &hf_ber_unknown_BITSTRING
, {
5231 "BITSTRING", "ber.unknown.BITSTRING", FT_BYTES
, BASE_NONE
,
5232 NULL
, 0, "This is an unknown BITSTRING", HFILL
}},
5233 { &hf_ber_unknown_BOOLEAN
, {
5234 "BOOLEAN", "ber.unknown.BOOLEAN", FT_UINT8
, BASE_HEX
,
5235 NULL
, 0, "This is an unknown BOOLEAN", HFILL
}},
5236 { &hf_ber_unknown_ENUMERATED
, {
5237 "ENUMERATED", "ber.unknown.ENUMERATED", FT_UINT32
, BASE_DEC
,
5238 NULL
, 0, "This is an unknown ENUMERATED", HFILL
}},
5240 "BER Error", "ber.error", FT_STRING
, BASE_NONE
,
5241 NULL
, 0, NULL
, HFILL
}},
5242 { &hf_ber_direct_reference
,
5243 { "direct-reference", "ber.direct_reference",
5244 FT_OID
, BASE_NONE
, NULL
, 0,
5245 "ber.OBJECT_IDENTIFIER", HFILL
}},
5246 { &hf_ber_indirect_reference
,
5247 { "indirect-reference", "ber.indirect_reference",
5248 FT_INT32
, BASE_DEC
, NULL
, 0,
5249 "ber.INTEGER", HFILL
}},
5250 { &hf_ber_data_value_descriptor
,
5251 { "data-value-descriptor", "ber.data_value_descriptor",
5252 FT_STRING
, BASE_NONE
, NULL
, 0,
5253 "ber.ObjectDescriptor", HFILL
}},
5255 { "encoding", "ber.encoding",
5256 FT_UINT32
, BASE_DEC
, VALS(ber_T_encoding_vals
), 0,
5257 "ber.T_encoding", HFILL
}},
5258 { &hf_ber_octet_aligned
,
5259 { "octet-aligned", "ber.octet_aligned",
5260 FT_BYTES
, BASE_NONE
, NULL
, 0,
5261 "ber.T_octet_aligned", HFILL
}},
5262 { &hf_ber_arbitrary
,
5263 { "arbitrary", "ber.arbitrary",
5264 FT_BYTES
, BASE_NONE
, NULL
, 0,
5265 "ber.T_arbitrary", HFILL
}},
5266 { &hf_ber_single_ASN1_type
,
5267 { "single-ASN1-type", "ber.single_ASN1_type",
5268 FT_NONE
, BASE_NONE
, NULL
, 0,
5269 "ber.T_single_ASN1_type", HFILL
}},
5271 /* Fragment entries */
5272 { &hf_ber_fragments
,
5273 { "OCTET STRING fragments", "ber.octet_string.fragments", FT_NONE
, BASE_NONE
,
5274 NULL
, 0x00, NULL
, HFILL
} },
5276 { "OCTET STRING fragment", "ber.octet_string.fragment", FT_FRAMENUM
, BASE_NONE
,
5277 NULL
, 0x00, NULL
, HFILL
} },
5278 { &hf_ber_fragment_overlap
,
5279 { "OCTET STRING fragment overlap", "ber.octet_string.fragment.overlap", FT_BOOLEAN
,
5280 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
5281 { &hf_ber_fragment_overlap_conflicts
,
5282 { "OCTET STRING fragment overlapping with conflicting data",
5283 "ber.octet_string.fragment.overlap.conflicts", FT_BOOLEAN
, BASE_NONE
, NULL
,
5284 0x0, NULL
, HFILL
} },
5285 { &hf_ber_fragment_multiple_tails
,
5286 { "OCTET STRING has multiple tail fragments",
5287 "ber.octet_string.fragment.multiple_tails", FT_BOOLEAN
, BASE_NONE
,
5288 NULL
, 0x0, NULL
, HFILL
} },
5289 { &hf_ber_fragment_too_long_fragment
,
5290 { "OCTET STRING fragment too long", "ber.octet_string.fragment.too_long_fragment",
5291 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
,
5293 { &hf_ber_fragment_error
,
5294 { "OCTET STRING defragmentation error", "ber.octet_string.fragment.error", FT_FRAMENUM
,
5295 BASE_NONE
, NULL
, 0x00, NULL
, HFILL
} },
5296 { &hf_ber_fragment_count
,
5297 { "OCTET STRING fragment count", "ber.octet_string.fragment.count", FT_UINT32
, BASE_DEC
,
5298 NULL
, 0x00, NULL
, HFILL
} },
5299 { &hf_ber_reassembled_in
,
5300 { "Reassembled in", "ber.octet_string.reassembled.in", FT_FRAMENUM
, BASE_NONE
,
5301 NULL
, 0x00, NULL
, HFILL
} },
5302 { &hf_ber_reassembled_length
,
5303 { "Reassembled OCTET STRING length", "ber.octet_string.reassembled.length", FT_UINT32
, BASE_DEC
,
5304 NULL
, 0x00, NULL
, HFILL
} }
5308 static gint
*ett
[] = {
5309 &ett_ber_octet_string
,
5310 &ett_ber_reassembled_octet_string
,
5315 &ett_ber_T_encoding
,
5319 static ei_register_info ei
[] = {
5320 { &ei_ber_size_constraint_string
, { "ber.size_constraint.string", PI_PROTOCOL
, PI_WARN
, "Size constraint: string", EXPFILL
}},
5321 { &ei_ber_size_constraint_value
, { "ber.size_constraint.value", PI_PROTOCOL
, PI_WARN
, "Size constraint: values", EXPFILL
}},
5322 { &ei_ber_size_constraint_items
, { "ber.size_constraint.items", PI_PROTOCOL
, PI_WARN
, "Size constraint: items", EXPFILL
}},
5323 { &ei_ber_sequence_field_wrong
, { "ber.error.sequence.field_wrong", PI_MALFORMED
, PI_WARN
, "BER Error: Wrong field in SEQUENCE", EXPFILL
}},
5324 { &ei_ber_expected_octet_string
, { "ber.error.expected.octet_string", PI_MALFORMED
, PI_WARN
, "BER Error: OctetString expected", EXPFILL
}},
5325 { &ei_ber_expected_null
, { "ber.error.expected.null", PI_MALFORMED
, PI_WARN
, "BER Error: NULL expected", EXPFILL
}},
5326 { &ei_ber_expected_null_zero_length
, { "ber.error.expected.null_zero_length", PI_MALFORMED
, PI_WARN
, "BER Error: NULL expect zero length", EXPFILL
}},
5327 { &ei_ber_expected_sequence
, { "ber.error.expected.sequence", PI_MALFORMED
, PI_WARN
, "BER Error: Sequence expected", EXPFILL
}},
5328 { &ei_ber_expected_set
, { "ber.error.expected.set", PI_MALFORMED
, PI_WARN
, "BER Error: SET expected", EXPFILL
}},
5329 { &ei_ber_expected_string
, { "ber.error.expected.string", PI_MALFORMED
, PI_WARN
, "BER Error: String expected", EXPFILL
}},
5330 { &ei_ber_expected_object_identifier
, { "ber.error.expected.object_identifier", PI_MALFORMED
, PI_WARN
, "BER Error: Object Identifier expected", EXPFILL
}},
5331 { &ei_ber_expected_generalized_time
, { "ber.error.expected.generalized_time", PI_MALFORMED
, PI_WARN
, "BER Error: GeneralizedTime expected", EXPFILL
}},
5332 { &ei_ber_expected_utc_time
, { "ber.error.expected.utc_time", PI_MALFORMED
, PI_WARN
, "BER Error: UTCTime expected", EXPFILL
}},
5333 { &ei_ber_expected_bitstring
, { "ber.error.expected.bitstring", PI_MALFORMED
, PI_WARN
, "BER Error: BitString expected", EXPFILL
}},
5334 { &ei_ber_error_length
, { "ber.error.length", PI_MALFORMED
, PI_WARN
, "BER Error length", EXPFILL
}},
5335 { &ei_ber_wrong_tag_in_tagged_type
, { "ber.error.wrong_tag_in_tagged_type", PI_MALFORMED
, PI_WARN
, "BER Error: Wrong tag in tagged type", EXPFILL
}},
5336 { &ei_ber_universal_tag_unknown
, { "ber.error.universal_tag_unknown", PI_MALFORMED
, PI_WARN
, "BER Error: can not handle universal", EXPFILL
}},
5337 { &ei_ber_no_oid
, { "ber.error.no_oid", PI_MALFORMED
, PI_WARN
, "BER Error: No OID supplied to call_ber_oid_callback", EXPFILL
}},
5338 { &ei_ber_oid_not_implemented
, { "ber.error.oid_not_implemented", PI_UNDECODED
, PI_WARN
, "BER: Dissector for OID not implemented. Contact Wireshark developers if you want this supported", EXPFILL
}},
5339 { &ei_ber_syntax_not_implemented
, { "ber.error.syntax_not_implemented", PI_UNDECODED
, PI_WARN
, "BER: Syntax not implemented", EXPFILL
}},
5340 { &ei_ber_value_too_many_bytes
, { "ber.error.value_too_many_bytes", PI_MALFORMED
, PI_WARN
, "Value is encoded with too many bytes", EXPFILL
}},
5341 { &ei_ber_unknown_field_sequence
, { "ber.error.unknown_field.sequence", PI_MALFORMED
, PI_WARN
, "BER Error: Unknown field in Sequence", EXPFILL
}},
5342 { &ei_ber_unknown_field_set
, { "ber.error.unknown_field.set", PI_MALFORMED
, PI_WARN
, "BER Error: Unknown field in SET", EXPFILL
}},
5343 { &ei_ber_missing_field_set
, { "ber.error.missing_field.set", PI_MALFORMED
, PI_WARN
, "BER Error: Missing field in SET", EXPFILL
}},
5344 { &ei_ber_empty_choice
, { "ber.error.empty_choice", PI_MALFORMED
, PI_WARN
, "BER Error: Empty choice was found", EXPFILL
}},
5345 { &ei_ber_choice_not_found
, { "ber.error.choice_not_found", PI_MALFORMED
, PI_WARN
, "BER Error: This choice field was not found", EXPFILL
}},
5346 { &ei_ber_bits_unknown
, { "ber.error.bits_unknown", PI_UNDECODED
, PI_WARN
, "BER Error: Bits unknown", EXPFILL
}},
5347 { &ei_ber_bits_set_padded
, { "ber.error.bits_set_padded", PI_UNDECODED
, PI_WARN
, "BER Error: Bits set in padded area", EXPFILL
}},
5348 { &ei_ber_illegal_padding
, { "ber.error.illegal_padding", PI_UNDECODED
, PI_WARN
, "Illegal padding", EXPFILL
}},
5349 { &ei_ber_invalid_format_generalized_time
, { "ber.error.invalid_format.generalized_time", PI_MALFORMED
, PI_WARN
, "BER Error: GeneralizedTime invalid format", EXPFILL
}},
5350 { &ei_ber_invalid_format_utctime
, { "ber.error.invalid_format.utctime", PI_MALFORMED
, PI_WARN
, "BER Error: malformed UTCTime encoding", EXPFILL
}},
5353 module_t
*ber_module
;
5354 expert_module_t
* expert_ber
;
5355 uat_t
* users_uat
= uat_new("OID Tables",
5359 (void**) &oid_users
,
5361 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
5362 "ChObjectIdentifiers",
5369 proto_ber
= proto_register_protocol("Basic Encoding Rules (ASN.1 X.690)", "BER", "ber");
5371 ber_handle
= register_dissector("ber", dissect_ber
, proto_ber
);
5373 proto_register_field_array(proto_ber
, hf
, array_length(hf
));
5374 proto_register_subtree_array(ett
, array_length(ett
));
5375 expert_ber
= expert_register_protocol(proto_ber
);
5376 expert_register_field_array(expert_ber
, ei
, array_length(ei
));
5378 proto_set_cant_toggle(proto_ber
);
5380 /* Register preferences */
5381 ber_module
= prefs_register_protocol(proto_ber
, NULL
);
5383 prefs_register_bool_preference(ber_module
, "show_internals",
5384 "Show internal BER encapsulation tokens",
5385 "Whether the dissector should also display internal"
5386 " ASN.1 BER details such as Identifier and Length fields", &show_internal_ber_fields
);
5387 prefs_register_bool_preference(ber_module
, "decode_unexpected",
5388 "Decode unexpected tags as BER encoded data",
5389 "Whether the dissector should decode unexpected tags as"
5390 " ASN.1 BER encoded data", &decode_unexpected
);
5391 prefs_register_bool_preference(ber_module
, "decode_octetstring",
5392 "Decode OCTET STRING as BER encoded data",
5393 "Whether the dissector should try decoding OCTET STRINGs as"
5394 " constructed ASN.1 BER encoded data", &decode_octetstring_as_ber
);
5396 prefs_register_bool_preference(ber_module
, "decode_primitive",
5397 "Decode Primitive as BER encoded data",
5398 "Whether the dissector should try decoding unknown primitive as"
5399 " constructed ASN.1 BER encoded data", &decode_primitive_as_ber
);
5401 prefs_register_bool_preference(ber_module
, "warn_too_many_bytes",
5402 "Warn if too many leading zero bits in encoded data",
5403 "Whether the dissector should warn if excessive leading zero (0) bits",
5404 &decode_warning_leading_zero_bits
);
5406 prefs_register_uat_preference(ber_module
, "oid_table", "Object Identifiers",
5407 "A table that provides names for object identifiers"
5408 " and the syntax of any associated values",
5411 ber_oid_dissector_table
= register_dissector_table("ber.oid", "BER OID Dissectors", FT_STRING
, BASE_NONE
);
5412 ber_syntax_dissector_table
= register_dissector_table("ber.syntax", "BER Syntax Dissectors", FT_STRING
, BASE_NONE
);
5413 syntax_table
= g_hash_table_new(g_str_hash
, g_str_equal
); /* oid to syntax */
5415 register_ber_syntax_dissector("ASN.1", proto_ber
, dissect_ber_syntax
);
5417 register_init_routine(ber_defragment_init
);
5421 proto_reg_handoff_ber(void)
5425 oid_add_from_string("asn1", "2.1");
5426 oid_add_from_string("basic-encoding", "2.1.1");
5428 dissector_add_uint("wtap_encap", WTAP_ENCAP_BER
, ber_handle
);
5430 ber_decode_as_foreach(ber_add_syntax_name
, &i
);
5433 qsort(&syntax_names
[1], i
- 1, sizeof(value_string
), cmp_value_string
);
5434 syntax_names
[i
].value
= 0;
5435 syntax_names
[i
].strptr
= NULL
;
5437 /* allow the dissection of BER/DER carried over a TCP transport
5438 by using "Decode As..." */
5439 dissector_add_handle("tcp.port", ber_handle
);