2 * Helpers for ASN.1/BER dissection
3 * Ronnie Sahlberg (C) 2004
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * ITU-T Recommendation X.690 (07/2002),
14 * Information technology ASN.1 encoding rules:
15 * Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)
18 /* TODO: change #.REGISTER signature to dissector_t and
19 * update call_ber_oid_callback() accordingly.
21 * Since we don't pass the TAG/LENGTH from the CHOICE/SEQUENCE/SEQUENCE OF/
22 * SET OF helpers through the callbacks to the next pabket-ber helper
23 * when the tags are IMPLICIT, this causes a problem when we also have
24 * indefinite length at the same time as the tags are implicit.
26 * While the proper fix is to change the signatures for packet-ber.c helpers
27 * as well as the signatures for the callbacks to include the indefinite length
28 * indication that would be a major job.
30 * Originally we used a kludge - we set a global variable in the
31 * CHOICE/SEQUENCE [OF]/SET [OF] helpers to indicate to the next helper
32 * whether the length is indefinite or not.
33 * That had currently only been implemented for {SEQUENCE|SET} [OF] but not
36 * This version attacks the problem(s) in a different way. If we see
37 * indefinite length the get_ber_length traverses the tags within the
38 * compound value and then we return the true length of the compound value
39 * including the EOC. Thus the tvb length is now always correct even for
40 * indefinite length, then if we get implicit tags they can be handled as
41 * if they were definite length.
48 #include <epan/packet.h>
49 #include <epan/exceptions.h>
50 #include <epan/reassemble.h>
51 #include <epan/oids.h>
52 #include <epan/expert.h>
54 #include <epan/decode_as.h>
56 #include <wiretap/wtap.h>
58 #include <epan/ws_printf.h>
61 #include "packet-ber.h"
64 * Set a limit on recursion so we don't blow away the stack. Another approach
65 * would be to remove recursion completely but then we'd exhaust CPU+memory
66 * trying to read a hellabyte of nested indefinite lengths.
68 * XXX - Max nesting in the ASN.1 plugin is 32. Should they match?
70 #define BER_MAX_NESTING 500
72 void proto_register_ber(void);
73 void proto_reg_handoff_ber(void);
76 static int hf_ber_id_class
;
77 static int hf_ber_id_pc
;
78 static int hf_ber_id_uni_tag
;
79 static int hf_ber_id_uni_tag_ext
;
80 static int hf_ber_id_tag
;
81 static int hf_ber_id_tag_ext
;
82 static int hf_ber_length
;
83 static int hf_ber_length_octets
;
84 static int hf_ber_bitstring_padding
;
85 static int hf_ber_bitstring_empty
;
86 static int hf_ber_unknown_OID
;
87 static int hf_ber_unknown_relative_OID
;
88 static int hf_ber_unknown_BOOLEAN
;
89 static int hf_ber_unknown_OCTETSTRING
;
90 static int hf_ber_unknown_BER_OCTETSTRING
;
91 static int hf_ber_unknown_BER_primitive
;
92 static int hf_ber_unknown_GraphicString
;
93 static int hf_ber_unknown_NumericString
;
94 static int hf_ber_unknown_PrintableString
;
95 static int hf_ber_unknown_TeletexString
;
96 static int hf_ber_unknown_VisibleString
;
97 static int hf_ber_unknown_GeneralString
;
98 static int hf_ber_unknown_UniversalString
;
99 static int hf_ber_unknown_BMPString
;
100 static int hf_ber_unknown_IA5String
;
101 static int hf_ber_unknown_UTCTime
;
102 static int hf_ber_unknown_UTF8String
;
103 static int hf_ber_unknown_GeneralizedTime
;
104 static int hf_ber_unknown_INTEGER
;
105 static int hf_ber_unknown_REAL
;
106 static int hf_ber_unknown_BITSTRING
;
107 static int hf_ber_unknown_ENUMERATED
;
108 static int hf_ber_direct_reference
; /* OBJECT_IDENTIFIER */
109 static int hf_ber_indirect_reference
; /* INTEGER */
110 static int hf_ber_data_value_descriptor
; /* ObjectDescriptor */
111 static int hf_ber_encoding
; /* T_encoding */
112 static int hf_ber_single_ASN1_type
; /* T_single_ASN1_type */
113 static int hf_ber_octet_aligned
; /* OCTET_STRING */
114 static int hf_ber_arbitrary
; /* BIT_STRING */
115 static int hf_ber_extra_data
;
116 static int hf_ber_encoding_boiler_plate
;
118 /* Generated from convert_proto_tree_add_text.pl */
119 static int hf_ber_seq_of_eoc
;
120 static int hf_ber_64bit_uint_as_bytes
;
121 static int hf_ber_choice_eoc
;
122 static int hf_ber_seq_field_eoc
;
123 static int hf_ber_seq_eoc
;
124 static int hf_ber_set_field_eoc
;
125 static int hf_ber_set_eoc
;
126 static int hf_ber_null_tag
;
127 static int hf_ber_unknown_octetstring
;
128 static int hf_ber_unknown_data
;
130 static int hf_ber_fragments
;
131 static int hf_ber_fragment
;
132 static int hf_ber_fragment_overlap
;
133 static int hf_ber_fragment_overlap_conflicts
;
134 static int hf_ber_fragment_multiple_tails
;
135 static int hf_ber_fragment_too_long_fragment
;
136 static int hf_ber_fragment_error
;
137 static int hf_ber_fragment_count
;
138 static int hf_ber_reassembled_in
;
139 static int hf_ber_reassembled_length
;
141 static int ett_ber_octet_string
;
142 static int ett_ber_reassembled_octet_string
;
143 static int ett_ber_primitive
;
144 static int ett_ber_unknown
;
145 static int ett_ber_SEQUENCE
;
146 static int ett_ber_EXTERNAL
;
147 static int ett_ber_T_encoding
;
148 static int ett_ber_fragment
;
149 static int ett_ber_fragments
;
151 static expert_field ei_ber_size_constraint_string
;
152 static expert_field ei_ber_size_constraint_value
;
153 static expert_field ei_ber_size_constraint_items
;
154 static expert_field ei_ber_sequence_field_wrong
;
155 static expert_field ei_ber_expected_octet_string
;
156 static expert_field ei_ber_expected_null
;
157 static expert_field ei_ber_expected_null_zero_length
;
158 static expert_field ei_ber_expected_sequence
;
159 static expert_field ei_ber_expected_set
;
160 static expert_field ei_ber_expected_string
;
161 static expert_field ei_ber_expected_object_identifier
;
162 static expert_field ei_ber_expected_generalized_time
;
163 static expert_field ei_ber_expected_utc_time
;
164 static expert_field ei_ber_expected_bitstring
;
165 static expert_field ei_ber_error_length
;
166 static expert_field ei_ber_wrong_tag_in_tagged_type
;
167 static expert_field ei_ber_universal_tag_unknown
;
168 static expert_field ei_ber_no_oid
;
169 static expert_field ei_ber_syntax_not_implemented
;
170 static expert_field ei_ber_oid_not_implemented
;
171 static expert_field ei_ber_value_too_many_bytes
;
172 static expert_field ei_ber_unknown_field_sequence
;
173 static expert_field ei_ber_unknown_field_set
;
174 static expert_field ei_ber_missing_field_set
;
175 static expert_field ei_ber_empty_choice
;
176 static expert_field ei_ber_choice_not_found
;
177 static expert_field ei_ber_bits_unknown
;
178 static expert_field ei_ber_bits_set_padded
;
179 static expert_field ei_ber_illegal_padding
;
180 static expert_field ei_ber_invalid_format_generalized_time
;
181 static expert_field ei_ber_invalid_format_utctime
;
182 static expert_field ei_hf_field_not_integer_type
;
183 static expert_field ei_ber_constr_bitstr
;
184 static expert_field ei_ber_real_not_primitive
;
186 static dissector_handle_t ber_handle
;
187 static dissector_handle_t ber_file_handle
;
189 static bool show_internal_ber_fields
;
190 static bool decode_octetstring_as_ber
;
191 static bool decode_primitive_as_ber
;
192 static bool decode_unexpected
;
193 static bool decode_warning_leading_zero_bits
;
195 static char *decode_as_syntax
;
197 static dissector_table_t ber_oid_dissector_table
;
198 static dissector_table_t ber_syntax_dissector_table
;
200 static GHashTable
*syntax_table
;
202 static int8_t last_class
;
204 static int32_t last_tag
;
205 static uint32_t last_length
;
206 static tvbuff_t
*last_length_tvb
;
207 static int last_length_offset
;
208 static int last_length_len
;
209 static bool last_ind
;
211 static const value_string ber_class_codes
[] = {
212 { BER_CLASS_UNI
, "UNIVERSAL" },
213 { BER_CLASS_APP
, "APPLICATION" },
214 { BER_CLASS_CON
, "CONTEXT" },
215 { BER_CLASS_PRI
, "PRIVATE" },
219 static const true_false_string ber_pc_codes
= {
220 "Constructed Encoding",
225 static const value_string ber_uni_tag_codes
[] = {
226 { BER_UNI_TAG_EOC
, "'end-of-content'" },
227 { BER_UNI_TAG_BOOLEAN
, "BOOLEAN" },
228 { BER_UNI_TAG_INTEGER
, "INTEGER" },
229 { BER_UNI_TAG_BITSTRING
, "BIT STRING" },
230 { BER_UNI_TAG_OCTETSTRING
, "OCTET STRING" },
231 { BER_UNI_TAG_NULL
, "NULL" },
232 { BER_UNI_TAG_OID
, "OBJECT IDENTIFIER" },
233 { BER_UNI_TAG_ObjectDescriptor
, "ObjectDescriptor" },
234 { BER_UNI_TAG_EXTERNAL
, "EXTERNAL" },
235 { BER_UNI_TAG_REAL
, "REAL" },
236 { BER_UNI_TAG_ENUMERATED
, "ENUMERATED" },
237 { BER_UNI_TAG_EMBEDDED_PDV
, "EMBEDDED PDV" },
238 { BER_UNI_TAG_UTF8String
, "UTF8String" },
239 { BER_UNI_TAG_RELATIVE_OID
, "RELATIVE-OID" },
241 * Reserved for future editions of this
242 * Recommendation | International Standard
244 { 14, "Reserved for future editions" },
245 { 15 , "Reserved for future editions" },
247 { BER_UNI_TAG_SEQUENCE
, "SEQUENCE" },
248 { BER_UNI_TAG_SET
, "SET" },
249 { BER_UNI_TAG_NumericString
, "NumericString" },
250 { BER_UNI_TAG_PrintableString
, "PrintableString" },
251 { BER_UNI_TAG_TeletexString
, "TeletexString, T61String" },
252 { BER_UNI_TAG_VideotexString
, "VideotexString" },
253 { BER_UNI_TAG_IA5String
, "IA5String" },
254 { BER_UNI_TAG_UTCTime
, "UTCTime" },
255 { BER_UNI_TAG_GeneralizedTime
, "GeneralizedTime" },
256 { BER_UNI_TAG_GraphicString
, "GraphicString" },
257 { BER_UNI_TAG_VisibleString
, "VisibleString, ISO64String" },
258 { BER_UNI_TAG_GeneralString
, "GeneralString" },
259 { BER_UNI_TAG_UniversalString
, "UniversalString" },
260 { BER_UNI_TAG_CHARACTERSTRING
, "CHARACTER STRING" },
261 { BER_UNI_TAG_BMPString
, "BMPString" },
265 static value_string_ext ber_uni_tag_codes_ext
= VALUE_STRING_EXT_INIT(ber_uni_tag_codes
);
268 static const true_false_string ber_real_binary_vals
= {
273 static const true_false_string ber_real_decimal_vals
= {
279 typedef struct _da_data
{
284 typedef struct _oid_user_t
{
290 UAT_CSTRING_CB_DEF(oid_users
, oid
, oid_user_t
)
291 UAT_CSTRING_CB_DEF(oid_users
, name
, oid_user_t
)
292 UAT_VS_CSTRING_DEF(oid_users
, syntax
, oid_user_t
, 0, "")
294 static oid_user_t
*oid_users
;
295 static unsigned num_oid_users
;
297 #define MAX_SYNTAX_NAMES 128
298 /* Define non_const_value_string as a hack to prevent checkAPIs.pl from complaining */
299 #define non_const_value_string value_string
300 static non_const_value_string syntax_names
[MAX_SYNTAX_NAMES
+1] = {
305 static const fragment_items octet_string_frag_items
= {
306 /* Fragment subtrees */
309 /* Fragment fields */
312 &hf_ber_fragment_overlap
,
313 &hf_ber_fragment_overlap_conflicts
,
314 &hf_ber_fragment_multiple_tails
,
315 &hf_ber_fragment_too_long_fragment
,
316 &hf_ber_fragment_error
,
317 &hf_ber_fragment_count
,
318 /* Reassembled in field */
319 &hf_ber_reassembled_in
,
320 /* Reassembled length field */
321 &hf_ber_reassembled_length
,
322 /* Reassembled data field */
325 "OCTET STRING fragments"
329 add_ber_encoded_label(tvbuff_t
* tvb
, packet_info
* pinfo _U_
, proto_tree
* tree
)
333 ti
= proto_tree_add_item(tree
, hf_ber_encoding_boiler_plate
, tvb
, 0, -1, ENC_NA
);
334 proto_item_set_generated(ti
);
339 oid_copy_cb(void *dest
, const void *orig
, size_t len _U_
)
341 oid_user_t
*u
= (oid_user_t
*)dest
;
342 const oid_user_t
*o
= (const oid_user_t
*)orig
;
344 u
->oid
= g_strdup(o
->oid
);
345 u
->name
= g_strdup(o
->name
);
346 u
->syntax
= o
->syntax
;
354 oid_user_t
*u
= (oid_user_t
*)r
;
361 cmp_value_string(const void *v1
, const void *v2
)
363 const value_string
*vs1
= (const value_string
*)v1
;
364 const value_string
*vs2
= (const value_string
*)v2
;
366 return strcmp(vs1
->strptr
, vs2
->strptr
);
369 static uat_field_t users_flds
[] = {
370 UAT_FLD_OID(oid_users
, oid
, "OID", "Object Identifier"),
371 UAT_FLD_CSTRING(oid_users
, name
, "Name", "Human readable name for the OID"),
372 UAT_FLD_VS(oid_users
, syntax
, "Syntax", syntax_names
, "Syntax of values associated with the OID"),
377 static void ber_prompt(packet_info
*pinfo _U_
, char* result
)
379 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "Decode ASN.1 file as");
382 static void *ber_value(packet_info
*pinfo _U_
)
388 struct ber_decode_as_populate
390 decode_as_add_to_list_func add_to_list
;
395 decode_ber_add_to_list(void *key
, void *value
, void *user_data
)
397 struct ber_decode_as_populate
* populate
= (struct ber_decode_as_populate
*)user_data
;
398 dtbl_entry_t
*dtbl_entry
= (dtbl_entry_t
*)value
;
399 populate
->add_to_list("ASN.1", (char *)key
, dtbl_entry_get_initial_handle(dtbl_entry
), populate
->ui_element
);
402 static void ber_populate_list(const char *table_name _U_
, decode_as_add_to_list_func add_to_list
, void *ui_element
)
404 struct ber_decode_as_populate populate
;
406 populate
.add_to_list
= add_to_list
;
407 populate
.ui_element
= ui_element
;
409 ber_decode_as_foreach(decode_ber_add_to_list
, &populate
);
412 static bool ber_decode_as_reset(const char *name _U_
, const void *pattern _U_
)
414 g_free(decode_as_syntax
);
415 decode_as_syntax
= NULL
;
419 static bool ber_decode_as_change(const char *name _U_
, const void *pattern _U_
, const void *handle _U_
, const char* list_name
)
421 g_free(decode_as_syntax
);
422 decode_as_syntax
= g_strdup(list_name
);
427 dissect_ber_oid_NULL_callback(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
, void* data _U_
)
429 return tvb_captured_length(tvb
);
434 register_ber_oid_dissector_handle(const char *oid
, dissector_handle_t dissector
, int proto _U_
, const char *name
)
436 dissector_add_string("ber.oid", oid
, dissector
);
437 oid_add_from_string(name
, oid
);
441 register_ber_oid_dissector(const char *oid
, dissector_t dissector
, int proto
, const char *name
)
443 dissector_handle_t dissector_handle
;
445 dissector_handle
= create_dissector_handle(dissector
, proto
);
446 dissector_add_string("ber.oid", oid
, dissector_handle
);
447 oid_add_from_string(name
, oid
);
451 register_ber_syntax_dissector(const char *syntax
, int proto
, dissector_t dissector
)
453 dissector_handle_t dissector_handle
;
455 dissector_handle
= create_dissector_handle_with_name_and_description(dissector
, proto
, NULL
, syntax
);
456 dissector_add_string("ber.syntax", syntax
, dissector_handle
);
461 register_ber_oid_syntax(const char *oid
, const char *name
, const char *syntax
)
464 if (syntax
&& *syntax
)
465 g_hash_table_insert(syntax_table
, (void *)g_strdup(oid
), (void *)g_strdup(syntax
));
468 register_ber_oid_name(oid
, name
);
471 /* Register the oid name to get translation in proto dissection */
473 register_ber_oid_name(const char *oid
, const char *name
)
475 oid_add_from_string(name
, oid
);
479 ber_add_syntax_name(void *key
, void *value _U_
, void *user_data
)
481 unsigned *i
= (unsigned*)user_data
;
483 if (*i
< MAX_SYNTAX_NAMES
) {
484 syntax_names
[*i
].value
= *i
;
485 syntax_names
[*i
].strptr
= (const char*)key
;
493 ber_decode_as_dt(const char *table_name _U_
, ftenum_t selector_type _U_
, void *key
, void *value
, void *user_data
)
495 da_data
*decode_as_data
;
497 decode_as_data
= (da_data
*)user_data
;
499 decode_as_data
->func(key
, value
, decode_as_data
->user_data
);
503 ber_decode_as_foreach(GHFunc func
, void *user_data
)
505 da_data decode_as_data
;
507 decode_as_data
.func
= func
;
508 decode_as_data
.user_data
= user_data
;
510 dissector_table_foreach("ber.syntax", ber_decode_as_dt
, &decode_as_data
);
514 /* Get oid syntax from hash table to get translation in proto dissection(packet-per.c) */
516 get_ber_oid_syntax(const char *oid
)
518 return (const char *)g_hash_table_lookup(syntax_table
, oid
);
522 ber_update_oids(void)
526 for (i
= 0; i
< num_oid_users
; i
++)
527 register_ber_oid_syntax(oid_users
[i
].oid
, oid_users
[i
].name
, oid_users
[i
].syntax
);
531 ber_check_length (uint32_t length
, int32_t min_len
, int32_t max_len
, asn1_ctx_t
*actx
, proto_item
*item
, bool bit
)
533 if ((min_len
!= -1) && (length
< (uint32_t)min_len
)) {
534 expert_add_info_format(
535 actx
->pinfo
, item
, &ei_ber_size_constraint_string
,
536 "Size constraint: %sstring too short: %d (%d .. %d)",
537 bit
? "bit " : "", length
, min_len
, max_len
);
538 } else if ((max_len
!= -1) && (length
> (uint32_t)max_len
)) {
539 expert_add_info_format(
540 actx
->pinfo
, item
, &ei_ber_size_constraint_string
,
541 "Size constraint: %sstring too long: %d (%d .. %d)",
542 bit
? "bit " : "", length
, min_len
, max_len
);
547 ber_check_value64 (int64_t value
, int64_t min_len
, int64_t max_len
, asn1_ctx_t
*actx
, proto_item
*item
)
549 if ((min_len
!= -1) && (value
< min_len
)) {
550 expert_add_info_format(
551 actx
->pinfo
, item
, &ei_ber_size_constraint_value
,
552 "Size constraint: value too small: %" PRId64
" (%" PRId64
" .. %" PRId64
")",
553 value
, min_len
, max_len
);
554 } else if ((max_len
!= -1) && (value
> max_len
)) {
555 expert_add_info_format(
556 actx
->pinfo
, item
, &ei_ber_size_constraint_value
,
557 "Size constraint: value too big: %" PRId64
" (%" PRId64
" .. %" PRId64
")",
558 value
, min_len
, max_len
);
563 ber_check_value (uint32_t value
, int32_t min_len
, int32_t max_len
, asn1_ctx_t
*actx
, proto_item
*item
)
565 if ((min_len
!= -1) && (value
< (uint32_t)min_len
)) {
566 expert_add_info_format(
567 actx
->pinfo
, item
, &ei_ber_size_constraint_value
,
568 "Size constraint: value too small: %d (%d .. %d)",
569 value
, min_len
, max_len
);
570 } else if ((max_len
!= -1) && (value
> (uint32_t)max_len
)) {
571 expert_add_info_format(
572 actx
->pinfo
, item
, &ei_ber_size_constraint_value
,
573 "Size constraint: value too big: %d (%d .. %d)",
574 value
, min_len
, max_len
);
579 ber_check_items (int cnt
, int32_t min_len
, int32_t max_len
, asn1_ctx_t
*actx
, proto_item
*item
)
581 if ((min_len
!= -1) && (cnt
< min_len
)) {
582 expert_add_info_format(
583 actx
->pinfo
, item
, &ei_ber_size_constraint_items
,
584 "Size constraint: too few items: %d (%d .. %d)",
585 cnt
, min_len
, max_len
);
586 } else if ((max_len
!= -1) && (cnt
> max_len
)) {
587 expert_add_info_format(
588 actx
->pinfo
, item
, &ei_ber_size_constraint_items
,
589 "Size constraint: too many items: %d (%d .. %d)",
590 cnt
, min_len
, max_len
);
595 * XXX - if the specified length is less than the remaining length
596 * of data in the tvbuff, either 1) the specified length is bad and
597 * we should report that with an expert info or 2) the tvbuff is
598 * unreassembled and we should make the new tvbuff also be an
599 * unreassembled tvbuff.
602 ber_tvb_new_subset_length(tvbuff_t
*tvb
, const int backing_offset
, const int backing_length
)
604 int length_remaining
;
606 length_remaining
= tvb_reported_length_remaining(tvb
, backing_offset
);
607 return tvb_new_subset_length(tvb
, backing_offset
, (length_remaining
> backing_length
) ? backing_length
: length_remaining
);
611 dissect_ber_tagged_type(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, int8_t tag_cls
, int32_t tag_tag
, bool tag_impl
, ber_type_fn type
)
615 int identifier_offset
;
618 tvbuff_t
*next_tvb
= tvb
;
623 header_field_info
*hfinfo
;
625 hfinfo
= proto_registrar_get_nth(hf_id
);
630 if (tvb_reported_length_remaining(tvb
, offset
) > 3) {
631 proto_tree_add_debug_text(tree
, "dissect_ber_tagged_type(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name
, implicit_tag
, offset
, tvb_reported_length_remaining(tvb
, offset
), tvb_get_uint8(tvb
, offset
), tvb_get_uint8(tvb
, offset
+1), tvb_get_uint8(tvb
, offset
+2));
633 proto_tree_add_debug_text(tree
, "dissect_ber_tagged_type(%s) entered\n", name
);
639 offset
= type(tag_impl
, tvb
, offset
, actx
, tree
, hf_id
);
643 identifier_offset
= offset
;
644 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &tmp_cls
, NULL
, &tmp_tag
);
645 identifier_len
= offset
- identifier_offset
;
646 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &tmp_len
, NULL
);
648 if ((tmp_cls
!= tag_cls
) || (tmp_tag
!= tag_tag
)) {
649 proto_tree_add_expert_format(
650 tree
, actx
->pinfo
, &ei_ber_wrong_tag_in_tagged_type
,
651 tvb
, identifier_offset
, identifier_len
,
652 "BER Error: Wrong tag in tagged type - expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
653 val_to_str_const(tag_cls
, ber_class_codes
, "Unknown"),
656 val_to_str_ext_const(tag_tag
, &ber_uni_tag_codes_ext
, "Unknown"),
657 val_to_str_const(tmp_cls
, ber_class_codes
, "Unknown"),
663 next_tvb
= ber_tvb_new_subset_length(tvb
, offset
, tmp_len
);
664 type(tag_impl
, next_tvb
, 0, actx
, tree
, hf_id
);
667 offset
= type(tag_impl
, tvb
, offset
, actx
, tree
, hf_id
);
674 * Add a "length bogus" error.
677 ber_add_bad_length_error(packet_info
*pinfo
, proto_tree
*tree
,
678 const char *name
, tvbuff_t
*tvb
, const int start
,
683 ti
= proto_tree_add_expert_format(
684 tree
, pinfo
, &ei_ber_error_length
, tvb
, start
, length
,
685 "BER Error: %s: length of item (%d) is not valid",
691 * Add an "exceeds tvb length" error.
694 ber_add_large_length_error(packet_info
*pinfo
, proto_tree
*tree
, tvbuff_t
*tvb
,
695 int offset
, int length
, tvbuff_t
*len_tvb
,
696 const int len_offset
, const uint32_t len_length
)
698 proto_tree_add_expert_format(
699 tree
, pinfo
, &ei_ber_error_length
, len_tvb
, len_offset
, len_length
,
700 "BER Error: length %u longer than tvb_reported_length_remaining: %d",
702 tvb_reported_length_remaining(tvb
, offset
));
706 * Like proto_tree_add_item(), but checks whether the length of the item
707 * being added is appropriate for the type of the item being added, so
708 * if it's not, we report an error rather than a dissector bug.
710 * This is for use when a field that's nominally an OCTET STRING but
711 * where we want the string further interpreted, e.g. as a number or
712 * a network address or a UN*X-style time stamp.
714 * XXX - this duplicates the length checking in proto_tree_add_item()
715 * and the routines it calls; that should really be done in one
716 * place. We *do* want to report a dissector bug in proto_tree_add_item()
717 * if the dissector explicitly says, for example, "this IPv4 address is
718 * 7 bytes long", but we don't want to report a dissector bug if the
719 * *packet* says "this IPv4 address is 7 bytes long", we want to report
720 * a malformed packet.
723 ber_proto_tree_add_item(packet_info
*pinfo
, proto_tree
*tree
,
724 const int hfindex
, tvbuff_t
*tvb
, const int start
,
725 int length
, const unsigned encoding
)
727 header_field_info
*hfinfo
;
730 hfinfo
= proto_registrar_get_nth((unsigned)hfindex
);
731 if (hfinfo
!= NULL
) {
732 switch (hfinfo
->type
) {
743 if ((length
!= 1) && (length
!= 2) && (length
!= 3) &&
745 return ber_add_bad_length_error(pinfo
, tree
,
746 hfinfo
->name
, tvb
, start
, length
);
750 if (length
!= FT_IPv4_LEN
)
751 return ber_add_bad_length_error(pinfo
, tree
,
752 hfinfo
->name
, tvb
, start
, length
);
756 if (length
!= FT_IPXNET_LEN
)
757 return ber_add_bad_length_error(pinfo
, tree
,
758 hfinfo
->name
, tvb
, start
, length
);
762 if ((length
< 0) || (length
> FT_IPv6_LEN
))
763 return ber_add_bad_length_error(pinfo
, tree
,
764 hfinfo
->name
, tvb
, start
, length
);
768 if (length
!= FT_ETHER_LEN
)
769 return ber_add_bad_length_error(pinfo
, tree
,
770 hfinfo
->name
, tvb
, start
, length
);
774 if (length
!= FT_GUID_LEN
)
775 return ber_add_bad_length_error(pinfo
, tree
,
776 hfinfo
->name
, tvb
, start
, length
);
781 return ber_add_bad_length_error(pinfo
, tree
,
782 hfinfo
->name
, tvb
, start
, length
);
787 return ber_add_bad_length_error(pinfo
, tree
,
788 hfinfo
->name
, tvb
, start
, length
);
791 case FT_ABSOLUTE_TIME
:
792 case FT_RELATIVE_TIME
:
793 if ((length
!= 4) && (length
!= 8))
794 return ber_add_bad_length_error(pinfo
, tree
,
795 hfinfo
->name
, tvb
, start
, length
);
799 ti
= proto_tree_add_item(tree
, hfindex
, tvb
, start
, length
, encoding
);
800 proto_item_append_text(ti
, "<MISSING>");
808 return proto_tree_add_item(tree
, hfindex
, tvb
, start
, length
, encoding
);
812 // NOLINTNEXTLINE(misc-no-recursion)
813 try_dissect_unknown_ber(packet_info
*pinfo
, tvbuff_t
*tvb
, volatile int offset
, proto_tree
*tree
, int nest_level
)
819 int identifier_offset
;
825 proto_item
*item
= NULL
;
826 proto_tree
*next_tree
= NULL
;
830 volatile bool is_decoded_as
;
834 if (nest_level
> BER_MAX_NESTING
) {
835 /* Assume that we have a malformed packet. */
836 THROW(ReportedBoundsError
);
839 start_offset
= offset
;
840 asn1_ctx_init(&asn1_ctx
, ASN1_ENC_BER
, true, pinfo
);
842 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
844 offset
= get_ber_length(tvb
, offset
, &len
, &ind
);
845 len_len
= offset
- len_offset
;
847 if (len
> (uint32_t)tvb_reported_length_remaining(tvb
, offset
)) {
848 /* hmm maybe something bad happened or the frame is short;
849 since these are not vital outputs just return instead of
850 throwing an exception.
853 if (show_internal_ber_fields
) {
854 offset
= dissect_ber_identifier(pinfo
, tree
, tvb
, start_offset
, &ber_class
, &pc
, &tag
);
855 offset
= dissect_ber_length(pinfo
, tree
, tvb
, offset
, &len
, NULL
);
857 ber_add_large_length_error(pinfo
, tree
, tvb
, offset
, len
, tvb
, len_offset
, len_len
);
858 return tvb_reported_length(tvb
);
860 /* we don't care about the class only on the constructor flag */
863 /* this is not constructed */
865 switch (ber_class
) { /* we do care about the class */
866 case BER_CLASS_UNI
: /* it a Universal tag - we can decode it */
868 case BER_UNI_TAG_EOC
:
869 /* XXX: shouldn't really get here */
871 case BER_UNI_TAG_INTEGER
:
872 offset
= dissect_ber_integer(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_INTEGER
, NULL
);
874 case BER_UNI_TAG_REAL
:
875 offset
= dissect_ber_real(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_REAL
, NULL
);
877 case BER_UNI_TAG_BITSTRING
:
878 offset
= dissect_ber_bitstring(false, &asn1_ctx
, tree
, tvb
, start_offset
, NULL
, 0, hf_ber_unknown_BITSTRING
, -1, NULL
);
880 case BER_UNI_TAG_ENUMERATED
:
881 offset
= dissect_ber_integer(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_ENUMERATED
, NULL
);
883 case BER_UNI_TAG_GraphicString
:
884 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_GraphicString
, NULL
);
886 case BER_UNI_TAG_OCTETSTRING
:
887 is_decoded_as
= false;
888 if (decode_octetstring_as_ber
&& (len
>= 2)) {
889 volatile int ber_offset
= 0;
890 uint32_t ber_len
= 0;
892 ber_offset
= get_ber_identifier(tvb
, offset
, NULL
, &pc
, NULL
);
893 ber_offset
= get_ber_length(tvb
, ber_offset
, &ber_len
, NULL
);
897 if (pc
&& (ber_len
> 0) && (ber_len
+ (ber_offset
- offset
) == len
)) {
898 /* Decoded a constructed ASN.1 tag with a length indicating this
899 * could be BER encoded data. Try dissecting as unknown BER.
901 is_decoded_as
= true;
902 if (show_internal_ber_fields
) {
903 offset
= dissect_ber_identifier(pinfo
, tree
, tvb
, start_offset
, NULL
, NULL
, NULL
);
904 offset
= dissect_ber_length(pinfo
, tree
, tvb
, offset
, NULL
, NULL
);
906 item
= ber_proto_tree_add_item(pinfo
, tree
, hf_ber_unknown_BER_OCTETSTRING
, tvb
, offset
, len
, ENC_NA
);
907 next_tree
= proto_item_add_subtree(item
, ett_ber_octet_string
);
908 offset
= try_dissect_unknown_ber(pinfo
, tvb
, offset
, next_tree
, nest_level
+ 1);
911 if (!is_decoded_as
) {
912 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_OCTETSTRING
, NULL
);
915 case BER_UNI_TAG_OID
:
916 offset
= dissect_ber_object_identifier_str(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_OID
, NULL
);
918 case BER_UNI_TAG_RELATIVE_OID
:
919 offset
= dissect_ber_relative_oid_str(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_relative_OID
, NULL
);
921 case BER_UNI_TAG_NumericString
:
922 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_NumericString
, NULL
);
924 case BER_UNI_TAG_PrintableString
:
925 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_PrintableString
, NULL
);
927 case BER_UNI_TAG_TeletexString
:
928 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_TeletexString
, NULL
);
930 case BER_UNI_TAG_VisibleString
:
931 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_VisibleString
, NULL
);
933 case BER_UNI_TAG_GeneralString
:
934 offset
= dissect_ber_GeneralString(&asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_GeneralString
, NULL
, 0);
936 case BER_UNI_TAG_BMPString
:
937 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_BMPString
, NULL
);
939 case BER_UNI_TAG_UniversalString
:
940 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_UniversalString
, NULL
);
942 case BER_UNI_TAG_IA5String
:
943 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_IA5String
, NULL
);
945 case BER_UNI_TAG_UTCTime
:
946 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_UTCTime
, NULL
);
948 case BER_UNI_TAG_NULL
:
949 proto_tree_add_item(tree
, hf_ber_null_tag
, tvb
, offset
, len
, ENC_NA
);
951 case BER_UNI_TAG_UTF8String
:
952 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_UTF8String
, NULL
);
954 case BER_UNI_TAG_GeneralizedTime
:
955 offset
= dissect_ber_octet_string(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_GeneralizedTime
, NULL
);
957 case BER_UNI_TAG_BOOLEAN
:
958 offset
= dissect_ber_boolean(false, &asn1_ctx
, tree
, tvb
, start_offset
, hf_ber_unknown_BOOLEAN
, NULL
);
961 identifier_offset
= start_offset
;
962 offset
= dissect_ber_identifier(pinfo
, tree
, tvb
, start_offset
, &ber_class
, &pc
, &tag
);
963 identifier_len
= offset
- identifier_offset
;
964 offset
= dissect_ber_length(pinfo
, tree
, tvb
, offset
, &len
, NULL
);
965 proto_tree_add_expert_format(
966 tree
, pinfo
, &ei_ber_universal_tag_unknown
,
967 tvb
, identifier_offset
, identifier_len
,
968 "BER Error: can not handle universal tag:%d",
977 /* we dissect again if show_internal_ber_fields is set */
978 if (show_internal_ber_fields
) {
979 offset
= dissect_ber_identifier(pinfo
, tree
, tvb
, start_offset
, &ber_class
, &pc
, &tag
);
980 offset
= dissect_ber_length(pinfo
, tree
, tvb
, offset
, &len
, NULL
);
983 /* we can't dissect this directly as it is specific */
984 pi
= proto_tree_add_none_format(tree
, hf_ber_unknown_BER_primitive
, tvb
, offset
, len
,
985 "[%s %d] ", val_to_str_const(ber_class
, ber_class_codes
, "Unknown"), tag
);
987 is_decoded_as
= false;
988 if (decode_primitive_as_ber
&& (len
>= 2)) {
989 volatile int ber_offset
= 0;
990 uint32_t ber_len
= 0;
992 ber_offset
= get_ber_identifier(tvb
, offset
, NULL
, &pc
, NULL
);
993 ber_offset
= get_ber_length(tvb
, ber_offset
, &ber_len
, NULL
);
997 if (pc
&& (ber_len
> 0) && (ber_len
+ (ber_offset
- offset
) == len
)) {
998 /* Decoded a constructed ASN.1 tag with a length indicating this
999 * could be BER encoded data. Try dissecting as unknown BER.
1001 is_decoded_as
= true;
1002 proto_item_append_text(pi
, "[BER encoded]");
1003 next_tree
= proto_item_add_subtree(pi
, ett_ber_primitive
);
1004 offset
= try_dissect_unknown_ber(pinfo
, tvb
, offset
, next_tree
, nest_level
+ 1);
1008 if (!is_decoded_as
&& len
) {
1009 /* we may want to do better and show the bytes */
1010 is_printable
= true;
1011 for (i
= 0; i
< len
; i
++) {
1012 c
= tvb_get_uint8(tvb
, offset
+ i
);
1014 if (is_printable
&& !g_ascii_isprint(c
))
1015 is_printable
= false;
1017 proto_item_append_text(pi
, "%02x", c
);
1020 if (is_printable
) { /* give a nicer representation if it looks like a string */
1021 proto_item_append_text(pi
, " (");
1022 for (i
= 0; i
< len
; i
++) {
1023 proto_item_append_text(pi
, "%c", tvb_get_uint8(tvb
, offset
+ i
));
1025 proto_item_append_text(pi
, ")");
1033 /* this is constructed */
1035 /* we dissect again if show_internal_ber_fields is set */
1036 if (show_internal_ber_fields
) {
1037 offset
= dissect_ber_identifier(pinfo
, tree
, tvb
, start_offset
, &ber_class
, &pc
, &tag
);
1038 offset
= dissect_ber_length(pinfo
, tree
, tvb
, offset
, &len
, NULL
);
1041 hdr_len
= offset
-start_offset
;
1043 switch (ber_class
) {
1045 next_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_ber_SEQUENCE
, NULL
,
1046 val_to_str_ext_const(tag
, &ber_uni_tag_codes_ext
, "Unknown"));
1047 while (offset
< (int)(start_offset
+ len
+ hdr_len
))
1048 offset
= try_dissect_unknown_ber(pinfo
, tvb
, offset
, next_tree
, nest_level
+1);
1054 next_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, len
, ett_ber_SEQUENCE
, NULL
,
1055 "[%s %d]", val_to_str_const(ber_class
, ber_class_codes
, "Unknown"), tag
);
1056 while (offset
< (int)(start_offset
+ len
+ hdr_len
))
1057 offset
= try_dissect_unknown_ber(pinfo
, tvb
, offset
, next_tree
, nest_level
+1);
1067 // NOLINTNEXTLINE(misc-no-recursion)
1068 dissect_unknown_ber(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
)
1070 return try_dissect_unknown_ber(pinfo
, tvb
, offset
, tree
, 1);
1074 call_ber_oid_callback(const char *oid
, tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
1077 const char *syntax
= NULL
;
1084 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1086 ((((syntax
= get_ber_oid_syntax(oid
)) == NULL
) ||
1087 /* First see if a syntax has been registered for this oid (user defined) */
1088 (len
= dissector_try_string_with_data(ber_syntax_dissector_table
, syntax
, next_tvb
, pinfo
, tree
, true, data
)) == 0) &&
1089 /* Then try registered oid's */
1090 (len
= dissector_try_string_with_data(ber_oid_dissector_table
, oid
, next_tvb
, pinfo
, tree
, true, data
)) == 0))
1092 proto_item
*item
= NULL
;
1093 proto_tree
*next_tree
= NULL
;
1094 int length_remaining
;
1096 /* XXX we should probably use get_ber_length() here */
1097 length_remaining
= tvb_reported_length_remaining(tvb
, offset
);
1100 item
= proto_tree_add_expert(tree
, pinfo
, &ei_ber_no_oid
, next_tvb
, 0, length_remaining
);
1101 } else if (tvb_get_ntohs (tvb
, offset
) != 0x0500) { /* Not NULL tag */
1103 item
= proto_tree_add_expert_format(
1104 tree
, pinfo
, &ei_ber_syntax_not_implemented
, next_tvb
, 0, length_remaining
,
1105 "BER: Dissector for syntax:%s not implemented."
1106 " Contact Wireshark developers if you want this supported",
1109 item
= proto_tree_add_expert(tree
, pinfo
, &ei_ber_oid_not_implemented
, next_tvb
, 0, length_remaining
);
1114 if (decode_unexpected
) {
1119 next_tree
= proto_item_add_subtree(item
, ett_ber_unknown
);
1121 ber_offset
= get_ber_identifier(next_tvb
, 0, NULL
, NULL
, NULL
);
1122 ber_offset
= get_ber_length(next_tvb
, ber_offset
, &ber_len
, NULL
);
1123 if ((ber_len
+ ber_offset
) == length_remaining
) {
1124 /* Decoded an ASN.1 tag with a length indicating this
1125 * could be BER encoded data. Try dissecting as unknown BER.
1127 dissect_unknown_ber(pinfo
, next_tvb
, 0, next_tree
);
1129 proto_tree_add_item(next_tree
, hf_ber_unknown_data
, next_tvb
, 0, length_remaining
, ENC_NA
);
1132 len
= length_remaining
;
1141 call_ber_syntax_callback(const char *syntax
, tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
)
1146 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1147 if (syntax
== NULL
||
1148 (len
= dissector_try_string_with_data(ber_syntax_dissector_table
, syntax
, next_tvb
, pinfo
, tree
, true, NULL
)) == 0)
1150 proto_item
*item
= NULL
;
1152 if (syntax
== NULL
) {
1153 item
= proto_tree_add_expert_format(
1154 tree
, pinfo
, &ei_ber_no_oid
, next_tvb
, 0, tvb_reported_length_remaining(tvb
, offset
),
1155 "BER Error: No syntax supplied to call_ber_syntax_callback");
1157 item
= proto_tree_add_expert_format(
1158 tree
, pinfo
, &ei_ber_syntax_not_implemented
, next_tvb
, 0, tvb_reported_length_remaining(tvb
, offset
),
1159 "BER: Dissector for syntax:%s not implemented."
1160 " Contact Wireshark developers if you want this supported",
1163 if (decode_unexpected
) {
1164 proto_tree
*unknown_tree
= proto_item_add_subtree(item
, ett_ber_unknown
);
1165 dissect_unknown_ber(pinfo
, next_tvb
, 0, unknown_tree
);
1167 len
= tvb_reported_length_remaining(tvb
, offset
);
1176 /* 8.1 General rules for encoding */
1178 /* 8.1.2 Identifier octets */
1180 get_ber_identifier(tvbuff_t
*tvb
, int offset
, int8_t *ber_class
, bool *pc
, int32_t *tag
) {
1186 id
= tvb_get_uint8(tvb
, offset
);
1189 ws_debug_printf("BER ID=%02x", id
);
1192 tmp_class
= (id
>> 6) & 0x03;
1193 tmp_pc
= (id
>> 5) & 0x01;
1194 tmp_tag
= id
& 0x1F;
1196 if (tmp_tag
== 0x1F) {
1198 while (tvb_reported_length_remaining(tvb
, offset
) > 0) {
1199 t
= tvb_get_uint8(tvb
, offset
);
1201 ws_debug_printf(" %02x", t
);
1205 tmp_tag
|= t
& 0x7F;
1212 ws_debug_printf("\n");
1215 *ber_class
= tmp_class
;
1221 last_class
= tmp_class
;
1229 get_last_ber_identifier(int8_t *ber_class
, bool *pc
, int32_t *tag
)
1232 *ber_class
= last_class
;
1241 dissect_ber_identifier(packet_info
*pinfo _U_
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int8_t *ber_class
, bool *pc
, int32_t *tag
)
1243 int old_offset
= offset
;
1248 offset
= get_ber_identifier(tvb
, offset
, &tmp_class
, &tmp_pc
, &tmp_tag
);
1250 if (show_internal_ber_fields
) {
1251 proto_tree_add_uint(tree
, hf_ber_id_class
, tvb
, old_offset
, 1, tmp_class
<< 6);
1252 proto_tree_add_boolean(tree
, hf_ber_id_pc
, tvb
, old_offset
, 1, (tmp_pc
) ? 0x20 : 0x00);
1253 if (tmp_tag
> 0x1F) {
1254 if (tmp_class
== BER_CLASS_UNI
) {
1255 proto_tree_add_uint(tree
, hf_ber_id_uni_tag_ext
, tvb
, old_offset
+ 1, offset
- (old_offset
+ 1), tmp_tag
);
1257 proto_tree_add_uint(tree
, hf_ber_id_tag_ext
, tvb
, old_offset
+ 1, offset
- (old_offset
+ 1), tmp_tag
);
1260 if (tmp_class
== BER_CLASS_UNI
) {
1261 proto_tree_add_uint(tree
, hf_ber_id_uni_tag
, tvb
, old_offset
, 1, tmp_tag
);
1263 proto_tree_add_uint(tree
, hf_ber_id_tag
, tvb
, old_offset
, 1, tmp_tag
);
1269 *ber_class
= tmp_class
;
1278 /** Try to get the length octets of the BER TLV.
1279 * Only (TAGs and) LENGTHs that fit inside 32 bit integers are supported.
1281 * @return true if we have the entire length, false if we're in the middle of
1282 * an indefinite length and haven't reached EOC.
1284 /* 8.1.3 Length octets */
1287 // NOLINTNEXTLINE(misc-no-recursion)
1288 try_get_ber_length(tvbuff_t
*tvb
, int offset
, uint32_t *length
, bool *ind
, int nest_level
) {
1291 uint32_t tmp_length
;
1293 int tmp_offset
, s_offset
;
1301 if (nest_level
> BER_MAX_NESTING
) {
1302 /* Assume that we have a malformed packet. */
1303 THROW(ReportedBoundsError
);
1306 oct
= tvb_get_uint8(tvb
, offset
);
1309 if (!(oct
& 0x80)) {
1317 oct
= tvb_get_uint8(tvb
, offset
);
1319 tmp_length
= (tmp_length
<<8) + oct
;
1324 tmp_offset
= offset
;
1325 /* ok in here we can traverse the BER to find the length, this will fix most indefinite length issues */
1326 /* Assumption here is that indefinite length is always used on constructed types*/
1328 while (tvb_get_uint8(tvb
, offset
) || tvb_get_uint8(tvb
, offset
+1)) {
1329 /* not an EOC at offset */
1331 offset
= get_ber_identifier(tvb
, offset
, &tclass
, &tpc
, &ttag
);
1332 offset
= try_get_ber_length(tvb
, offset
, &indef_len
, NULL
, nest_level
+1);
1333 tmp_length
+= indef_len
+(offset
-s_offset
); /* length + tag and length */
1334 offset
+= indef_len
;
1335 /* Make sure we've moved forward in the packet */
1336 if (offset
<= s_offset
)
1337 THROW(ReportedBoundsError
);
1341 offset
= tmp_offset
;
1345 /* Several users treat the length as signed value, clamp the value to avoid
1346 * an overflow to negative values. */
1347 if (tmp_length
> (uint32_t)INT32_MAX
)
1348 tmp_length
= (uint32_t)INT32_MAX
;
1351 *length
= tmp_length
;
1356 ws_debug_printf("get BER length %d, offset %d (remaining %d)\n", tmp_length
, offset
, tvb_reported_length_remaining(tvb
, offset
));
1363 get_ber_length(tvbuff_t
*tvb
, int offset
, uint32_t *length
, bool *ind
)
1365 return try_get_ber_length(tvb
, offset
, length
, ind
, 1);
1369 get_last_ber_length(uint32_t *length
, bool *ind
, tvbuff_t
**len_tvb
, int *len_offset
, int *len_len
)
1372 *length
= last_length
;
1376 *len_tvb
= last_length_tvb
;
1378 *len_offset
= last_length_offset
;
1380 *len_len
= last_length_len
;
1383 /* this function dissects the length octets of the BER TLV.
1384 * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
1387 dissect_ber_length(packet_info
*pinfo _U_
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, uint32_t *length
, bool *ind
)
1389 int old_offset
= offset
;
1390 uint32_t tmp_length
;
1393 offset
= get_ber_length(tvb
, offset
, &tmp_length
, &tmp_ind
);
1395 if (show_internal_ber_fields
) {
1397 proto_tree_add_uint_format_value(tree
, hf_ber_length
, tvb
, old_offset
, 1, tmp_length
, "Indefinite length %d", tmp_length
);
1399 if ((offset
- old_offset
) > 1) {
1400 proto_tree_add_uint(tree
, hf_ber_length_octets
, tvb
, old_offset
, 1, (tvb_get_uint8(tvb
, old_offset
) & 0x7f));
1401 proto_tree_add_uint(tree
, hf_ber_length
, tvb
, old_offset
+1, offset
- (old_offset
+1), tmp_length
);
1403 proto_tree_add_uint(tree
, hf_ber_length
, tvb
, old_offset
, offset
- old_offset
, tmp_length
);
1408 *length
= tmp_length
;
1413 proto_tree_add_debug_text(tree
, "dissect BER length %d, offset %d (remaining %d)\n", tmp_length
, offset
, tvb_reported_length_remaining(tvb
, offset
));
1416 last_length
= tmp_length
;
1418 last_length_tvb
= tvb
;
1419 last_length_offset
= old_offset
;
1420 last_length_len
= offset
- old_offset
;
1425 static reassembly_table octet_segment_reassembly_table
;
1428 dissect_ber_constrained_octet_string_impl(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int32_t min_len
, int32_t max_len
, int hf_id
, tvbuff_t
**out_tvb
, unsigned nest_level
, unsigned encoding
);
1431 // NOLINTNEXTLINE(misc-no-recursion)
1432 reassemble_octet_string(asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_id
, tvbuff_t
*tvb
, int offset
, uint32_t con_len
, bool ind
, tvbuff_t
**out_tvb
, unsigned nest_level
)
1434 fragment_head
*fd_head
= NULL
;
1435 tvbuff_t
*next_tvb
= NULL
;
1436 tvbuff_t
*reassembled_tvb
= NULL
;
1437 uint16_t dst_ref
= 0;
1438 int start_offset
= offset
;
1439 bool fragment
= true;
1440 bool firstFragment
= true;
1442 if (nest_level
> BER_MAX_NESTING
) {
1443 /* Assume that we have a malformed packet. */
1444 THROW(ReportedBoundsError
);
1447 /* so we need to consume octet strings for the given length */
1452 if (con_len
== 0) /* Zero encodings (8.7.3) */
1455 /* not sure we need this */
1456 actx
->pinfo
->fragmented
= true;
1460 offset
= dissect_ber_constrained_octet_string_impl(false, actx
, NULL
,
1461 tvb
, offset
, NO_BOUND
, NO_BOUND
, hf_id
, &next_tvb
, nest_level
+ 1, 0);
1463 if (next_tvb
== NULL
) {
1464 /* Assume that we have a malformed packet. */
1465 THROW(ReportedBoundsError
);
1469 /* this was indefinite length - so check for EOC */
1471 if ((tvb_get_uint8(tvb
, offset
) == 0) && (tvb_get_uint8(tvb
, offset
+1) == 0)) {
1478 if ((uint32_t)(offset
- start_offset
) >= con_len
)
1482 if (!fragment
&& firstFragment
) {
1483 /* there is only one fragment (I'm sure there's a reason it was constructed) */
1484 /* anyway, we can get out of here */
1486 get_ber_identifier(tvb
, start_offset
, NULL
, &pc
, NULL
);
1488 /* Only display here if not constructed */
1489 dissect_ber_octet_string(false, actx
, tree
, tvb
, start_offset
, hf_id
, NULL
);
1491 reassembled_tvb
= next_tvb
;
1496 if (tvb_reported_length(next_tvb
) < 1) {
1497 /* Don't cause an assertion in the reassembly code. */
1498 THROW(ReportedBoundsError
);
1500 fd_head
= fragment_add_seq_next(&octet_segment_reassembly_table
,
1501 next_tvb
, 0, actx
->pinfo
,
1502 (dst_ref
| nest_level
<< 16), NULL
,
1503 tvb_reported_length(next_tvb
),
1506 firstFragment
= false;
1510 if (fd_head
->next
) {
1511 /* not sure I really want to do this here - should be nearer the application where we can give it a better name*/
1512 proto_tree
*next_tree
;
1513 proto_item
*frag_tree_item
;
1515 reassembled_tvb
= tvb_new_chain(next_tvb
, fd_head
->tvb_data
);
1517 actx
->created_item
= proto_tree_add_item(tree
, hf_id
, reassembled_tvb
, 0, -1, ENC_BIG_ENDIAN
);
1518 next_tree
= proto_item_add_subtree (actx
->created_item
, ett_ber_reassembled_octet_string
);
1520 add_new_data_source(actx
->pinfo
, reassembled_tvb
, "Reassembled OCTET STRING");
1521 show_fragment_seq_tree(fd_head
, &octet_string_frag_items
, next_tree
, actx
->pinfo
, reassembled_tvb
, &frag_tree_item
);
1526 *out_tvb
= reassembled_tvb
;
1528 /* again - not sure we need this */
1529 actx
->pinfo
->fragmented
= false;
1535 /* 8.7 Encoding of an octetstring value */
1537 // NOLINTNEXTLINE(misc-no-recursion)
1538 dissect_ber_constrained_octet_string(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int32_t min_len
, int32_t max_len
, int hf_id
, tvbuff_t
**out_tvb
) {
1539 return dissect_ber_constrained_octet_string_impl(implicit_tag
, actx
, tree
, tvb
, offset
, min_len
, max_len
, hf_id
, out_tvb
, 0, 0);
1543 // NOLINTNEXTLINE(misc-no-recursion)
1544 dissect_ber_constrained_octet_string_impl(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int32_t min_len
, int32_t max_len
, int hf_id
, tvbuff_t
**out_tvb
, unsigned nest_level
, unsigned encoding
) {
1548 int identifier_offset
;
1556 proto_item
*it
, *cause
;
1557 uint32_t len_remain
;
1562 header_field_info
*hfinfo
;
1564 hfinfo
= proto_registrar_get_nth(hf_id
);
1565 name
= hfinfo
->name
;
1569 if (tvb_reported_length_remaining(tvb
, offset
) > 3) {
1570 proto_tree_add_debug_text(tree
, "OCTET STRING dissect_ber_octet string(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name
, implicit_tag
, offset
, tvb_reported_length_remaining(tvb
, offset
), tvb_get_uint8(tvb
, offset
), tvb_get_uint8(tvb
, offset
+1), tvb_get_uint8(tvb
, offset
+2));
1572 proto_tree_add_debug_text(tree
, "OCTET STRING dissect_ber_octet_string(%s) entered\n", name
);
1580 if (!implicit_tag
) {
1582 /* read header and len for the octet string */
1583 identifier_offset
= offset
;
1584 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
1585 identifier_len
= offset
- identifier_offset
;
1586 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, &ind
);
1587 end_offset
= offset
+len
;
1589 /* sanity check: we only handle Constructed Universal Sequences */
1590 if ((ber_class
!= BER_CLASS_APP
) && (ber_class
!= BER_CLASS_PRI
)) {
1591 if ( (ber_class
!= BER_CLASS_UNI
)
1592 || ((tag
< BER_UNI_TAG_NumericString
) && (tag
!= BER_UNI_TAG_OCTETSTRING
) && (tag
!= BER_UNI_TAG_UTF8String
)) ) {
1593 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
1594 cause
= proto_tree_add_expert_format(
1595 tree
, actx
->pinfo
, &ei_ber_expected_octet_string
,
1596 tvb
, identifier_offset
, identifier_len
,
1597 "BER Error: OctetString expected but class:%s(%d) %s tag:%d was unexpected",
1598 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
1600 tfs_get_string(pc
, &tfs_constructed_primitive
),
1602 if (decode_unexpected
) {
1603 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
1604 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
1610 /* implicit tag so get from last tag/length */
1612 get_last_ber_identifier(&ber_class
, &pc
, &tag
);
1613 get_last_ber_length(&len
, &ind
, &len_tvb
, &len_offset
, &len_len
);
1615 end_offset
= offset
+len
;
1617 /* caller may have created new buffer for indefinite length data Verify via length */
1618 len_remain
= (uint32_t)tvb_reported_length_remaining(tvb
, offset
);
1619 if (ind
&& (len_remain
== (len
- 2))) {
1620 /* new buffer received so adjust length and indefinite flag */
1624 } else if (len_remain
< len
) {
1626 * error - short frame, or this item runs past the
1627 * end of the item containing it
1629 ber_add_large_length_error(actx
->pinfo
, tree
, tvb
, offset
, len
, len_tvb
, len_offset
, len_len
);
1635 actx
->created_item
= NULL
;
1639 end_offset
= reassemble_octet_string(actx
, tree
, hf_id
, tvb
, offset
, len
, ind
, out_tvb
, nest_level
);
1642 int length_remaining
;
1644 length_remaining
= tvb_reported_length_remaining(tvb
, offset
);
1646 if (length_remaining
< 1) {
1651 if (len
<= (uint32_t)length_remaining
) {
1652 length_remaining
= len
;
1656 * Strings are special. See X.680 section 41 "Definition of
1657 * restricted character string types" and X.690 section 8.20
1658 * "Encoding for values of the restricted character string
1661 * Some restricted character string types are defined in X.680
1662 * "by reference to a registration number in the ISO International
1663 * Register of Character Sets" - or, in Table 8, by multiple
1664 * registration numbers, or one or more registration numbers
1665 * plus some characters such as SPACE and/or DELETE, or a
1666 * reference to "all G sets" or "all G sets and all C sets".
1667 * Presumably this indicates which characters are allowed
1668 * in strings of those character types, with "all {G,C} sets"
1669 * meaning the only restriction is to character sets registered
1672 * The encodings of those types are specified in X.690 as
1673 * containing "the octets specified in ISO/IEC 2022 for
1674 * encodings in an 8-bit environment, using the escape sequence
1675 * and character codings registered in accordance with ISO/IEC
1678 * ISO/IEC 2022 is also ECMA-35:
1680 * http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-035.pdf
1682 * ISO/IEC 2375 is the procedure for registering character
1683 * codings in the ISO International Register of Character Sets.
1686 * http://kikaku.itscj.ipsj.or.jp/ISO-IR/
1690 * http://kikaku.itscj.ipsj.or.jp/ISO-IR/overview.htm
1692 * for that registry.
1694 * If we've been provided with a non-zero encoding, use
1695 * that; otherwise, calculate it based on the tag. (A
1696 * zero encoding is ENC_ASCII|ENC_NA/ENC_BIG_ENDIAN, which
1697 * is the default, so it's OK to use here; this is for
1698 * protcols such as LDAP that use OCTET STRING for UTF-8
1701 if (encoding
== 0) {
1704 case BER_UNI_TAG_UTF8String
:
1708 encoding
= ENC_UTF_8
|ENC_NA
;
1711 case BER_UNI_TAG_NumericString
:
1712 case BER_UNI_TAG_PrintableString
:
1713 case BER_UNI_TAG_VisibleString
:
1714 case BER_UNI_TAG_IA5String
:
1716 * (Subsets of) Boring Old ASCII, with no(?) ISO 2022
1719 encoding
= ENC_ASCII
|ENC_NA
;
1722 case BER_UNI_TAG_TeletexString
:
1723 encoding
= ENC_T61
|ENC_NA
;
1726 case BER_UNI_TAG_VideotexString
:
1727 encoding
= ENC_T61
|ENC_NA
;
1730 case BER_UNI_TAG_GraphicString
:
1731 case BER_UNI_TAG_GeneralString
:
1733 * One of the types defined in terms of character sets
1734 * in the ISO International Register of Character Sets,
1735 * with the BER encoding being ISO 2022-based.
1737 * XXX - treat as ASCII for now.
1739 encoding
= ENC_ASCII
|ENC_NA
;
1742 case BER_UNI_TAG_UniversalString
:
1746 encoding
= ENC_UCS_4
|ENC_BIG_ENDIAN
;
1749 case BER_UNI_TAG_CHARACTERSTRING
:
1751 * XXX - what's the transfer syntax?
1752 * Treat as ASCII for now.
1754 encoding
= ENC_ASCII
|ENC_NA
;
1757 case BER_UNI_TAG_BMPString
:
1759 * UCS-2, not UTF-16; as it says, BMP, as in Basic
1760 * Multilingual Plane.
1762 encoding
= ENC_UCS_2
|ENC_BIG_ENDIAN
;
1766 encoding
= ENC_BIG_ENDIAN
;
1770 it
= ber_proto_tree_add_item(actx
->pinfo
, tree
, hf_id
, tvb
, offset
, length_remaining
, encoding
);
1771 actx
->created_item
= it
;
1772 ber_check_length(length_remaining
, min_len
, max_len
, actx
, it
, false);
1775 proto_tree_add_item(tree
, hf_ber_unknown_octetstring
, tvb
, offset
, len
, ENC_NA
);
1779 *out_tvb
= ber_tvb_new_subset_length(tvb
, offset
, len
);
1786 // NOLINTNEXTLINE(misc-no-recursion)
1787 dissect_ber_octet_string(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, tvbuff_t
**out_tvb
) {
1788 return dissect_ber_constrained_octet_string_impl(implicit_tag
, actx
, tree
, tvb
, offset
, NO_BOUND
, NO_BOUND
, hf_id
, out_tvb
, 0, 0);
1792 dissect_ber_octet_string_with_encoding(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, tvbuff_t
**out_tvb
, unsigned encoding
) {
1793 return dissect_ber_constrained_octet_string_impl(implicit_tag
, actx
, tree
, tvb
, offset
, NO_BOUND
, NO_BOUND
, hf_id
, out_tvb
, 0, encoding
);
1797 dissect_ber_octet_string_wcb(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, ber_callback func
)
1799 tvbuff_t
*out_tvb
= NULL
;
1801 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, (func
) ? &out_tvb
: NULL
);
1802 if (func
&& out_tvb
&& (tvb_reported_length(out_tvb
) > 0)) {
1804 tree
= proto_item_add_subtree(actx
->created_item
, ett_ber_octet_string
);
1805 /* TODO Should hf_id2 be passed as last parameter???*/
1806 func(false, out_tvb
, 0, actx
, tree
, -1);
1811 /* 8.8 Encoding of a null value */
1813 dissect_ber_null(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
) {
1817 int identifier_offset
;
1823 if (!implicit_tag
) {
1824 identifier_offset
= offset
;
1825 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
1826 identifier_len
= offset
- identifier_offset
;
1828 ((ber_class
!= BER_CLASS_UNI
) || (tag
!= BER_UNI_TAG_NULL
))) {
1829 proto_tree_add_expert_format(
1830 tree
, actx
->pinfo
, &ei_ber_expected_null
,
1831 tvb
, identifier_offset
, identifier_len
,
1832 "BER Error: NULL expected but class:%s(%d) %s tag:%d was unexpected",
1833 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
1835 tfs_get_string(pc
, &tfs_constructed_primitive
),
1839 len_offset
= offset
;
1840 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
1841 len_len
= offset
- len_offset
;
1843 proto_tree_add_expert_format(
1844 tree
, actx
->pinfo
, &ei_ber_expected_null_zero_length
,
1845 tvb
, len_offset
, len_len
,
1846 "BER Error: NULL type expects zero length data but Length=%d",
1848 proto_tree_add_item(tree
, hf_ber_extra_data
, tvb
, offset
, len
, ENC_NA
);
1853 proto_tree_add_item(tree
, hf_id
, tvb
, offset
, 0, ENC_BIG_ENDIAN
);
1858 dissect_ber_integer64(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, int64_t *value
)
1866 bool used_too_many_bytes
= false;
1871 header_field_info
*hfinfo
;
1873 hfinfo
= proto_registrar_get_nth(hf_id
);
1874 name
= hfinfo
->name
;
1878 if (tvb_reported_length_remaining(tvb
, offset
) > 3) {
1879 proto_tree_add_debug_text(tree
, "INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name
, implicit_tag
, offset
, tvb_reported_length_remaining(tvb
, offset
), tvb_get_uint8(tvb
, offset
), tvb_get_uint8(tvb
, offset
+1), tvb_get_uint8(tvb
, offset
+2));
1881 proto_tree_add_debug_text(tree
, "INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d \n", name
, implicit_tag
);
1891 if (!implicit_tag
) {
1892 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
1893 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
1895 int32_t remaining
= tvb_reported_length_remaining(tvb
, offset
);
1896 len
= remaining
>0 ? remaining
: 0;
1902 first
= tvb_get_uint8(tvb
, offset
);
1903 /* we can't handle integers > 64 bits */
1904 /* take into account the use case of a 64bits unsigned integer: you will have a 9th byte set to 0 */
1905 if ((len
> 9) || ((len
== 9) && (first
!= 0))) {
1907 header_field_info
*hfinfo
= proto_registrar_get_nth(hf_id
);
1909 /* use the original field only if it is suitable for bytes */
1910 if (hfinfo
->type
!= FT_BYTES
)
1911 hf_id
= hf_ber_64bit_uint_as_bytes
;
1913 proto_tree_add_bytes_format(tree
, hf_id
, tvb
, offset
, len
, NULL
,
1914 "%s: 0x%s", hfinfo
->name
, tvb_bytes_to_str(actx
->pinfo
->pool
, tvb
, offset
, len
));
1920 /* extend sign bit for signed fields */
1921 enum ftenum type
= FT_INT32
; /* Default to signed, is this correct? */
1923 type
= proto_registrar_get_ftype(hf_id
);
1925 if (first
& 0x80 && FT_IS_INT(type
)) {
1928 if ((len
> 1) && decode_warning_leading_zero_bits
) {
1929 uint8_t second
= tvb_get_uint8(tvb
, offset
+1);
1930 if (((first
== 0x00) && ((second
& 0x80) == 0)) ||
1931 ((first
== 0xff) && ((second
& 0x80) != 0))) {
1932 used_too_many_bytes
= true;
1935 for (i
=0; i
<len
; i
++) {
1936 val
= ((uint64_t)val
<<8) | tvb_get_uint8(tvb
, offset
);
1941 actx
->created_item
= NULL
;
1945 header_field_info
* hfi
;
1947 hfi
= proto_registrar_get_nth(hf_id
);
1948 if ((len
< 1) || (len
> 9) || ((len
== 9) && (first
!= 0))) {
1949 proto_tree_add_expert_format(
1950 tree
, actx
->pinfo
, &ei_ber_error_length
, tvb
, offset
-len
, len
,
1951 "BER Error: %s: length of item (%u) is not valid", hfi
->name
, len
);
1953 switch (hfi
->type
) {
1958 actx
->created_item
= proto_tree_add_uint(tree
, hf_id
, tvb
, offset
-len
, len
, (uint32_t)val
);
1964 actx
->created_item
= proto_tree_add_int(tree
, hf_id
, tvb
, offset
-len
, len
, (int32_t)val
);
1967 actx
->created_item
= proto_tree_add_int64(tree
, hf_id
, tvb
, offset
-len
, len
, val
);
1970 actx
->created_item
= proto_tree_add_uint64(tree
, hf_id
, tvb
, offset
-len
, len
, (uint64_t)val
);
1974 * Some protocols have INTEGER fields that can store values
1975 * larger than 64 bits and therefore have to use FT_BYTES.
1976 * Values larger than 64 bits are handled above while smaller
1977 * values are handled here.
1979 actx
->created_item
= proto_tree_add_bytes_format(tree
, hf_id
, tvb
, offset
-len
, len
, NULL
,
1980 "%s: 0x%s", hfi
->name
, tvb_bytes_to_str(actx
->pinfo
->pool
, tvb
, offset
-len
, len
));
1983 DISSECTOR_ASSERT_NOT_REACHED();
1986 if (used_too_many_bytes
) {
1987 expert_add_info_format(
1988 actx
->pinfo
, actx
->created_item
, &ei_ber_value_too_many_bytes
,
1989 "Value is encoded with too many bytes(9 leading zero or one bits), hf_abbr: %s",
2003 dissect_ber_constrained_integer64(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int64_t min_len
, int64_t max_len
, int hf_id
, int64_t *value
)
2007 offset
= dissect_ber_integer64(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, &val
);
2012 ber_check_value64 (val
, min_len
, max_len
, actx
, actx
->created_item
);
2018 dissect_ber_integer(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, uint32_t *value
)
2022 offset
= dissect_ber_integer64(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, &val
);
2024 *value
= (uint32_t)val
;
2031 dissect_ber_constrained_integer(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int32_t min_len
, int32_t max_len
, int hf_id
, uint32_t *value
)
2035 offset
= dissect_ber_integer64(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, &val
);
2037 *value
= (uint32_t)val
;
2040 ber_check_value ((uint32_t)val
, min_len
, max_len
, actx
, actx
->created_item
);
2046 dissect_ber_boolean(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, bool *value
)
2053 header_field_info
*hfi
;
2055 if (!implicit_tag
) {
2056 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
2057 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
2058 /*if (ber_class != BER_CLASS_UNI)*/
2060 int32_t remaining
= tvb_reported_length_remaining(tvb
, offset
);
2061 len
= remaining
> 0 ? remaining
: 0;
2066 val
= tvb_get_uint8(tvb
, offset
);
2069 actx
->created_item
= NULL
;
2072 hfi
= proto_registrar_get_nth(hf_id
);
2073 if (hfi
->type
== FT_BOOLEAN
)
2074 actx
->created_item
= proto_tree_add_boolean(tree
, hf_id
, tvb
, offset
-1, 1, val
);
2076 actx
->created_item
= proto_tree_add_uint(tree
, hf_id
, tvb
, offset
-1, 1, val
? 1 : 0);
2080 actx
->created_item
= NULL
;
2083 hfi
= proto_registrar_get_nth(hf_id
);
2084 proto_tree_add_expert_format(
2085 tree
, actx
->pinfo
, &ei_ber_error_length
, tvb
, offset
, len
,
2086 "BER Error: %s: length of item (%u) is not valid", hfi
->name
, len
);
2091 *value
= (val
? true : false);
2098 /* 8.5 Encoding of a real value */
2099 /* Somewhat tested */
2101 dissect_ber_real(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, double *value
)
2106 uint32_t val_length
= 0, len_remain
, end_offset
;
2112 if (!implicit_tag
) {
2113 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
2114 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &val_length
, NULL
);
2116 end_offset
= offset
+ val_length
;
2118 /* implicit tag so get from last tag/length */
2119 get_last_ber_identifier(&ber_class
, &pc
, &tag
);
2120 get_last_ber_length(&val_length
, NULL
, &len_tvb
, &len_offset
, &len_len
);
2122 end_offset
= offset
+ val_length
;
2124 /* Check is buffer has (at least) the expected length */
2125 len_remain
= (uint32_t)tvb_reported_length_remaining(tvb
, offset
);
2126 if (len_remain
< val_length
) {
2127 /* error - this item runs past the end of the item containing it */
2128 ber_add_large_length_error(actx
->pinfo
, tree
, tvb
, offset
, val_length
, len_tvb
, len_offset
, len_len
);
2132 /* 8.5.1 The encoding of a real value shall be primitive. */
2134 /* Constructed (not primitive) */
2135 proto_tree_add_expert(
2136 tree
, actx
->pinfo
, &ei_ber_real_not_primitive
, tvb
, offset
- 2, 1);
2139 val
= asn1_get_real(tvb_get_ptr(tvb
, offset
, val_length
), val_length
);
2140 actx
->created_item
= proto_tree_add_double(tree
, hf_id
, tvb
, end_offset
- val_length
, val_length
, val
);
2148 /* this function dissects a BER sequence
2151 dissect_ber_sequence(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, const ber_sequence_t
*seq
, int hf_id
, int ett_id
) {
2153 bool pcx
, ind
= 0, ind_field
, imp_tag
= false;
2155 int identifier_offset
;
2158 proto_tree
*tree
= parent_tree
;
2159 proto_item
*item
= NULL
;
2168 header_field_info
*hfinfo
;
2170 hfinfo
= proto_registrar_get_nth(hf_id
);
2171 name
= hfinfo
->name
;
2175 if (tvb_reported_length_remaining(tvb
, offset
) > 3) {
2176 proto_tree_add_debug_text(tree
, "SEQUENCE dissect_ber_sequence(%s) entered offset:%d len:%d %02x:%02x:%02x\n", name
, offset
, tvb_reported_length_remaining(tvb
, offset
), tvb_get_uint8(tvb
, offset
), tvb_get_uint8(tvb
, offset
+1), tvb_get_uint8(tvb
, offset
+2));
2178 proto_tree_add_debug_text(tree
, "SEQUENCE dissect_ber_sequence(%s) entered\n", name
);
2183 if (!implicit_tag
) {
2184 offset
= get_ber_identifier(tvb
, offset
, NULL
, NULL
, NULL
);
2185 offset
= get_ber_length(tvb
, offset
, &lenx
, NULL
);
2187 /* was implicit tag so just use the length of the tvb */
2188 lenx
= tvb_reported_length_remaining(tvb
, offset
);
2189 end_offset
= offset
+lenx
;
2191 /* create subtree */
2194 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, hoffset
, lenx
+ offset
- hoffset
, ENC_BIG_ENDIAN
);
2195 tree
= proto_item_add_subtree(item
, ett_id
);
2200 if (!implicit_tag
) {
2201 /* first we must read the sequence header */
2202 identifier_offset
= offset
;
2203 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &classx
, &pcx
, &tagx
);
2204 identifier_len
= offset
- identifier_offset
;
2205 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &lenx
, &ind
);
2207 /* Fixed the length is correctly returned from dissect ber_length
2208 end_offset = tvb_reported_length(tvb);*/
2209 end_offset
= offset
+ lenx
-2;
2211 end_offset
= offset
+ lenx
;
2214 /* sanity check: we only handle Constructed Universal Sequences */
2215 if ((classx
!= BER_CLASS_APP
) && (classx
!= BER_CLASS_PRI
)) {
2217 || ((classx
!= BER_CLASS_UNI
) || (tagx
!= BER_UNI_TAG_SEQUENCE
))) {
2218 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
2219 cause
= proto_tree_add_expert_format(
2220 tree
, actx
->pinfo
, &ei_ber_expected_sequence
,
2221 tvb
, identifier_offset
, identifier_len
,
2222 "BER Error: Sequence expected but class:%s(%d) %s tag:%d was unexpected",
2223 val_to_str_const(classx
, ber_class_codes
, "Unknown"),
2225 tfs_get_string(pcx
, &tfs_constructed_primitive
),
2227 if (decode_unexpected
) {
2228 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2229 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2235 if(offset
== end_offset
){
2236 proto_item_append_text(item
, " [0 length]");
2238 /* loop over all entries until we reach the end of the sequence */
2239 while (offset
< end_offset
) {
2246 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2247 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2248 if ((tvb_get_uint8(tvb
, offset
) == 0) && (tvb_get_uint8(tvb
, offset
+1) == 0)) {
2249 /* If the first bytes is 00 00 of a indefinite length field it's a zero length field*/
2250 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
2251 dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, &ind
);
2252 proto_item_append_text(item
, " 0 items");
2255 if (show_internal_ber_fields) {
2256 proto_tree_add_expert(tree, pinfo, &ei_ber_error_seq_eoc, tvb, s_offset, offset+2, "ERROR WRONG SEQ EOC");
2263 /* read header and len for next field */
2264 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
2265 offset
= get_ber_length(tvb
, offset
, &len
, &ind_field
);
2266 eoffset
= offset
+ len
;
2267 /* Make sure we move forward */
2268 if (eoffset
<= hoffset
)
2269 THROW(ReportedBoundsError
);
2271 /*if (ind_field && (len == 2)) {
2272 / disgusting indefinite length zero length field, what are these people doing /
2278 ber_sequence_try_again
:
2279 /* have we run out of known entries in the sequence ?*/
2281 /* it was not, move to the next one and try again */
2282 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2283 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
2284 cause
= proto_tree_add_expert_format(
2285 tree
, actx
->pinfo
, &ei_ber_unknown_field_sequence
,
2286 tvb
, hoffset
, ((offset
- hoffset
) + len
),
2287 "BER Error: This field lies beyond the end of the known sequence definition.");
2288 if (decode_unexpected
) {
2289 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2290 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2296 /* Verify that this one is the one we want.
2297 * Skip check completely if ber_class == ANY
2298 * of if NOCHKTAG is set
2300 /* XXX Bug in asn2wrs,
2301 * for scope [7] Scope OPTIONAL,
2303 * { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_scope },
2304 * and there should not be a NOTCHKTAG here
2306 if ( ((seq
->ber_class
== BER_CLASS_CON
) || (seq
->ber_class
== BER_CLASS_APP
) || (seq
->ber_class
== BER_CLASS_PRI
))
2307 && (!(seq
->flags
& BER_FLAGS_NOOWNTAG
)) ) {
2308 if ( (seq
->ber_class
!= BER_CLASS_ANY
)
2310 && ( (seq
->ber_class
!= ber_class
)
2311 || (seq
->tag
!= tag
) ) ) {
2312 /* it was not, move to the next one and try again */
2313 if (seq
->flags
& BER_FLAGS_OPTIONAL
) {
2314 /* well this one was optional so just skip to the next one and try again. */
2316 goto ber_sequence_try_again
;
2318 identifier_offset
= hoffset
;
2319 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2320 identifier_len
= offset
- identifier_offset
;
2321 dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, NULL
, NULL
);
2322 if (seq
->ber_class
== BER_CLASS_UNI
) {
2323 cause
= proto_tree_add_expert_format(
2324 tree
, actx
->pinfo
, &ei_ber_sequence_field_wrong
,
2325 tvb
, identifier_offset
, identifier_len
,
2326 "BER Error: Wrong field in SEQUENCE: expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
2327 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2330 val_to_str_ext_const(seq
->tag
, &ber_uni_tag_codes_ext
, "Unknown"),
2331 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2335 cause
= proto_tree_add_expert_format(
2336 tree
, actx
->pinfo
, &ei_ber_sequence_field_wrong
,
2337 tvb
, identifier_offset
, identifier_len
,
2338 "BER Error: Wrong field in SEQUENCE: expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2339 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2342 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2346 if (decode_unexpected
) {
2347 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2348 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2354 } else if (!(seq
->flags
& BER_FLAGS_NOTCHKTAG
)) {
2355 if ( (seq
->ber_class
!= BER_CLASS_ANY
)
2357 && ( (seq
->ber_class
!= ber_class
)
2358 || (seq
->tag
!= tag
) ) ) {
2359 /* it was not, move to the next one and try again */
2360 if (seq
->flags
& BER_FLAGS_OPTIONAL
) {
2361 /* well this one was optional so just skip to the next one and try again. */
2363 goto ber_sequence_try_again
;
2366 identifier_offset
= hoffset
;
2367 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2368 identifier_len
= offset
- identifier_offset
;
2369 dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, NULL
, NULL
);
2370 if ( seq
->ber_class
== BER_CLASS_UNI
) {
2371 cause
= proto_tree_add_expert_format(
2372 tree
, actx
->pinfo
, &ei_ber_sequence_field_wrong
,
2373 tvb
, identifier_offset
, identifier_len
,
2374 "BER Error: Wrong field in SEQUENCE: expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d",
2375 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2378 val_to_str_ext_const(seq
->tag
, &ber_uni_tag_codes_ext
, "Unknown"),
2379 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2382 cause
= proto_tree_add_expert_format(
2383 tree
, actx
->pinfo
, &ei_ber_sequence_field_wrong
,
2384 tvb
, identifier_offset
, identifier_len
,
2385 "BER Error: Wrong field in SEQUENCE: expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2386 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
2389 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2393 if (decode_unexpected
) {
2394 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2395 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2403 if (!(seq
->flags
& BER_FLAGS_NOOWNTAG
) ) {
2404 /* dissect header and len for field */
2405 if (ind_field
&& (len
== 2)) {
2406 /* This is a Zero length field */
2407 next_tvb
= ber_tvb_new_subset_length(tvb
, offset
, len
);
2410 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2411 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
2412 next_tvb
= ber_tvb_new_subset_length(tvb
, hoffset
, eoffset
- hoffset
- (ind_field
? 2 : 0));
2415 next_tvb
= ber_tvb_new_subset_length(tvb
, hoffset
, eoffset
- hoffset
);
2419 /* call the dissector for this field */
2420 if ((eoffset
-hoffset
) > length_remaining
) {
2421 /* If the field is indefinite (i.e. we don't know the
2422 * length) of if the tvb is short, then just
2423 * give it all of the tvb and hope for the best.
2425 next_tvb
= tvb_new_subset_remaining(tvb
, hoffset
);
2434 header_field_info
*hfinfo
;
2436 hfinfo
= proto_registrar_get_nth(hf_id
);
2437 name
= hfinfo
->name
;
2441 if (tvb_reported_length_remaining(next_tvb
, 0) > 3) {
2442 proto_tree_add_debug_text(tree
, "SEQUENCE dissect_ber_sequence(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x\n", name
, offset
, tvb_reported_length_remaining(next_tvb
, 0), tvb_get_uint8(next_tvb
, 0), tvb_get_uint8(next_tvb
, 1), tvb_get_uint8(next_tvb
, 2));
2444 proto_tree_add_debug_text(tree
, "SEQUENCE dissect_ber_sequence(%s) calling subdissector\n", name
);
2448 if (next_tvb
== NULL
) {
2449 /* Assume that we have a malformed packet. */
2450 THROW(ReportedBoundsError
);
2453 if (seq
->flags
& BER_FLAGS_IMPLTAG
) {
2457 count
= seq
->func(imp_tag
, next_tvb
, 0, actx
, tree
, *seq
->p_id
);
2462 header_field_info
*hfinfo
;
2464 hfinfo
= proto_registrar_get_nth(hf_id
);
2465 name
= hfinfo
->name
;
2469 proto_tree_add_debug_text(tree
, "SEQUENCE dissect_ber_sequence(%s) subdissector ate %d bytes\n", name
, count
);
2472 /* if it was optional and no bytes were eaten and it was */
2473 /* supposed to (len <> 0), just try again. */
2474 if ((len
!= 0) && (count
== 0) && (seq
->flags
& BER_FLAGS_OPTIONAL
)) {
2476 goto ber_sequence_try_again
;
2477 /* move the offset to the beginning of the next sequenced item */
2480 if (!(seq
->flags
& BER_FLAGS_NOOWNTAG
) ) {
2481 /* if we stripped the tag and length we should also strip the EOC is ind_len
2482 * Unless it's a zero length field (len = 2)
2484 if ((ind_field
== 1) && (len
> 2))
2487 if (show_internal_ber_fields
) {
2488 proto_tree_add_item(tree
, hf_ber_seq_field_eoc
, tvb
, offset
-2, 2, ENC_NA
);
2495 /* if we didn't end up at exactly offset, then we ate too many bytes */
2496 if (offset
!= end_offset
) {
2497 tvb_ensure_bytes_exist(tvb
, offset
-2, 2);
2498 proto_tree_add_expert_format(
2499 tree
, actx
->pinfo
, &ei_ber_error_length
, tvb
, offset
-2, 2,
2500 "BER Error: SEQUENCE is %d too many bytes long",
2501 offset
- end_offset
);
2504 /* need to eat this EOC
2505 end_offset = tvb_reported_length(tvb);*/
2507 if (show_internal_ber_fields
) {
2508 proto_tree_add_item(tree
, hf_ber_seq_eoc
, tvb
, end_offset
-2, 2, ENC_NA
);
2514 /* This function dissects a BER set
2517 dissect_ber_set(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, const ber_sequence_t
*set
, int hf_id
, int ett_id
) {
2519 bool pcx
, ind
= 0, ind_field
, imp_tag
;
2521 int identifier_offset
;
2526 proto_tree
*tree
= parent_tree
;
2527 proto_item
*item
= NULL
;
2529 int end_offset
, s_offset
;
2532 uint32_t mandatory_fields
= 0;
2535 const ber_sequence_t
*cset
= NULL
;
2537 #define MAX_SET_ELEMENTS 32
2544 header_field_info
*hfinfo
;
2546 hfinfo
= proto_registrar_get_nth(hf_id
);
2547 name
= hfinfo
->name
;
2551 if (tvb_reported_length_remaining(tvb
, offset
) > 3) {
2552 proto_tree_add_debug_text(tree
, "SET dissect_ber_set(%s) entered offset:%d len:%d %02x:%02x:%02x\n", name
, offset
, tvb_reported_length_remaining(tvb
, offset
), tvb_get_uint8(tvb
, offset
), tvb_get_uint8(tvb
, offset
+1), tvb_get_uint8(tvb
, offset
+2));
2554 proto_tree_add_debug_text(tree
, "SET dissect_ber_set(%s) entered\n", name
);
2559 if (!implicit_tag
) {
2561 /* first we must read the sequence header */
2562 identifier_offset
= offset
;
2563 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &classx
, &pcx
, &tagx
);
2564 identifier_len
= offset
- identifier_offset
;
2565 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &lenx
, &ind
);
2567 /* Fixed the length is correctly returned from dissect ber_length
2568 end_offset = tvb_reported_length(tvb);*/
2569 end_offset
= offset
+ lenx
-2;
2571 end_offset
= offset
+ lenx
;
2574 /* sanity check: we only handle Constructed Universal Sets */
2575 if ((classx
!= BER_CLASS_APP
) && (classx
!= BER_CLASS_PRI
)) {
2577 || ((classx
!= BER_CLASS_UNI
) || (tagx
!= BER_UNI_TAG_SET
))) {
2578 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
2579 cause
= proto_tree_add_expert_format(
2580 tree
, actx
->pinfo
, &ei_ber_expected_set
,
2581 tvb
, identifier_offset
, identifier_len
,
2582 "BER Error: SET expected but class:%s(%d) %s tag:%d was found",
2583 val_to_str_const(classx
, ber_class_codes
, "Unknown"),
2585 tfs_get_string(pcx
, &tfs_constructed_primitive
),
2587 if (decode_unexpected
) {
2588 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2589 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2595 /* was implicit tag so just use the length of the tvb */
2596 lenx
= tvb_reported_length_remaining(tvb
, offset
);
2597 end_offset
= offset
+lenx
;
2598 identifier_offset
= 0;
2602 /* create subtree */
2605 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, offset
, lenx
, ENC_BIG_ENDIAN
);
2606 tree
= proto_item_add_subtree(item
, ett_id
);
2610 /* record the mandatory elements of the set so we can check we found everything at the end
2611 we can only record 32 elements for now ... */
2612 for (set_idx
= 0; (set_idx
< MAX_SET_ELEMENTS
) && (cset
= &set
[set_idx
])->func
; set_idx
++) {
2614 if (!(cset
->flags
& BER_FLAGS_OPTIONAL
))
2615 mandatory_fields
|= 1 << set_idx
;
2619 /* loop over all entries until we reach the end of the set */
2620 while (offset
< end_offset
) {
2627 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2628 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2630 if ((tvb_get_uint8(tvb
, offset
) == 0) && (tvb_get_uint8(tvb
, offset
+1) == 0)) {
2631 if (show_internal_ber_fields
) {
2632 proto_tree_add_item(tree
, hf_ber_seq_eoc
, tvb
, s_offset
, offset
+2, ENC_NA
);
2638 /* read header and len for next field */
2639 identifier_offset
= offset
;
2640 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
2641 identifier_len
= offset
- identifier_offset
;
2642 len_offset
= offset
;
2643 offset
= get_ber_length(tvb
, offset
, &len
, &ind_field
);
2644 len_len
= offset
- len_offset
;
2645 eoffset
= offset
+ len
;
2647 if (len
> (uint32_t)(end_offset
- offset
) || len
> (uint32_t) tvb_reported_length_remaining(tvb
, offset
)) {
2648 ber_add_large_length_error(actx
->pinfo
, tree
, tvb
, offset
, len
, tvb
, len_offset
, len_len
);
2652 /* Look through the Set to see if this class/id exists and
2653 * hasn't been seen before
2654 * Skip check completely if ber_class == ANY
2655 * of if NOCHKTAG is set
2658 for (first_pass
= true, cset
= set
, set_idx
= 0; cset
->func
|| first_pass
; cset
++, set_idx
++) {
2660 /* we reset for a second pass when we will look for choices */
2664 cset
= set
; /* reset to the beginning */
2666 /* If the set has no values, there is no point in trying again. */
2672 if ((first_pass
&& ((cset
->ber_class
== ber_class
) && (cset
->tag
== tag
))) ||
2673 (!first_pass
&& ((cset
->ber_class
== BER_CLASS_ANY
) && (cset
->tag
== -1))) ) /* choices */
2675 if (!(cset
->flags
& BER_FLAGS_NOOWNTAG
) ) {
2676 /* dissect header and len for field */
2677 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
2678 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
2679 next_tvb
= ber_tvb_new_subset_length(tvb
, hoffset
, eoffset
- hoffset
- (ind_field
? 2 : 0));
2681 next_tvb
= ber_tvb_new_subset_length(tvb
, hoffset
, eoffset
- hoffset
);
2686 /* call the dissector for this field */
2687 if ((eoffset
-hoffset
)>length_remaining
) {
2688 /* If the field is indefinite (i.e. we don't know the
2689 * length) of if the tvb is short, then just
2690 * give it all of the tvb and hope for the best.
2692 next_tvb
= tvb_new_subset_remaining(tvb
, hoffset
);
2701 header_field_info
*hfinfo
;
2703 hfinfo
= proto_registrar_get_nth(hf_id
);
2704 name
= hfinfo
->name
;
2708 if (tvb_reported_length_remaining(next_tvb
, 0) > 3) {
2709 proto_tree_add_debug_text(tree
, "SET dissect_ber_set(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x\n", name
, offset
, tvb_reported_length_remaining(next_tvb
, 0), tvb_get_uint8(next_tvb
, 0), tvb_get_uint8(next_tvb
, 1), tvb_get_uint8(next_tvb
, 2));
2711 proto_tree_add_debug_text(tree
, "SET dissect_ber_set(%s) calling subdissector\n", name
);
2715 if (next_tvb
== NULL
) {
2716 /* Assume that we have a malformed packet. */
2717 THROW(ReportedBoundsError
);
2720 if ((cset
->flags
& BER_FLAGS_IMPLTAG
))
2722 count
= cset
->func(imp_tag
, next_tvb
, 0, actx
, tree
, *cset
->p_id
);
2724 /* if we consumed some bytes,
2725 or we knew the length was zero (during the first pass only) */
2726 if (count
|| (first_pass
&& ((len
== 0) || ((ind_field
== 1) && (len
== 2))))) {
2728 if (set_idx
< MAX_SET_ELEMENTS
)
2729 mandatory_fields
&= ~(1 << set_idx
);
2733 if (!(cset
->flags
& BER_FLAGS_NOOWNTAG
) ) {
2734 /* if we stripped the tag and length we should also strip the EOC is ind_len */
2735 if (ind_field
== 1) {
2737 if (show_internal_ber_fields
) {
2738 proto_tree_add_item(tree
, hf_ber_set_field_eoc
, tvb
, offset
, count
, ENC_NA
);
2748 /* we didn't find a match */
2749 cause
= proto_tree_add_expert_format(
2750 tree
, actx
->pinfo
, &ei_ber_unknown_field_set
,
2751 tvb
, identifier_offset
, identifier_len
,
2752 "BER Error: Unknown field in SET class:%s(%d) tag:%d",
2753 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
2756 if (decode_unexpected
) {
2757 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
2758 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
2764 if (mandatory_fields
) {
2766 /* OK - we didn't find some of the elements we expected */
2768 for (set_idx
= 0; (set_idx
< MAX_SET_ELEMENTS
) && (cset
= &set
[set_idx
])->func
; set_idx
++) {
2769 if (mandatory_fields
& (1U << set_idx
)) {
2770 /* here is something we should have seen - but didn't! */
2771 proto_tree_add_expert_format(
2772 tree
, actx
->pinfo
, &ei_ber_missing_field_set
,
2773 tvb
, identifier_offset
, identifier_len
,
2774 "BER Error: Missing field in SET class:%s(%d) tag:%d expected",
2775 val_to_str_const(cset
->ber_class
, ber_class_codes
, "Unknown"),
2783 /* if we didn't end up at exactly offset, then we ate too many bytes */
2784 if (offset
!= end_offset
) {
2785 tvb_ensure_bytes_exist(tvb
, offset
-2, 2);
2786 proto_tree_add_expert_format(
2787 tree
, actx
->pinfo
, &ei_ber_error_length
, tvb
, offset
-2, 2,
2788 "BER Error: SET is %d too many bytes long",
2789 offset
- end_offset
);
2793 /* need to eat this EOC
2794 end_offset = tvb_reported_length(tvb);*/
2796 if (show_internal_ber_fields
) {
2797 proto_tree_add_item(tree
, hf_ber_set_eoc
, tvb
, end_offset
-2, 2, ENC_NA
);
2806 #define DEBUG_BER_CHOICE
2810 dissect_ber_choice(asn1_ctx_t
*actx
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, const ber_choice_t
*choice
, int hf_id
, int ett_id
, int *branch_taken
)
2813 bool pc
, ind
, imp_tag
= false;
2815 int identifier_offset
;
2818 proto_tree
*tree
= parent_tree
;
2819 proto_item
*item
= NULL
;
2820 int end_offset
, start_offset
, count
;
2821 int hoffset
= offset
;
2825 header_field_info
*hfinfo
;
2826 const ber_choice_t
*ch
;
2828 #ifdef DEBUG_BER_CHOICE
2832 hfinfo
= proto_registrar_get_nth(hf_id
);
2833 name
= hfinfo
->name
;
2837 if (tvb_reported_length_remaining(tvb
, offset
) > 3) {
2838 proto_tree_add_debug_text(tree
, "CHOICE dissect_ber_choice(%s) entered offset:%d len:%d %02x:%02x:%02x\n", name
, offset
, tvb_reported_length_remaining(tvb
, offset
), tvb_get_uint8(tvb
, offset
), tvb_get_uint8(tvb
, offset
+1), tvb_get_uint8(tvb
, offset
+2));
2840 proto_tree_add_debug_text(tree
, "CHOICE dissect_ber_choice(%s) entered len:%d\n", name
, tvb_reported_length_remaining(tvb
, offset
));
2845 start_offset
= offset
;
2851 if (tvb_reported_length_remaining(tvb
, offset
) == 0) {
2852 proto_tree_add_expert(
2853 parent_tree
, actx
->pinfo
, &ei_ber_empty_choice
, tvb
, offset
, 0);
2857 /* read header and len for choice field */
2858 identifier_offset
= offset
;
2859 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
2860 identifier_len
= offset
- identifier_offset
;
2861 offset
= get_ber_length(tvb
, offset
, &len
, &ind
);
2862 end_offset
= offset
+ len
;
2864 /* Some sanity checks.
2865 * The hf field passed to us MUST be an integer type
2868 hfinfo
= proto_registrar_get_nth(hf_id
);
2869 switch (hfinfo
->type
) {
2876 proto_tree_add_expert_format(
2877 tree
, actx
->pinfo
, &ei_hf_field_not_integer_type
,
2878 tvb
, identifier_offset
, identifier_len
,
2879 "BER Error: dissect_ber_choice(): frame:%u offset:%d Was passed an HF field that was not integer type : %s",
2880 actx
->pinfo
->num
, offset
, hfinfo
->abbrev
);
2885 /* loop over all entries until we find the right choice or
2886 run out of entries */
2889 while (ch
->func
|| first_pass
) {
2893 /* we reset for a second pass when we will look for choices */
2896 ch
= choice
; /* reset to the beginning */
2903 #ifdef DEBUG_BER_CHOICE
2904 proto_tree_add_debug_text(tree
, "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
);
2907 && (((ch
->ber_class
== ber_class
) && (ch
->tag
== tag
))
2908 || ((ch
->ber_class
== ber_class
) && (ch
->tag
== -1) && (ch
->flags
& BER_FLAGS_NOOWNTAG
))))
2909 || (!first_pass
&& (((ch
->ber_class
== BER_CLASS_ANY
) && (ch
->tag
== -1)))) /* we failed on the first pass so now try any choices */
2911 if (!(ch
->flags
& BER_FLAGS_NOOWNTAG
)) {
2912 /* dissect header and len for field */
2913 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, start_offset
, NULL
, NULL
, NULL
);
2914 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
2915 start_offset
= hoffset
;
2922 length
= end_offset
- hoffset
;
2924 /* create subtree */
2927 item
= proto_tree_add_uint(parent_tree
, hf_id
, tvb
, hoffset
, end_offset
- hoffset
, ch
->value
);
2928 tree
= proto_item_add_subtree(item
, ett_id
);
2933 /* This is bogus and makes the OID_1.0.9506.1.1.cap file
2934 * in Steven J Schaeffer's email of 2005-09-12 fail to dissect
2935 * properly. Maybe we should get rid of 'first_pass'
2937 * It was added as a qad workaround for some problem CMIP
2939 * God, this file is a mess and it is my fault. /ronnie
2942 next_tvb
= ber_tvb_new_subset_length(tvb
, hoffset
, length
);
2944 next_tvb
= tvb
; /* we didn't make selection on this class/tag so pass it on */
2946 next_tvb
= ber_tvb_new_subset_length(tvb
, hoffset
, length
);
2949 #ifdef DEBUG_BER_CHOICE
2953 hfinfo
= proto_registrar_get_nth(hf_id
);
2954 name
= hfinfo
->name
;
2958 if (tvb_reported_length_remaining(next_tvb
, 0) > 3) {
2959 proto_tree_add_debug_text(tree
, "CHOICE dissect_ber_choice(%s) calling subdissector start_offset:%d offset:%d len:%d %02x:%02x:%02x\n", name
, start_offset
, offset
, tvb_reported_length_remaining(next_tvb
, 0), tvb_get_uint8(next_tvb
, 0), tvb_get_uint8(next_tvb
, 1), tvb_get_uint8(next_tvb
, 2));
2961 proto_tree_add_debug_text(tree
, "CHOICE dissect_ber_choice(%s) calling subdissector len:%d\n", name
, tvb_reported_length(next_tvb
));
2965 if (next_tvb
== NULL
) {
2966 /* Assume that we have a malformed packet. */
2967 THROW(ReportedBoundsError
);
2970 if ((ch
->flags
& BER_FLAGS_IMPLTAG
))
2972 count
= ch
->func(imp_tag
, next_tvb
, 0, actx
, tree
, *ch
->p_id
);
2973 #ifdef DEBUG_BER_CHOICE
2977 hfinfo
= proto_registrar_get_nth(hf_id
);
2978 name
= hfinfo
->name
;
2982 proto_tree_add_debug_text(tree
, "CHOICE dissect_ber_choice(%s) subdissector ate %d bytes\n", name
, count
);
2985 if ((count
== 0) && (((ch
->ber_class
== ber_class
) && (ch
->tag
== -1) && (ch
->flags
& BER_FLAGS_NOOWNTAG
)) || !first_pass
)) {
2986 /* wrong one, break and try again */
2988 #ifdef DEBUG_BER_CHOICE
2992 hfinfo
= proto_registrar_get_nth(hf_id
);
2993 name
= hfinfo
->name
;
2997 proto_tree_add_debug_text(tree
, "CHOICE dissect_ber_choice(%s) trying again\n", name
);
3002 if (!(ch
->flags
& BER_FLAGS_NOOWNTAG
)) {
3004 /* we are traversing a indefinite length choice where we did not pass the tag length */
3005 /* we need to eat the EOC */
3006 if (show_internal_ber_fields
) {
3007 proto_tree_add_item(tree
, hf_ber_choice_eoc
, tvb
, end_offset
-2, 2, ENC_NA
);
3016 /* none of the branches were taken so set the param
3022 /*XXX here we should have another flag to the CHOICE to distinguish
3023 * between the case when we know it is a mandatory or if the CHOICE is optional == no arm matched */
3025 /* oops no more entries and we still haven't found
3028 proto_tree_add_expert(
3029 tree
, actx
->pinfo
, &ei_ber_choice_not_found
, tvb
, offset
, len
);
3033 return start_offset
;
3037 /* this function dissects a BER GeneralString
3040 dissect_ber_GeneralString(asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, char *name_string
, int name_len
)
3045 int identifier_offset
;
3063 /* first we must read the GeneralString header */
3064 identifier_offset
= offset
;
3065 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
3066 identifier_len
= offset
- identifier_offset
;
3067 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
3068 end_offset
= offset
+ len
;
3070 /* sanity check: we only handle Universal GeneralString*/
3071 if ( (ber_class
!= BER_CLASS_UNI
)
3072 || (tag
!= BER_UNI_TAG_GENSTR
) ) {
3073 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
3074 cause
= proto_tree_add_expert_format(
3075 tree
, actx
->pinfo
, &ei_ber_expected_general_string
,
3076 tvb
, identifier_offset
, identifier_len
,
3077 "BER Error: GeneralString expected but class:%s(%d) %s tag:%d was unexpected",
3078 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3079 ber_class
, tfs_get_string(pc
, &tfs_constructed_primitive
),
3081 if (decode_unexpected
) {
3082 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3083 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3088 if (len
>= (max_len
- 1)) {
3092 tvb_memcpy(tvb
, str
, offset
, len
);
3096 proto_tree_add_string(tree
, hf_id
, tvb
, offset
, len
, str
);
3104 // NOLINTNEXTLINE(misc-no-recursion)
3105 dissect_ber_constrained_restricted_string(bool implicit_tag
, int32_t type
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int32_t min_len
, int32_t max_len
, int hf_id
, tvbuff_t
**out_tvb
) {
3109 int identifier_offset
;
3113 int hoffset
= offset
;
3119 header_field_info
*hfinfo
;
3121 hfinfo
= proto_registrar_get_nth(hf_id
);
3122 name
= hfinfo
->name
;
3126 if (tvb_reported_length_remaining(tvb
, offset
) > 3) {
3127 proto_tree_add_debug_text(tree
, "RESTRICTED STRING dissect_ber_octet string(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name
, implicit_tag
, offset
, tvb_reported_length_remaining(tvb
, offset
), tvb_get_uint8(tvb
, offset
), tvb_get_uint8(tvb
, offset
+1), tvb_get_uint8(tvb
, offset
+2));
3129 proto_tree_add_debug_text(tree
, "RESTRICTED STRING dissect_ber_octet_string(%s) entered\n", name
);
3134 if (!implicit_tag
) {
3135 identifier_offset
= offset
;
3136 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
3137 identifier_len
= offset
- identifier_offset
;
3138 offset
= get_ber_length(tvb
, offset
, &len
, NULL
);
3139 eoffset
= offset
+ len
;
3142 if ( (ber_class
!= BER_CLASS_UNI
)
3143 || (tag
!= type
) ) {
3144 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
3145 cause
= proto_tree_add_expert_format(
3146 tree
, actx
->pinfo
, &ei_ber_expected_string
,
3147 tvb
, identifier_offset
, identifier_len
,
3148 "BER Error: String with tag=%d expected but class:%s(%d) %s tag:%d was unexpected",
3150 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3151 ber_class
, tfs_get_string(pc
, &tfs_constructed_primitive
),
3153 if (decode_unexpected
) {
3154 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3155 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3162 return dissect_ber_constrained_octet_string(implicit_tag
, actx
, tree
, tvb
, hoffset
, min_len
, max_len
, hf_id
, out_tvb
);
3165 // NOLINTNEXTLINE(misc-no-recursion)
3166 int dissect_ber_restricted_string(bool implicit_tag
, int32_t type
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, tvbuff_t
**out_tvb
)
3168 return dissect_ber_constrained_restricted_string(implicit_tag
, type
, actx
, tree
, tvb
, offset
, NO_BOUND
, NO_BOUND
, hf_id
, out_tvb
);
3172 // NOLINTNEXTLINE(misc-no-recursion)
3173 dissect_ber_GeneralString(asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, char *name_string
, unsigned name_len
)
3175 tvbuff_t
*out_tvb
= NULL
;
3178 offset
= dissect_ber_restricted_string(false, BER_UNI_TAG_GeneralString
, actx
, tree
, tvb
, offset
, hf_id
, (name_string
) ? &out_tvb
: NULL
);
3182 * XXX - do we want to just get what's left in the tvbuff
3183 * if the full length isn't available in the tvbuff, or
3184 * do we want to throw an exception?
3187 tvb_len
= tvb_reported_length(out_tvb
);
3188 if ((unsigned)tvb_len
>= name_len
) {
3189 tvb_memcpy(out_tvb
, (uint8_t*)name_string
, 0, name_len
-1);
3190 name_string
[name_len
-1] = '\0';
3192 tvb_memcpy(out_tvb
, (uint8_t*)name_string
, 0, tvb_len
);
3193 name_string
[tvb_len
] = '\0';
3201 /* 8.19 Encoding of a relative or absolute object identifier value.
3204 // NOLINTNEXTLINE(misc-no-recursion)
3205 dissect_ber_any_oid(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, tvbuff_t
**value_tvb
, bool is_absolute
)
3210 int identifier_offset
;
3218 header_field_info
*hfi
;
3222 header_field_info
*hfinfo
;
3224 hfinfo
= proto_registrar_get_nth(hf_id
);
3225 name
= hfinfo
->name
;
3229 if (tvb_reported_length_remaining(tvb
, offset
) > 3) {
3230 proto_tree_add_debug_text(tree
, "OBJECT IDENTIFIER dissect_ber_any_oid(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name
, implicit_tag
, offset
, tvb_reported_length_remaining(tvb
, offset
), tvb_get_uint8(tvb
, offset
), tvb_get_uint8(tvb
, offset
+1), tvb_get_uint8(tvb
, offset
+2));
3232 proto_tree_add_debug_text(tree
, "OBJECT IDENTIFIER dissect_ber_any_oid(%s) entered\n", name
);
3237 if (!implicit_tag
) {
3240 identifier_offset
= offset
;
3241 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
3242 identifier_len
= offset
- identifier_offset
;
3243 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
3244 eoffset
= offset
+ len
;
3245 if ( (ber_class
!= BER_CLASS_UNI
)
3246 || (is_absolute
&& tag
!= BER_UNI_TAG_OID
)
3247 || (!is_absolute
&& tag
!= BER_UNI_TAG_RELATIVE_OID
) ) {
3248 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
3249 cause
= proto_tree_add_expert_format(
3250 tree
, actx
->pinfo
, &ei_ber_expected_object_identifier
,
3251 tvb
, identifier_offset
, identifier_len
,
3252 "BER Error: Object Identifier expected but class:%s(%d) %s tag:%d was unexpected",
3253 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3255 tfs_get_string(pc
, &tfs_constructed_primitive
),
3257 if (decode_unexpected
) {
3258 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3259 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3264 len
= tvb_reported_length_remaining(tvb
, offset
);
3265 eoffset
= offset
+len
;
3268 actx
->created_item
= NULL
;
3269 hfi
= proto_registrar_get_nth(hf_id
);
3270 if ((is_absolute
&& hfi
->type
== FT_OID
) || (!is_absolute
&& hfi
->type
== FT_REL_OID
)) {
3271 actx
->created_item
= proto_tree_add_item(tree
, hf_id
, tvb
, offset
, len
, ENC_BIG_ENDIAN
);
3272 } else if (FT_IS_STRING(hfi
->type
)) {
3273 str
= oid_encoded2string(actx
->pinfo
->pool
, tvb_get_ptr(tvb
, offset
, len
), len
);
3274 actx
->created_item
= proto_tree_add_string(tree
, hf_id
, tvb
, offset
, len
, str
);
3275 if (actx
->created_item
) {
3276 /* see if we know the name of this oid */
3277 name
= oid_resolved_from_encoded(actx
->pinfo
->pool
, tvb_get_ptr(tvb
, offset
, len
), len
);
3279 proto_item_append_text(actx
->created_item
, " (%s)", name
);
3283 DISSECTOR_ASSERT_NOT_REACHED();
3287 *value_tvb
= ber_tvb_new_subset_length(tvb
, offset
, len
);
3293 // NOLINTNEXTLINE(misc-no-recursion)
3294 dissect_ber_any_oid_str(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, const char **value_stringx
, bool is_absolute
)
3296 tvbuff_t
*value_tvb
= NULL
;
3299 offset
= dissect_ber_any_oid(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, (value_stringx
) ? &value_tvb
: NULL
, is_absolute
);
3301 if (value_stringx
) {
3302 if (value_tvb
&& (length
= tvb_reported_length(value_tvb
))) {
3303 *value_stringx
= oid_encoded2string(actx
->pinfo
->pool
, tvb_get_ptr(value_tvb
, 0, length
), length
);
3305 *value_stringx
= "";
3312 /* 8.19 Encoding of a relative object identifier value.
3315 // NOLINTNEXTLINE(misc-no-recursion)
3316 dissect_ber_relative_oid(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, tvbuff_t
**value_tvb
)
3318 return dissect_ber_any_oid(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, value_tvb
, false);
3322 // NOLINTNEXTLINE(misc-no-recursion)
3323 dissect_ber_relative_oid_str(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, const char **value_stringx
)
3325 return dissect_ber_any_oid_str(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, value_stringx
, false);
3328 /* 8.19 Encoding of an object identifier value.
3331 // NOLINTNEXTLINE(misc-no-recursion)
3332 dissect_ber_object_identifier(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, tvbuff_t
**value_tvb
)
3334 return dissect_ber_any_oid(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, value_tvb
, true);
3338 // NOLINTNEXTLINE(misc-no-recursion)
3339 dissect_ber_object_identifier_str(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, const char **value_stringx
)
3341 return dissect_ber_any_oid_str(implicit_tag
, actx
, tree
, tvb
, offset
, hf_id
, value_stringx
, true);
3345 #define DEBUG_BER_SQ_OF
3349 dissect_ber_sq_of(bool implicit_tag
, int32_t type
, asn1_ctx_t
*actx
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, int32_t min_len
, int32_t max_len
, const ber_sequence_t
*seq
, int hf_id
, int ett_id
) {
3351 bool pcx
, ind
= false, ind_field
;
3353 int identifier_offset
;
3357 proto_tree
*tree
= parent_tree
;
3358 proto_item
*item
= NULL
;
3360 int cnt
, hoffsetx
, end_offset
;
3362 header_field_info
*hfi
;
3365 #ifdef DEBUG_BER_SQ_OF
3368 header_field_info
*hfinfo
;
3370 hfinfo
= proto_registrar_get_nth(hf_id
);
3371 name
= hfinfo
->name
;
3375 if (tvb_reported_length_remaining(tvb
,offset
) > 3) {
3376 proto_tree_add_debug_text(tree
, "SQ OF dissect_ber_sq_of(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name
, implicit_tag
, offset
, tvb_reported_length_remaining(tvb
, offset
), tvb_get_uint8(tvb
, offset
), tvb_get_uint8(tvb
, offset
+1), tvb_get_uint8(tvb
, offset
+2));
3378 proto_tree_add_debug_text(tree
, "SQ OF dissect_ber_sq_of(%s) entered\n", name
);
3383 if (!implicit_tag
) {
3385 /* first we must read the sequence header */
3386 identifier_offset
= offset
;
3387 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &classx
, &pcx
, &tagx
);
3388 identifier_len
= offset
- identifier_offset
;
3389 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &lenx
, &ind
);
3390 end_offset
= offset
+ lenx
;
3392 /* sanity check: we only handle Constructed Universal Sequences */
3393 if ((classx
!= BER_CLASS_APP
) && (classx
!= BER_CLASS_PRI
)) {
3395 || ((classx
!= BER_CLASS_UNI
) || (tagx
!= type
))) {
3396 tvb_ensure_bytes_exist(tvb
, hoffsetx
, 2);
3397 causex
= proto_tree_add_expert_format(
3399 (type
== BER_UNI_TAG_SEQUENCE
) ? &ei_ber_expected_set
: &ei_ber_expected_sequence
,
3400 tvb
, identifier_offset
, identifier_len
,
3401 "BER Error: %s OF expected but class:%s(%d) %s tag:%d was unexpected",
3402 (type
== BER_UNI_TAG_SEQUENCE
) ? "SET" : "SEQUENCE",
3403 val_to_str_const(classx
, ber_class_codes
, "Unknown"),
3404 classx
, tfs_get_string(pcx
, &tfs_constructed_primitive
),
3406 if (decode_unexpected
) {
3407 proto_tree
*unknown_tree
= proto_item_add_subtree(causex
, ett_ber_unknown
);
3408 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffsetx
, unknown_tree
);
3414 /* the tvb length should be correct now nope we could be coming from an implicit choice or sequence, thus we
3415 read the items we match and return the length*/
3416 lenx
= tvb_reported_length_remaining(tvb
, offset
);
3417 end_offset
= offset
+ lenx
;
3420 /* count number of items */
3424 /* only count the number of items IFF we have the full blob,
3425 * else this will just generate a [short frame] before we even start
3426 * dissecting a single item.
3428 /* XXX Do we really need to count them at all ? ronnie */
3429 if (tvb_captured_length_remaining(tvb
, offset
) == tvb_reported_length_remaining(tvb
, offset
)) {
3431 while (offset
< end_offset
) {
3437 /*if (ind) { this sequence of was of indefinite length, if this is implicit indefinite impossible maybe
3438 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
3439 if ((tvb_get_uint8(tvb
, offset
) == 0) && (tvb_get_uint8(tvb
, offset
+1) == 0)) {
3444 /* read header and len for next field */
3445 offset
= get_ber_identifier(tvb
, offset
, NULL
, NULL
, NULL
);
3446 offset
= get_ber_length(tvb
, offset
, &len
, &ind
);
3447 /* best place to get real length of implicit sequence of or set of is here... */
3448 /* adjust end_offset if we find somthing that doesn't match */
3451 if (offset
<= s_offset
) {
3452 /* Underflow - give up; this can happen with a very large
3463 /* create subtree */
3465 hfi
= proto_registrar_get_nth(hf_id
);
3467 if (hfi
->type
== FT_NONE
) {
3468 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, offset
, lenx
, ENC_BIG_ENDIAN
);
3469 proto_item_append_text(item
, ":");
3472 item
= proto_tree_add_uint(parent_tree
, hf_id
, tvb
, offset
, lenx
, cnt
);
3473 proto_item_append_text(item
, (cnt
== 1) ? " item" : " items");
3475 item
= proto_tree_add_uint_format_value(parent_tree
, hf_id
, tvb
, offset
, lenx
, cnt
, "unknown number of items");
3477 tree
= proto_item_add_subtree(item
, ett_id
);
3478 ber_check_items (cnt
, min_len
, max_len
, actx
, item
);
3482 /* loop over all entries until we reach the end of the sequence */
3483 while (offset
< end_offset
) {
3494 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
3495 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
3496 if ((tvb_get_uint8(tvb
, offset
) == 0) && (tvb_get_uint8(tvb
, offset
+1) == 0)) {
3497 if (show_internal_ber_fields
) {
3498 proto_tree_add_item(tree
, hf_ber_seq_of_eoc
, tvb
, hoffset
, end_offset
-hoffset
, ENC_NA
);
3503 /* read header and len for next field */
3504 identifier_offset
= offset
;
3505 offset
= get_ber_identifier(tvb
, offset
, &ber_class
, &pc
, &tag
);
3506 identifier_len
= offset
- identifier_offset
;
3507 offset
= get_ber_length(tvb
, offset
, &len
, &ind_field
);
3508 eoffset
= offset
+ len
;
3509 /* Make sure we move forward */
3510 if (eoffset
<= hoffset
)
3511 THROW(ReportedBoundsError
);
3513 if ((ber_class
== BER_CLASS_UNI
) && (tag
== BER_UNI_TAG_EOC
)) {
3514 /* This is a zero length sequence of*/
3515 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
3516 dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
3519 /* verify that this one is the one we want */
3520 /* ahup if we are implicit then we return to the upper layer how much we have used */
3521 if (seq
->ber_class
!= BER_CLASS_ANY
) {
3522 if ((seq
->ber_class
!= ber_class
)
3523 || (seq
->tag
!= tag
) ) {
3524 if (!(seq
->flags
& BER_FLAGS_NOTCHKTAG
)) {
3525 if ( seq
->ber_class
== BER_CLASS_UNI
) {
3526 cause
= proto_tree_add_expert_format(
3527 tree
, actx
->pinfo
, &ei_ber_sequence_field_wrong
,
3528 tvb
, identifier_offset
, identifier_len
,
3529 "BER Error: Wrong field in SEQUENCE OF: expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d",
3530 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
3533 val_to_str_ext_const(seq
->tag
, &ber_uni_tag_codes_ext
, "Unknown"),
3534 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3537 cause
= proto_tree_add_expert_format(
3538 tree
, actx
->pinfo
, &ei_ber_sequence_field_wrong
,
3539 tvb
, identifier_offset
, identifier_len
,
3540 "BER Error: Wrong field in SEQUENCE OF: expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
3541 val_to_str_const(seq
->ber_class
, ber_class_codes
, "Unknown"),
3544 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3548 if (decode_unexpected
) {
3549 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3550 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3559 if (!(seq
->flags
& BER_FLAGS_NOOWNTAG
) && !(seq
->flags
& BER_FLAGS_IMPLTAG
)) {
3560 /* dissect header and len for field */
3561 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
3562 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
3564 if ((seq
->flags
== BER_FLAGS_IMPLTAG
) && (seq
->ber_class
== BER_CLASS_CON
)) {
3565 /* Constructed sequence of with a tag */
3566 /* dissect header and len for field */
3567 hoffset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
, NULL
);
3568 hoffset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, hoffset
, NULL
, NULL
);
3569 /* Function has IMPLICIT TAG */
3572 next_tvb
= ber_tvb_new_subset_length(tvb
, hoffset
, eoffset
-hoffset
);
3575 if (seq
->flags
== BER_FLAGS_IMPLTAG
)
3577 /* call the dissector for this field */
3578 seq
->func(imp_tag
, next_tvb
, 0, actx
, tree
, *seq
->p_id
);
3579 /* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
3580 doesn't match the next item, thus this implicit sequence is over, return the number of bytes
3581 we have eaten to allow the possible upper sequence continue... */
3586 /* if we didn't end up at exactly offset, then we ate too many bytes */
3587 if (offset
!= end_offset
) {
3588 tvb_ensure_bytes_exist(tvb
, offset
-2, 2);
3589 proto_tree_add_expert_format(
3590 tree
, actx
->pinfo
, &ei_ber_error_length
, tvb
, offset
-2, 2,
3591 "BER Error: %s OF contained %d too many bytes",
3592 (type
== BER_UNI_TAG_SEQUENCE
) ? "SEQUENCE" : "SET",
3593 offset
- end_offset
);
3600 dissect_ber_constrained_sequence_of(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, int32_t min_len
, int32_t max_len
, const ber_sequence_t
*seq
, int hf_id
, int ett_id
) {
3601 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
);
3605 dissect_ber_sequence_of(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, const ber_sequence_t
*seq
, int hf_id
, int ett_id
) {
3606 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
);
3610 dissect_ber_constrained_set_of(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, int32_t min_len
, int32_t max_len
, const ber_sequence_t
*seq
, int hf_id
, int ett_id
) {
3611 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
);
3615 dissect_ber_set_of(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, const ber_sequence_t
*seq
, int hf_id
, int ett_id
) {
3616 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
);
3620 dissect_ber_GeneralizedTime(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
)
3623 const uint8_t *tmpstr
;
3627 int identifier_offset
;
3636 if (!implicit_tag
) {
3638 identifier_offset
= offset
;
3639 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
3640 identifier_len
= offset
- identifier_offset
;
3641 len_offset
= offset
;
3642 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
3643 len_len
= offset
- len_offset
;
3644 end_offset
= offset
+len
;
3646 /* sanity check. we only handle universal/generalized time */
3647 if ( (ber_class
!= BER_CLASS_UNI
) || (tag
!= BER_UNI_TAG_GeneralizedTime
)) {
3648 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
3649 cause
= proto_tree_add_expert_format(
3650 tree
, actx
->pinfo
, &ei_ber_expected_generalized_time
,
3651 tvb
, identifier_offset
, identifier_len
,
3652 "BER Error: GeneralizedTime expected but class:%s(%d) %s tag:%d was unexpected",
3653 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3655 tfs_get_string(pc
, &tfs_constructed_primitive
),
3657 if (decode_unexpected
) {
3658 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3659 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3664 len
= tvb_reported_length_remaining(tvb
, offset
);
3667 end_offset
= offset
+len
;
3670 /* ASN.1 GeneralizedTime is a ISO 8601 Basic profile that omits the T
3671 * between date and time. BER allows accuracy of hours, minutes, seconds,
3672 * fractions of a second "to any degree of accuracy", and even
3673 * fractional minutes or hours (see ITU-T X.680 46.2 and ITU-T X.690 8.25.)
3675 * CER/DER (and PER) require that the seconds field be present (cf.
3676 * ITU-T X.690 11.7 and ITU-T X.691 10.6.5), that the decimal point
3677 * element be ".", that fractional seconds trailing zeros MUST be omitted,
3678 * and that the decimal point shall also be omitted if the entire fractional
3679 * second is 0 (in order to have a unique representation.)
3681 * RFC 5280 says that X.509 certificate validity dates after 2050, which
3682 * MUST use GeneralizedTime, MUST be expressed in Z and MUST include
3683 * seconds but MUST NOT include fractional seconds.
3685 * The minimum that iso8601_to_nstime() handles currently is
3686 * YYYYMMDDhhmm = 12 digits
3687 * and the maximimum is
3688 * YYYYMMDDhhmmss.sssssssss+hhmm = 29 digits
3690 * That doesn't handle everything that BER technically supports, but
3691 * everything seen in practice. For the protocols that are more restrictive
3692 * if someone really wants to validate and complain about e.g. fractional
3693 * seconds in a X.509 certificate, that could be added to the conformance
3696 if ((len
< 12) || (len
> 29)) {
3697 cause
= proto_tree_add_expert_format(
3698 tree
, actx
->pinfo
, &ei_ber_error_length
,
3699 tvb
, len_offset
, len_len
,
3700 "BER Error: GeneralizedTime invalid length: %u",
3702 if (decode_unexpected
) {
3703 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3704 dissect_unknown_ber(actx
->pinfo
, tvb
, offset
, unknown_tree
);
3709 tmpstr
= tvb_get_string_enc(actx
->pinfo
->pool
, tvb
, offset
, len
, ENC_ASCII
);
3710 if (!iso8601_to_nstime(&ts
, tmpstr
, ISO8601_DATETIME_BASIC
)) {
3711 cause
= proto_tree_add_expert_format(
3712 tree
, actx
->pinfo
, &ei_ber_invalid_format_generalized_time
,
3714 "BER Error: GeneralizedTime invalid format: %s",
3716 if (decode_unexpected
) {
3717 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3718 dissect_unknown_ber(actx
->pinfo
, tvb
, offset
, unknown_tree
);
3724 proto_tree_add_time(tree
, hf_id
, tvb
, offset
, len
, &ts
);
3732 /* datestrptr: if not NULL return datetime string instead of adding to tree or NULL when packet is malformed
3733 * tvblen: if not NULL return consumed packet bytes
3736 dissect_ber_UTCTime(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int hf_id
, char **datestrptr
, uint32_t *tvblen
)
3738 char *outstr
, *outstrptr
;
3739 const uint8_t *instr
;
3743 int identifier_offset
;
3748 proto_tree
*error_tree
;
3749 const char *error_str
= NULL
;
3751 outstrptr
= outstr
= (char *)wmem_alloc(actx
->pinfo
->pool
, 29);
3753 if (datestrptr
) *datestrptr
= NULL
; /* mark invalid */
3754 if (tvblen
) *tvblen
= 0;
3756 if (!implicit_tag
) {
3758 identifier_offset
= offset
;
3759 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
3760 identifier_len
= offset
- identifier_offset
;
3761 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, NULL
);
3763 /* sanity check: we only handle UTCTime */
3764 if ( (ber_class
!= BER_CLASS_UNI
) || (tag
!= BER_UNI_TAG_UTCTime
) ) {
3765 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
3766 cause
= proto_tree_add_expert_format(
3767 tree
, actx
->pinfo
, &ei_ber_expected_utc_time
,
3768 tvb
, identifier_offset
, identifier_len
,
3769 "BER Error: UTCTime expected but class:%s(%d) %s tag:%d was unexpected",
3770 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3772 tfs_get_string(pc
, &tfs_constructed_primitive
),
3774 if (decode_unexpected
) {
3775 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3776 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3781 len
= tvb_reported_length_remaining(tvb
, offset
);
3784 if ((len
< 10) || (len
> 19)) {
3785 error_str
= wmem_strdup_printf(actx
->pinfo
->pool
, "BER Error: UTCTime invalid length: %u", len
);
3786 instr
= tvb_get_string_enc(actx
->pinfo
->pool
, tvb
, offset
, len
> 19 ? 19 : len
, ENC_ASCII
);
3790 instr
= tvb_get_string_enc(actx
->pinfo
->pool
, tvb
, offset
, len
, ENC_ASCII
);
3793 for (i
=0; i
<10; i
++) {
3794 if ((instr
[i
] < '0') || (instr
[i
] > '9')) {
3795 error_str
= "BER Error: malformed UTCTime encoding, "
3796 "first 10 octets have to contain YYMMDDhhmm in digits";
3800 snprintf(outstrptr
, 15, "%.2s-%.2s-%.2s %.2s:%.2s", instr
, instr
+2, instr
+4, instr
+6, instr
+8);
3805 if ((instr
[i
] >= '0') && (instr
[i
] <= '9')) {
3807 if ((instr
[i
] >= '0') && (instr
[i
] <= '9')) {
3809 snprintf(outstrptr
, 4, ":%.2s", instr
+10);
3812 error_str
= "BER Error: malformed UTCTime encoding, "
3813 "if 11th octet is a digit for seconds, "
3814 "the 12th octet has to be a digit, too";
3824 error_str
= "BER Error: malformed UTCTime encoding, "
3825 "there must be no further octets after \'Z\'";
3828 snprintf(outstrptr
, 7, " (UTC)");
3834 error_str
= "BER Error: malformed UTCTime encoding, "
3835 "4 digits must follow on \'+\' resp. \'-\'";
3838 for (n
=i
+1; n
<i
+5; n
++) {
3839 if ((instr
[n
] < '0') || (instr
[n
] > '9')) {
3840 error_str
= "BER Error: malformed UTCTime encoding, "
3841 "4 digits must follow on \'+\' resp. \'-\'";
3845 snprintf(outstrptr
, 12, " (UTC%c%.4s)", instr
[i
], instr
+i
+1);
3849 error_str
= wmem_strdup_printf(actx
->pinfo
->pool
,
3850 "BER Error: malformed UTCTime encoding, "
3851 "unexpected character in %dth octet, "
3852 "must be \'Z\', \'+\' or \'-\'", i
+1);
3858 error_str
= wmem_strdup_printf(actx
->pinfo
->pool
,
3859 "BER Error: malformed UTCTime encoding, %d unexpected character%s after %dth octet",
3861 (len
== (i
- 1) ? "s" : ""),
3867 *datestrptr
= outstr
; /* mark as valid */
3870 proto_tree_add_string(tree
, hf_id
, tvb
, offset
, len
, outstr
);
3873 if (tvblen
) *tvblen
= len
;
3878 cause
= proto_tree_add_string(tree
, hf_id
, tvb
, offset
, len
, instr
);
3879 error_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3884 proto_tree_add_expert_format(
3885 error_tree
, actx
->pinfo
, &ei_ber_invalid_format_utctime
,
3890 if (tvblen
) *tvblen
= len
;
3895 /* 8.6 Encoding of a bitstring value */
3898 // NOLINTNEXTLINE(misc-no-recursion)
3899 dissect_ber_constrained_bitstring(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, int32_t min_len
, int32_t max_len
, int * const *named_bits
, int num_named_bits
, int hf_id
, int ett_id
, tvbuff_t
**out_tvb
)
3904 int identifier_offset
;
3910 proto_item
*item
= NULL
;
3912 proto_tree
*tree
= NULL
;
3913 /*const char *sep;*/
3916 if (!implicit_tag
) {
3918 /* read header and len for the octet string */
3919 identifier_offset
= offset
;
3920 offset
= dissect_ber_identifier(actx
->pinfo
, parent_tree
, tvb
, offset
, &ber_class
, &pc
, &tag
);
3921 identifier_len
= offset
- identifier_offset
;
3922 offset
= dissect_ber_length(actx
->pinfo
, parent_tree
, tvb
, offset
, &len
, &ind
);
3923 end_offset
= offset
+ len
;
3925 /* sanity check: we only handle Universal BitStrings */
3927 /* for an IMPLICIT APPLICATION tag asn2wrs seems to call this
3928 function with implicit_tag = false. BER_FLAGS_NOOWNTAG was
3929 set so the APPLICATION tag was still present.
3930 So here we relax it for APPLICATION tags. CONTEXT tags may
3931 still cause a problem. */
3933 if (ber_class
!= BER_CLASS_APP
) {
3934 if ((ber_class
!= BER_CLASS_UNI
)
3935 || (tag
!= BER_UNI_TAG_BITSTRING
)) {
3936 tvb_ensure_bytes_exist(tvb
, hoffset
, 2);
3937 cause
= proto_tree_add_expert_format(
3938 parent_tree
, actx
->pinfo
, &ei_ber_expected_bitstring
,
3939 tvb
, identifier_offset
, identifier_len
,
3940 "BER Error: BitString expected but class:%s(%d) %s tag:%d was unexpected",
3941 val_to_str_const(ber_class
, ber_class_codes
, "Unknown"),
3942 ber_class
, tfs_get_string(pc
, &tfs_constructed_primitive
),
3944 if (decode_unexpected
) {
3945 proto_tree
*unknown_tree
= proto_item_add_subtree(cause
, ett_ber_unknown
);
3946 dissect_unknown_ber(actx
->pinfo
, tvb
, hoffset
, unknown_tree
);
3953 len
= tvb_reported_length_remaining(tvb
, offset
);
3954 end_offset
= offset
+ len
;
3956 if ((int)len
<= 0) {
3957 proto_tree_add_expert_format(
3958 parent_tree
, actx
->pinfo
, &ei_ber_constr_bitstr
, tvb
, offset
, len
,
3959 "BER Error: dissect_ber_constrained_bitstring(): frame:%u offset:%d Was passed an illegal length of %d",
3960 actx
->pinfo
->num
, offset
, len
);
3963 actx
->created_item
= NULL
;
3970 pad
= tvb_get_uint8(tvb
, offset
);
3971 /* 8.6.2.4 If a bitstring value has no 1 bits, then an encoder (as a sender's option)
3972 * may encode the value with a length of 1 and with an initial octet set to 0
3973 * or may encode it as a bit string with one or more 0 bits following the initial octet.
3975 if ((pad
== 0) && (len
== 1)) {
3977 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, offset
, len
, ENC_BIG_ENDIAN
);
3978 actx
->created_item
= item
;
3979 proto_tree_add_item(parent_tree
, hf_ber_bitstring_empty
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3981 *out_tvb
= ber_tvb_new_subset_length(tvb
, offset
, len
);
3983 ber_check_length(8 * len
- pad
, min_len
, max_len
, actx
, item
, true);
3987 proto_item
*pad_item
= proto_tree_add_item(parent_tree
, hf_ber_bitstring_padding
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3989 expert_add_info_format(
3990 actx
->pinfo
, pad_item
, &ei_ber_illegal_padding
,
3991 "Illegal padding (0 .. 7): %d", pad
);
3997 item
= proto_tree_add_item(parent_tree
, hf_id
, tvb
, offset
, len
, ENC_NA
);
3998 actx
->created_item
= item
;
4000 uint8_t *bitstring
= (uint8_t *)tvb_memdup(actx
->pinfo
->pool
, tvb
, offset
, len
);
4001 const int named_bits_bytelen
= (num_named_bits
+ 7) / 8;
4002 if (show_internal_ber_fields
) {
4003 if (len
< named_bits_bytelen
) {
4004 unsigned zero_bits_omitted
= num_named_bits
- ((len
* 8) - pad
);
4005 proto_item_append_text(item
, " [%u zero bits not encoded, but displayed]", zero_bits_omitted
);
4009 tree
= proto_item_add_subtree(item
, ett_id
);
4011 for (int i
= 0; i
< named_bits_bytelen
; i
++) {
4012 // Process 8 bits at a time instead of 64, each field masks a
4014 const int bit_offset
= 8 * i
;
4015 int* const* section_named_bits
= named_bits
+ bit_offset
;
4017 if (num_named_bits
- bit_offset
> 8) {
4018 memcpy(&flags
[0], named_bits
+ bit_offset
, 8 * sizeof(int*));
4020 section_named_bits
= (int* const*)flags
;
4023 // If less data is available than the number of named bits, then
4024 // the trailing (right) bits are assumed to be 0.
4027 value
= bitstring
[i
];
4028 if (num_named_bits
- bit_offset
> 7) {
4031 bitstring
[i
] &= 0xff >> (num_named_bits
- bit_offset
);
4035 // TODO should non-zero pad bits be masked from the value?
4036 // When trailing zeroes are not present in the data, mark the
4037 // last byte for the lack of a better alternative.
4038 proto_tree_add_bitmask_list_value(tree
, tvb
, offset
+ MIN(i
, len
- 1), 1, section_named_bits
, value
);
4040 // If more data is available than the number of named bits, then
4041 // either the spec was updated or the packet is malformed.
4042 for (int i
= 0; i
< len
; i
++) {
4044 expert_add_info_format(actx
->pinfo
, item
, &ei_ber_bits_unknown
, "Unknown bit(s): 0x%s",
4045 bytes_to_str(actx
->pinfo
->pool
, bitstring
, len
));
4052 *out_tvb
= ber_tvb_new_subset_length(tvb
, offset
, len
);
4057 if ((pad
> 0) && (pad
< 8) && (len
> 0)) {
4058 uint8_t bits_in_pad
= tvb_get_uint8(tvb
, offset
+ len
- 1) & (0xFF >> (8 - pad
));
4060 expert_add_info_format(
4061 actx
->pinfo
, item
, &ei_ber_bits_set_padded
,
4062 "Bits set in padded area: 0x%02x", bits_in_pad
);
4066 ber_check_length(8 * len
- pad
, min_len
, max_len
, actx
, item
, true);
4073 // NOLINTNEXTLINE(misc-no-recursion)
4074 dissect_ber_bitstring(bool implicit_tag
, asn1_ctx_t
*actx
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, int * const *named_bits
, int num_named_bits
, int hf_id
, int ett_id
, tvbuff_t
**out_tvb
)
4076 return dissect_ber_constrained_bitstring(implicit_tag
, actx
, parent_tree
, tvb
, offset
, -1, -1, named_bits
, num_named_bits
, hf_id
, ett_id
, out_tvb
);
4080 * 8.18 Encoding of a value of the external type
4081 * 8.18.1 The encoding of a value of the external type shall be the BER encoding of the following
4082 * sequence type, assumed to be defined in an environment of EXPLICIT TAGS,
4083 * with a value as specified in the subclauses below:
4085 * [UNIVERSAL 8] IMPLICIT SEQUENCE {
4086 * direct-reference OBJECT IDENTIFIER OPTIONAL,
4087 * indirect-reference INTEGER OPTIONAL,
4088 * data-value-descriptor ObjectDescriptor OPTIONAL,
4090 * single-ASN1-type [0] ABSTRACT-SYNTAX.&Type,
4091 * octet-aligned [1] IMPLICIT OCTET STRING,
4092 * arbitrary [2] IMPLICIT BIT STRING } }
4097 dissect_ber_INTEGER(bool implicit_tag
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
) {
4098 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
4099 &actx
->external
.indirect_reference
);
4100 actx
->external
.indirect_ref_present
= true;
4106 dissect_ber_T_octet_aligned(bool implicit_tag
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
)
4108 if (actx
->external
.u
.ber
.ber_callback
) {
4109 offset
= actx
->external
.u
.ber
.ber_callback(false, tvb
, offset
, actx
, tree
, hf_index
);
4110 } else if (actx
->external
.direct_ref_present
&&
4111 dissector_get_string_handle(ber_oid_dissector_table
, actx
->external
.direct_reference
)) {
4112 offset
= call_ber_oid_callback(actx
->external
.direct_reference
, tvb
, offset
, actx
->pinfo
, tree
, NULL
);
4114 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, &actx
->external
.octet_aligned
);
4120 dissect_ber_OBJECT_IDENTIFIER(bool implicit_tag
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
)
4122 DISSECTOR_ASSERT(actx
);
4123 offset
= dissect_ber_object_identifier_str(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, &actx
->external
.direct_reference
);
4124 actx
->external
.direct_ref_present
= true;
4130 dissect_ber_ObjectDescriptor(bool implicit_tag
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
)
4132 DISSECTOR_ASSERT(actx
);
4133 offset
= dissect_ber_restricted_string(implicit_tag
, BER_UNI_TAG_ObjectDescriptor
,
4134 actx
, tree
, tvb
, offset
, hf_index
,
4135 &actx
->external
.data_value_descriptor
);
4141 dissect_ber_T_single_ASN1_type(bool implicit_tag _U_
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
)
4143 if (actx
->external
.u
.ber
.ber_callback
) {
4144 offset
= actx
->external
.u
.ber
.ber_callback(false, tvb
, offset
, actx
, tree
, hf_index
);
4146 offset
= call_ber_oid_callback(actx
->external
.direct_reference
, tvb
, offset
, actx
->pinfo
, tree
, NULL
);
4153 dissect_ber_T_arbitrary(bool implicit_tag
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
)
4155 if (actx
->external
.u
.ber
.ber_callback
) {
4156 offset
= actx
->external
.u
.ber
.ber_callback(false, tvb
, offset
, actx
, tree
, hf_index
);
4158 offset
= dissect_ber_bitstring(implicit_tag
, actx
, tree
, tvb
, offset
,
4159 NULL
, 0, hf_index
, -1, &actx
->external
.arbitrary
);
4165 static const value_string ber_T_encoding_vals
[] = {
4166 { 0, "single-ASN1-type" },
4167 { 1, "octet-aligned" },
4172 static const ber_choice_t T_encoding_choice
[] = {
4173 { 0, &hf_ber_single_ASN1_type
, BER_CLASS_CON
, 0, 0, dissect_ber_T_single_ASN1_type
},
4174 { 1, &hf_ber_octet_aligned
, BER_CLASS_CON
, 1, BER_FLAGS_IMPLTAG
, dissect_ber_T_octet_aligned
},
4175 { 2, &hf_ber_arbitrary
, BER_CLASS_CON
, 2, BER_FLAGS_IMPLTAG
, dissect_ber_T_arbitrary
},
4176 { 0, NULL
, 0, 0, 0, NULL
}
4181 dissect_ber_T_encoding(bool implicit_tag _U_
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
) {
4182 // This assertion is used to remove clang's warning.
4183 DISSECTOR_ASSERT(actx
);
4184 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
4185 T_encoding_choice
, hf_index
, ett_ber_T_encoding
,
4186 &actx
->external
.encoding
);
4192 static const ber_sequence_t external_U_sequence
[] = {
4193 { &hf_ber_direct_reference
, BER_CLASS_UNI
, BER_UNI_TAG_OID
, BER_FLAGS_OPTIONAL
|BER_FLAGS_NOOWNTAG
, dissect_ber_OBJECT_IDENTIFIER
},
4194 { &hf_ber_indirect_reference
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_OPTIONAL
|BER_FLAGS_NOOWNTAG
, dissect_ber_INTEGER
},
4195 { &hf_ber_data_value_descriptor
, BER_CLASS_UNI
, BER_UNI_TAG_ObjectDescriptor
, BER_FLAGS_OPTIONAL
|BER_FLAGS_NOOWNTAG
, dissect_ber_ObjectDescriptor
},
4196 { &hf_ber_encoding
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
|BER_FLAGS_NOTCHKTAG
, dissect_ber_T_encoding
},
4197 { NULL
, 0, 0, 0, NULL
}
4200 dissect_ber_external_U(bool implicit_tag
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, proto_tree
*tree
, int hf_index
)
4202 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
4203 external_U_sequence
, hf_index
, ett_ber_EXTERNAL
);
4209 dissect_ber_external_type(bool implicit_tag
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, int hf_id
, ber_callback func
) {
4211 actx
->external
.u
.ber
.ber_callback
= func
;
4213 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
4214 hf_id
, BER_CLASS_UNI
, BER_UNI_TAG_EXTERNAL
, true, dissect_ber_external_U
);
4216 asn1_ctx_clean_external(actx
);
4222 dissect_ber_EmbeddedPDV_Type(bool implicit_tag
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, asn1_ctx_t
*actx
, int hf_id
, ber_callback func _U_
) {
4225 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
4226 hf_id
, BER_CLASS_UNI
, BER_UNI_TAG_EMBEDDED_PDV
, true, dissect_ber_external_U
);
4232 dissect_ber_syntax(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
4234 return dissect_unknown_ber(pinfo
, tvb
, 0, tree
);
4238 dissect_ber_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const char *syntax
)
4243 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "BER");
4245 col_set_str(pinfo
->cinfo
, COL_DEF_SRC
, "BER encoded value");
4249 /* if we got here we couldn't find anything better */
4250 col_set_str(pinfo
->cinfo
, COL_INFO
, "Unknown BER");
4252 offset
= dissect_unknown_ber(pinfo
, tvb
, 0, tree
);
4256 offset
= call_ber_syntax_callback(syntax
, tvb
, 0, pinfo
, tree
);
4258 /* see if we have a better name */
4259 name
= get_ber_oid_syntax(syntax
);
4260 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Decoded as %s", name
? name
: syntax
);
4267 dissect_ber(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
4269 return dissect_ber_common(tvb
, pinfo
, tree
, decode_as_syntax
);
4273 dissect_ber_file(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
4275 struct ber_phdr
*ber
= (struct ber_phdr
*)data
;
4277 const char *file_syntax
= NULL
;
4279 if ((ptr
= strrchr(ber
->pathname
, '.')) != NULL
)
4280 file_syntax
= get_ber_oid_syntax(ptr
);
4281 return dissect_ber_common(tvb
, pinfo
, tree
, file_syntax
);
4285 oid_has_dissector(const char *oid
) {
4286 return (dissector_get_string_handle(ber_oid_dissector_table
, oid
) != NULL
);
4292 g_hash_table_destroy(syntax_table
);
4296 proto_register_ber(void)
4298 static hf_register_info hf
[] = {
4299 { &hf_ber_id_class
, {
4300 "Class", "ber.id.class", FT_UINT8
, BASE_DEC
,
4301 VALS(ber_class_codes
), 0xc0, "Class of BER TLV Identifier", HFILL
}},
4302 { &hf_ber_bitstring_padding
, {
4303 "Padding", "ber.bitstring.padding", FT_UINT8
, BASE_DEC
,
4304 NULL
, 0x0, "Number of unused bits in the last octet of the bitstring", HFILL
}},
4305 { &hf_ber_bitstring_empty
, {
4306 "Empty", "ber.bitstring.empty", FT_UINT8
, BASE_DEC
,
4307 NULL
, 0x0, "This is an empty bitstring", HFILL
}},
4309 "P/C", "ber.id.pc", FT_BOOLEAN
, 8,
4310 TFS(&ber_pc_codes
), 0x20, "Primitive or Constructed BER encoding", HFILL
}},
4311 { &hf_ber_id_uni_tag
, {
4312 "Tag", "ber.id.uni_tag", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
,
4313 &ber_uni_tag_codes_ext
, 0x1f, "Universal tag type", HFILL
}},
4314 { &hf_ber_id_uni_tag_ext
, {
4315 "Tag", "ber.id.uni_tag", FT_UINT32
, BASE_DEC
,
4316 NULL
, 0, "Universal tag type", HFILL
}},
4318 "Tag", "ber.id.tag", FT_UINT8
, BASE_DEC
,
4319 NULL
, 0x1f, "Tag value for non-Universal classes", HFILL
}},
4320 { &hf_ber_id_tag_ext
, {
4321 "Tag", "ber.id.tag", FT_UINT32
, BASE_DEC
,
4322 NULL
, 0, "Tag value for non-Universal classes", HFILL
}},
4323 { &hf_ber_length_octets
, {
4324 "Length Octets", "ber.length_octets", FT_UINT8
, BASE_DEC
,
4325 NULL
, 0, "Number of length octets", HFILL
}},
4327 "Length", "ber.length", FT_UINT32
, BASE_DEC
,
4328 NULL
, 0, "Length of contents", HFILL
}},
4329 { &hf_ber_unknown_OCTETSTRING
, {
4330 "OCTETSTRING", "ber.unknown.OCTETSTRING", FT_BYTES
, BASE_NONE
,
4331 NULL
, 0, "This is an unknown OCTETSTRING", HFILL
}},
4332 { &hf_ber_unknown_BER_OCTETSTRING
, {
4333 "OCTETSTRING [BER encoded]", "ber.unknown.OCTETSTRING", FT_NONE
, BASE_NONE
,
4334 NULL
, 0, "This is an BER encoded OCTETSTRING", HFILL
}},
4335 { &hf_ber_unknown_BER_primitive
, {
4336 "Primitive [BER encoded]", "ber.unknown.primitive", FT_NONE
, BASE_NONE
,
4337 NULL
, 0, "This is a BER encoded Primitive", HFILL
}},
4338 { &hf_ber_unknown_OID
, {
4339 "OID", "ber.unknown.OID", FT_OID
, BASE_NONE
,
4340 NULL
, 0, "This is an unknown Object Identifier", HFILL
}},
4341 { &hf_ber_unknown_relative_OID
, {
4342 "OID", "ber.unknown.relative_OID", FT_REL_OID
, BASE_NONE
,
4343 NULL
, 0, "This is an unknown relative Object Identifier", HFILL
}},
4344 { &hf_ber_unknown_GraphicString
, {
4345 "GRAPHICSTRING", "ber.unknown.GRAPHICSTRING", FT_STRING
, BASE_NONE
,
4346 NULL
, 0, "This is an unknown GRAPHICSTRING", HFILL
}},
4347 { &hf_ber_unknown_NumericString
, {
4348 "NumericString", "ber.unknown.NumericString", FT_STRING
, BASE_NONE
,
4349 NULL
, 0, "This is an unknown NumericString", HFILL
}},
4350 { &hf_ber_unknown_PrintableString
, {
4351 "PrintableString", "ber.unknown.PrintableString", FT_STRING
, BASE_NONE
,
4352 NULL
, 0, "This is an unknown PrintableString", HFILL
}},
4353 { &hf_ber_unknown_TeletexString
, {
4354 "TeletexString", "ber.unknown.TeletexString", FT_STRING
, BASE_NONE
,
4355 NULL
, 0, "This is an unknown TeletexString", HFILL
}},
4356 { &hf_ber_unknown_VisibleString
, {
4357 "VisibleString", "ber.unknown.VisibleString", FT_STRING
, BASE_NONE
,
4358 NULL
, 0, "This is an unknown VisibleString", HFILL
}},
4359 { &hf_ber_unknown_GeneralString
, {
4360 "GeneralString", "ber.unknown.GeneralString", FT_STRING
, BASE_NONE
,
4361 NULL
, 0, "This is an unknown GeneralString", HFILL
}},
4362 { &hf_ber_unknown_UniversalString
, {
4363 "UniversalString", "ber.unknown.UniversalString", FT_STRING
, BASE_NONE
,
4364 NULL
, 0, "This is an unknown UniversalString", HFILL
}},
4365 { &hf_ber_unknown_BMPString
, {
4366 "BMPString", "ber.unknown.BMPString", FT_STRING
, BASE_NONE
,
4367 NULL
, 0, "This is an unknown BMPString", HFILL
}},
4368 { &hf_ber_unknown_IA5String
, {
4369 "IA5String", "ber.unknown.IA5String", FT_STRING
, BASE_NONE
,
4370 NULL
, 0, "This is an unknown IA5String", HFILL
}},
4371 { &hf_ber_unknown_UTCTime
, {
4372 "UTCTime", "ber.unknown.UTCTime", FT_STRING
, BASE_NONE
,
4373 NULL
, 0, "This is an unknown UTCTime", HFILL
}},
4374 { &hf_ber_unknown_UTF8String
, {
4375 "UTF8String", "ber.unknown.UTF8String", FT_STRING
, BASE_NONE
,
4376 NULL
, 0, "This is an unknown UTF8String", HFILL
}},
4377 { &hf_ber_unknown_GeneralizedTime
, {
4378 "GeneralizedTime", "ber.unknown.GeneralizedTime", FT_STRING
, BASE_NONE
,
4379 NULL
, 0, "This is an unknown GeneralizedTime", HFILL
}},
4380 { &hf_ber_unknown_INTEGER
, {
4381 "INTEGER", "ber.unknown.INTEGER", FT_INT64
, BASE_DEC
,
4382 NULL
, 0, "This is an unknown INTEGER", HFILL
}},
4383 { &hf_ber_unknown_REAL
, {
4384 "REAL", "ber.unknown.REAL", FT_DOUBLE
, BASE_NONE
,
4385 NULL
, 0, "This is an unknown REAL", HFILL
}},
4386 { &hf_ber_unknown_BITSTRING
, {
4387 "BITSTRING", "ber.unknown.BITSTRING", FT_BYTES
, BASE_NONE
,
4388 NULL
, 0, "This is an unknown BITSTRING", HFILL
}},
4389 { &hf_ber_unknown_BOOLEAN
, {
4390 "BOOLEAN", "ber.unknown.BOOLEAN", FT_UINT8
, BASE_HEX
,
4391 NULL
, 0, "This is an unknown BOOLEAN", HFILL
}},
4392 { &hf_ber_unknown_ENUMERATED
, {
4393 "ENUMERATED", "ber.unknown.ENUMERATED", FT_UINT32
, BASE_DEC
,
4394 NULL
, 0, "This is an unknown ENUMERATED", HFILL
}},
4395 { &hf_ber_direct_reference
,
4396 { "direct-reference", "ber.direct_reference",
4397 FT_OID
, BASE_NONE
, NULL
, 0,
4398 "ber.OBJECT_IDENTIFIER", HFILL
}},
4399 { &hf_ber_indirect_reference
,
4400 { "indirect-reference", "ber.indirect_reference",
4401 FT_INT32
, BASE_DEC
, NULL
, 0,
4402 "ber.INTEGER", HFILL
}},
4403 { &hf_ber_data_value_descriptor
,
4404 { "data-value-descriptor", "ber.data_value_descriptor",
4405 FT_STRING
, BASE_NONE
, NULL
, 0,
4406 "ber.ObjectDescriptor", HFILL
}},
4408 { "encoding", "ber.encoding",
4409 FT_UINT32
, BASE_DEC
, VALS(ber_T_encoding_vals
), 0,
4410 "ber.T_encoding", HFILL
}},
4411 { &hf_ber_octet_aligned
,
4412 { "octet-aligned", "ber.octet_aligned",
4413 FT_BYTES
, BASE_NONE
, NULL
, 0,
4414 "ber.T_octet_aligned", HFILL
}},
4415 { &hf_ber_arbitrary
,
4416 { "arbitrary", "ber.arbitrary",
4417 FT_BYTES
, BASE_NONE
, NULL
, 0,
4418 "ber.T_arbitrary", HFILL
}},
4419 { &hf_ber_single_ASN1_type
,
4420 { "single-ASN1-type", "ber.single_ASN1_type",
4421 FT_NONE
, BASE_NONE
, NULL
, 0,
4422 "ber.T_single_ASN1_type", HFILL
}},
4423 { &hf_ber_extra_data
,
4424 { "Extra data", "ber.extra_data",
4425 FT_BYTES
, BASE_NONE
, NULL
, 0,
4428 /* Fragment entries */
4429 { &hf_ber_fragments
,
4430 { "OCTET STRING fragments", "ber.octet_string.fragments", FT_NONE
, BASE_NONE
,
4431 NULL
, 0x00, NULL
, HFILL
} },
4433 { "OCTET STRING fragment", "ber.octet_string.fragment", FT_FRAMENUM
, BASE_NONE
,
4434 NULL
, 0x00, NULL
, HFILL
} },
4435 { &hf_ber_fragment_overlap
,
4436 { "OCTET STRING fragment overlap", "ber.octet_string.fragment.overlap", FT_BOOLEAN
,
4437 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
4438 { &hf_ber_fragment_overlap_conflicts
,
4439 { "OCTET STRING fragment overlapping with conflicting data",
4440 "ber.octet_string.fragment.overlap.conflicts", FT_BOOLEAN
, BASE_NONE
, NULL
,
4441 0x0, NULL
, HFILL
} },
4442 { &hf_ber_fragment_multiple_tails
,
4443 { "OCTET STRING has multiple tail fragments",
4444 "ber.octet_string.fragment.multiple_tails", FT_BOOLEAN
, BASE_NONE
,
4445 NULL
, 0x0, NULL
, HFILL
} },
4446 { &hf_ber_fragment_too_long_fragment
,
4447 { "OCTET STRING fragment too long", "ber.octet_string.fragment.too_long_fragment",
4448 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
,
4450 { &hf_ber_fragment_error
,
4451 { "OCTET STRING defragmentation error", "ber.octet_string.fragment.error", FT_FRAMENUM
,
4452 BASE_NONE
, NULL
, 0x00, NULL
, HFILL
} },
4453 { &hf_ber_fragment_count
,
4454 { "OCTET STRING fragment count", "ber.octet_string.fragment.count", FT_UINT32
, BASE_DEC
,
4455 NULL
, 0x00, NULL
, HFILL
} },
4456 { &hf_ber_reassembled_in
,
4457 { "Reassembled in", "ber.octet_string.reassembled.in", FT_FRAMENUM
, BASE_NONE
,
4458 NULL
, 0x00, NULL
, HFILL
} },
4459 { &hf_ber_reassembled_length
,
4460 { "Reassembled OCTET STRING length", "ber.octet_string.reassembled.length", FT_UINT32
, BASE_DEC
,
4461 NULL
, 0x00, NULL
, HFILL
} },
4463 /* Generated from convert_proto_tree_add_text.pl */
4464 { &hf_ber_null_tag
, { "NULL tag", "ber.null_tag", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4465 { &hf_ber_unknown_data
, { "Unknown Data", "ber.unknown_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4466 { &hf_ber_unknown_octetstring
, { "Unknown OctetString", "ber.unknown_octetstring", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4467 { &hf_ber_seq_field_eoc
, { "SEQ FIELD EOC", "ber.seq_field_eoc", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4468 { &hf_ber_seq_eoc
, { "SEQ EOC", "ber.seq_eoc", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4469 { &hf_ber_set_field_eoc
, { "SET FIELD EOC", "ber.set_field_eoc", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4470 { &hf_ber_set_eoc
, { "SET EOC", "ber.set_eoc", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4471 { &hf_ber_choice_eoc
, { "CHOICE EOC", "ber.choice_eoc", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4472 { &hf_ber_seq_of_eoc
, { "SEQ OF EOC", "ber.seq_of_eoc", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4473 { &hf_ber_64bit_uint_as_bytes
, { "64bits unsigned integer", "ber.64bit_uint_as_bytes", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4474 { &hf_ber_encoding_boiler_plate
, { "BER encoded protocol, to see BER internal fields set protocol BER preferences", "ber.encoding_boiler_plate", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4477 static int *ett
[] = {
4478 &ett_ber_octet_string
,
4479 &ett_ber_reassembled_octet_string
,
4484 &ett_ber_T_encoding
,
4488 static ei_register_info ei
[] = {
4489 { &ei_ber_size_constraint_string
, { "ber.size_constraint.string", PI_PROTOCOL
, PI_WARN
, "Size constraint: string", EXPFILL
}},
4490 { &ei_ber_size_constraint_value
, { "ber.size_constraint.value", PI_PROTOCOL
, PI_WARN
, "Size constraint: values", EXPFILL
}},
4491 { &ei_ber_size_constraint_items
, { "ber.size_constraint.items", PI_PROTOCOL
, PI_WARN
, "Size constraint: items", EXPFILL
}},
4492 { &ei_ber_sequence_field_wrong
, { "ber.error.sequence.field_wrong", PI_MALFORMED
, PI_WARN
, "BER Error: Wrong field in SEQUENCE", EXPFILL
}},
4493 { &ei_ber_expected_octet_string
, { "ber.error.expected.octet_string", PI_MALFORMED
, PI_WARN
, "BER Error: OctetString expected", EXPFILL
}},
4494 { &ei_ber_expected_null
, { "ber.error.expected.null", PI_MALFORMED
, PI_WARN
, "BER Error: NULL expected", EXPFILL
}},
4495 { &ei_ber_expected_null_zero_length
, { "ber.error.expected.null_zero_length", PI_MALFORMED
, PI_WARN
, "BER Error: NULL type expects zero length data", EXPFILL
}},
4496 { &ei_ber_expected_sequence
, { "ber.error.expected.sequence", PI_MALFORMED
, PI_WARN
, "BER Error: Sequence expected", EXPFILL
}},
4497 { &ei_ber_expected_set
, { "ber.error.expected.set", PI_MALFORMED
, PI_WARN
, "BER Error: SET expected", EXPFILL
}},
4498 { &ei_ber_expected_string
, { "ber.error.expected.string", PI_MALFORMED
, PI_WARN
, "BER Error: String expected", EXPFILL
}},
4499 { &ei_ber_expected_object_identifier
, { "ber.error.expected.object_identifier", PI_MALFORMED
, PI_WARN
, "BER Error: Object Identifier expected", EXPFILL
}},
4500 { &ei_ber_expected_generalized_time
, { "ber.error.expected.generalized_time", PI_MALFORMED
, PI_WARN
, "BER Error: GeneralizedTime expected", EXPFILL
}},
4501 { &ei_ber_expected_utc_time
, { "ber.error.expected.utc_time", PI_MALFORMED
, PI_WARN
, "BER Error: UTCTime expected", EXPFILL
}},
4502 { &ei_ber_expected_bitstring
, { "ber.error.expected.bitstring", PI_MALFORMED
, PI_WARN
, "BER Error: BitString expected", EXPFILL
}},
4503 { &ei_ber_error_length
, { "ber.error.length", PI_MALFORMED
, PI_WARN
, "BER Error: length is not valid", EXPFILL
}},
4504 { &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
}},
4505 { &ei_ber_universal_tag_unknown
, { "ber.error.universal_tag_unknown", PI_MALFORMED
, PI_WARN
, "BER Error: can not handle universal", EXPFILL
}},
4506 { &ei_ber_no_oid
, { "ber.error.no_oid", PI_MALFORMED
, PI_WARN
, "BER Error: No OID supplied to call_ber_oid_callback", EXPFILL
}},
4507 { &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
}},
4508 { &ei_ber_syntax_not_implemented
, { "ber.error.syntax_not_implemented", PI_UNDECODED
, PI_WARN
, "BER: Dissector for syntax not implemented", EXPFILL
}},
4509 { &ei_ber_value_too_many_bytes
, { "ber.error.value_too_many_bytes", PI_MALFORMED
, PI_WARN
, "Value is encoded with too many bytes", EXPFILL
}},
4510 { &ei_ber_unknown_field_sequence
, { "ber.error.unknown_field.sequence", PI_MALFORMED
, PI_WARN
, "BER Error: Unknown field in Sequence", EXPFILL
}},
4511 { &ei_ber_unknown_field_set
, { "ber.error.unknown_field.set", PI_MALFORMED
, PI_WARN
, "BER Error: Unknown field in SET", EXPFILL
}},
4512 { &ei_ber_missing_field_set
, { "ber.error.missing_field.set", PI_MALFORMED
, PI_WARN
, "BER Error: Missing field in SET", EXPFILL
}},
4513 { &ei_ber_empty_choice
, { "ber.error.empty_choice", PI_MALFORMED
, PI_WARN
, "BER Error: Empty choice was found", EXPFILL
}},
4514 { &ei_ber_choice_not_found
, { "ber.error.choice_not_found", PI_MALFORMED
, PI_WARN
, "BER Error: This choice field was not found", EXPFILL
}},
4515 { &ei_ber_bits_unknown
, { "ber.error.bits_unknown", PI_UNDECODED
, PI_WARN
, "BER Error: Bits unknown", EXPFILL
}},
4516 { &ei_ber_bits_set_padded
, { "ber.error.bits_set_padded", PI_UNDECODED
, PI_WARN
, "BER Error: Bits set in padded area", EXPFILL
}},
4517 { &ei_ber_illegal_padding
, { "ber.error.illegal_padding", PI_UNDECODED
, PI_WARN
, "Illegal padding", EXPFILL
}},
4518 { &ei_ber_invalid_format_generalized_time
, { "ber.error.invalid_format.generalized_time", PI_MALFORMED
, PI_WARN
, "BER Error: GeneralizedTime invalid format", EXPFILL
}},
4519 { &ei_ber_invalid_format_utctime
, { "ber.error.invalid_format.utctime", PI_MALFORMED
, PI_WARN
, "BER Error: malformed UTCTime encoding", EXPFILL
}},
4520 { &ei_hf_field_not_integer_type
, { "ber.error.hf_field_not_integer_type", PI_PROTOCOL
, PI_ERROR
, "Was passed a HF field that was not integer type", EXPFILL
}},
4521 { &ei_ber_constr_bitstr
,{ "ber.error.constr_bitstr.len", PI_MALFORMED
, PI_WARN
, "BER Error: malformed Bitstring encoding", EXPFILL
} },
4522 { &ei_ber_real_not_primitive
,{ "ber.error.not_primitive.real", PI_MALFORMED
, PI_WARN
, "BER Error: REAL class not encoded as primitive", EXPFILL
} },
4525 /* Decode As handling */
4526 static build_valid_func ber_da_build_value
[1] = {ber_value
};
4527 static decode_as_value_t ber_da_values
= {ber_prompt
, 1, ber_da_build_value
};
4528 static decode_as_t ber_da
= {"ber", "ber.syntax", 1, 0, &ber_da_values
, NULL
, NULL
,
4529 ber_populate_list
, ber_decode_as_reset
, ber_decode_as_change
, NULL
};
4531 module_t
*ber_module
;
4532 expert_module_t
* expert_ber
;
4533 uat_t
* users_uat
= uat_new("OID Tables",
4539 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
4540 "ChObjectIdentifiers",
4548 proto_ber
= proto_register_protocol("Basic Encoding Rules (ASN.1 X.690)", "BER", "ber");
4550 ber_handle
= register_dissector("ber", dissect_ber
, proto_ber
);
4551 ber_file_handle
= register_dissector("ber_file", dissect_ber_file
, proto_ber
);
4553 proto_register_field_array(proto_ber
, hf
, array_length(hf
));
4554 proto_register_subtree_array(ett
, array_length(ett
));
4555 expert_ber
= expert_register_protocol(proto_ber
);
4556 expert_register_field_array(expert_ber
, ei
, array_length(ei
));
4558 proto_set_cant_toggle(proto_ber
);
4560 /* Register preferences */
4561 ber_module
= prefs_register_protocol(proto_ber
, NULL
);
4563 prefs_register_bool_preference(ber_module
, "show_internals",
4564 "Show internal BER encapsulation tokens",
4565 "Whether the dissector should also display internal"
4566 " ASN.1 BER details such as Identifier and Length fields", &show_internal_ber_fields
);
4567 prefs_register_bool_preference(ber_module
, "decode_unexpected",
4568 "Decode unexpected tags as BER encoded data",
4569 "Whether the dissector should decode unexpected tags as"
4570 " ASN.1 BER encoded data", &decode_unexpected
);
4571 prefs_register_bool_preference(ber_module
, "decode_octetstring",
4572 "Decode OCTET STRING as BER encoded data",
4573 "Whether the dissector should try decoding OCTET STRINGs as"
4574 " constructed ASN.1 BER encoded data", &decode_octetstring_as_ber
);
4576 prefs_register_bool_preference(ber_module
, "decode_primitive",
4577 "Decode Primitive as BER encoded data",
4578 "Whether the dissector should try decoding unknown primitive as"
4579 " constructed ASN.1 BER encoded data", &decode_primitive_as_ber
);
4581 prefs_register_bool_preference(ber_module
, "warn_too_many_bytes",
4582 "Warn if too many leading zero bits in encoded data",
4583 "Whether the dissector should warn if excessive leading zero (0) bits",
4584 &decode_warning_leading_zero_bits
);
4586 prefs_register_uat_preference(ber_module
, "oid_table", "Object Identifiers",
4587 "A table that provides names for object identifiers"
4588 " and the syntax of any associated values",
4591 ber_oid_dissector_table
= register_dissector_table("ber.oid", "BER OID", proto_ber
, FT_STRING
, STRING_CASE_SENSITIVE
);
4592 ber_syntax_dissector_table
= register_dissector_table("ber.syntax", "BER syntax", proto_ber
, FT_STRING
, STRING_CASE_SENSITIVE
);
4593 syntax_table
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
, g_free
); /* oid to syntax */
4595 register_ber_syntax_dissector("ASN.1", proto_ber
, dissect_ber_syntax
);
4597 reassembly_table_register(&octet_segment_reassembly_table
,
4598 &addresses_reassembly_table_functions
);
4600 register_shutdown_routine(ber_shutdown
);
4602 register_decode_as(&ber_da
);
4606 proto_reg_handoff_ber(void)
4610 oid_add_from_string("asn1", "2.1");
4611 oid_add_from_string("basic-encoding", "2.1.1");
4613 ber_decode_as_foreach(ber_add_syntax_name
, &i
);
4616 qsort(&syntax_names
[1], i
- 1, sizeof(value_string
), cmp_value_string
);
4617 syntax_names
[i
].value
= 0;
4618 syntax_names
[i
].strptr
= NULL
;
4620 /* allow the dissection of BER/DER carried over a TCP/UDP transport
4621 by using "Decode As..." */
4622 dissector_add_for_decode_as_with_preference("tcp.port", ber_handle
);
4623 dissector_add_for_decode_as_with_preference("udp.port", ber_handle
);
4627 dissector_add_uint("wtap_encap", WTAP_ENCAP_BER
, ber_file_handle
);
4629 dissector_add_string("media_type.suffix", "ber", ber_handle
); /* RFC 6839 */
4630 dissector_add_string("media_type.suffix", "der", ber_handle
); /* RFC 6839 */
4634 * Editor modelines - https://www.wireshark.org/tools/modelines.html
4639 * indent-tabs-mode: nil
4642 * vi: set shiftwidth=4 tabstop=8 expandtab:
4643 * :indentSize=4:tabSize=8:noTabs=true: