1 /* packet-ber.c
2  * Helpers for ASN.1/BER dissection
3  * Ronnie Sahlberg (C) 2004
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11 
12 /*
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)
16  *
17  */
18 /* TODO: change #.REGISTER signature to dissector_t and
19  * update call_ber_oid_callback() accordingly.
20  *
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.
25  *
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.
29  *
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
34  * CHOICE.
35  *
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.
42  */
43 
44 //#define DEBUG_BER 1
45 
46 #include "config.h"
47 
48 #include <stdio.h>
49 
50 #include <epan/packet.h>
51 #include <epan/exceptions.h>
52 #include <epan/reassemble.h>
53 #include <epan/oids.h>
54 #include <epan/expert.h>
55 #include <epan/uat.h>
56 #include <epan/decode_as.h>
57 #include <wiretap/wtap.h>
58 #ifdef DEBUG_BER
59 #include <epan/ws_printf.h>
60 #endif
61 
62 #include "packet-ber.h"
63 
64 /*
65  * Set a limit on recursion so we don't blow away the stack. Another approach
66  * would be to remove recursion completely but then we'd exhaust CPU+memory
67  * trying to read a hellabyte of nested indefinite lengths.
68 
69  * XXX - Max nesting in the ASN.1 plugin is 32. Should they match?
70  */
71 #define BER_MAX_NESTING 500
72 
73 void proto_register_ber(void);
74 void proto_reg_handoff_ber(void);
75 
76 static gint proto_ber = -1;
77 static gint hf_ber_id_class = -1;
78 static gint hf_ber_id_pc = -1;
79 static gint hf_ber_id_uni_tag = -1;
80 static gint hf_ber_id_uni_tag_ext = -1;
81 static gint hf_ber_id_tag = -1;
82 static gint hf_ber_id_tag_ext = -1;
83 static gint hf_ber_length = -1;
84 static gint hf_ber_bitstring_padding = -1;
85 static gint hf_ber_bitstring_empty = -1;
86 static gint hf_ber_unknown_OID = -1;
87 static gint hf_ber_unknown_relative_OID = -1;
88 static gint hf_ber_unknown_BOOLEAN = -1;
89 static gint hf_ber_unknown_OCTETSTRING = -1;
90 static gint hf_ber_unknown_BER_OCTETSTRING = -1;
91 static gint hf_ber_unknown_BER_primitive = -1;
92 static gint hf_ber_unknown_GraphicString = -1;
93 static gint hf_ber_unknown_NumericString = -1;
94 static gint hf_ber_unknown_PrintableString = -1;
95 static gint hf_ber_unknown_TeletexString = -1;
96 static gint hf_ber_unknown_VisibleString = -1;
97 static gint hf_ber_unknown_GeneralString = -1;
98 static gint hf_ber_unknown_UniversalString = -1;
99 static gint hf_ber_unknown_BMPString = -1;
100 static gint hf_ber_unknown_IA5String = -1;
101 static gint hf_ber_unknown_UTCTime = -1;
102 static gint hf_ber_unknown_UTF8String = -1;
103 static gint hf_ber_unknown_GeneralizedTime = -1;
104 static gint hf_ber_unknown_INTEGER = -1;
105 static gint hf_ber_unknown_REAL = -1;
106 static gint hf_ber_unknown_BITSTRING = -1;
107 static gint hf_ber_unknown_ENUMERATED = -1;
108 static gint hf_ber_direct_reference = -1;         /* OBJECT_IDENTIFIER */
109 static gint hf_ber_indirect_reference = -1;       /* INTEGER */
110 static gint hf_ber_data_value_descriptor = -1;    /* ObjectDescriptor */
111 static gint hf_ber_encoding = -1;                 /* T_encoding */
112 static gint hf_ber_single_ASN1_type = -1;         /* T_single_ASN1_type */
113 static gint hf_ber_octet_aligned = -1;            /* OCTET_STRING */
114 static gint hf_ber_arbitrary = -1;                /* BIT_STRING */
115 static gint hf_ber_extra_data = -1;
116 
117 /* Generated from convert_proto_tree_add_text.pl */
118 static int hf_ber_seq_of_eoc = -1;
119 static int hf_ber_64bit_uint_as_bytes = -1;
120 static int hf_ber_choice_eoc = -1;
121 static int hf_ber_seq_field_eoc = -1;
122 static int hf_ber_seq_eoc = -1;
123 static int hf_ber_set_field_eoc = -1;
124 static int hf_ber_set_eoc = -1;
125 static int hf_ber_null_tag = -1;
126 static int hf_ber_unknown_octetstring = -1;
127 static int hf_ber_unknown_data = -1;
128 
129 static int hf_ber_fragments = -1;
130 static int hf_ber_fragment = -1;
131 static int hf_ber_fragment_overlap = -1;
132 static int hf_ber_fragment_overlap_conflicts = -1;
133 static int hf_ber_fragment_multiple_tails = -1;
134 static int hf_ber_fragment_too_long_fragment = -1;
135 static int hf_ber_fragment_error = -1;
136 static int hf_ber_fragment_count = -1;
137 static int hf_ber_reassembled_in = -1;
138 static int hf_ber_reassembled_length = -1;
139 
140 static gint ett_ber_octet_string = -1;
141 static gint ett_ber_reassembled_octet_string = -1;
142 static gint ett_ber_primitive = -1;
143 static gint ett_ber_unknown = -1;
144 static gint ett_ber_SEQUENCE = -1;
145 static gint ett_ber_EXTERNAL = -1;
146 static gint ett_ber_T_encoding = -1;
147 static gint ett_ber_fragment = -1;
148 static gint ett_ber_fragments = -1;
149 
150 static expert_field ei_ber_size_constraint_string = EI_INIT;
151 static expert_field ei_ber_size_constraint_value = EI_INIT;
152 static expert_field ei_ber_size_constraint_items = EI_INIT;
153 static expert_field ei_ber_sequence_field_wrong = EI_INIT;
154 static expert_field ei_ber_expected_octet_string = EI_INIT;
155 static expert_field ei_ber_expected_null = EI_INIT;
156 static expert_field ei_ber_expected_null_zero_length = EI_INIT;
157 static expert_field ei_ber_expected_sequence = EI_INIT;
158 static expert_field ei_ber_expected_set = EI_INIT;
159 static expert_field ei_ber_expected_string = EI_INIT;
160 static expert_field ei_ber_expected_object_identifier = EI_INIT;
161 static expert_field ei_ber_expected_generalized_time = EI_INIT;
162 static expert_field ei_ber_expected_utc_time = EI_INIT;
163 static expert_field ei_ber_expected_bitstring = EI_INIT;
164 static expert_field ei_ber_error_length = EI_INIT;
165 static expert_field ei_ber_wrong_tag_in_tagged_type = EI_INIT;
166 static expert_field ei_ber_universal_tag_unknown = EI_INIT;
167 static expert_field ei_ber_no_oid = EI_INIT;
168 static expert_field ei_ber_syntax_not_implemented = EI_INIT;
169 static expert_field ei_ber_oid_not_implemented = EI_INIT;
170 static expert_field ei_ber_value_too_many_bytes = EI_INIT;
171 static expert_field ei_ber_unknown_field_sequence = EI_INIT;
172 static expert_field ei_ber_unknown_field_set = EI_INIT;
173 static expert_field ei_ber_missing_field_set = EI_INIT;
174 static expert_field ei_ber_empty_choice = EI_INIT;
175 static expert_field ei_ber_choice_not_found = EI_INIT;
176 static expert_field ei_ber_bits_unknown = EI_INIT;
177 static expert_field ei_ber_bits_set_padded = EI_INIT;
178 static expert_field ei_ber_illegal_padding = EI_INIT;
179 static expert_field ei_ber_invalid_format_generalized_time = EI_INIT;
180 static expert_field ei_ber_invalid_format_utctime = EI_INIT;
181 static expert_field ei_hf_field_not_integer_type = EI_INIT;
182 static expert_field ei_ber_constr_bitstr = EI_INIT;
183 static expert_field ei_ber_real_not_primitive = EI_INIT;
184 
185 static dissector_handle_t ber_handle;
186 
187 static gboolean show_internal_ber_fields         = FALSE;
188 static gboolean decode_octetstring_as_ber        = FALSE;
189 static gboolean decode_primitive_as_ber          = FALSE;
190 static gboolean decode_unexpected                = FALSE;
191 static gboolean decode_warning_leading_zero_bits = FALSE;
192 
193 static gchar *decode_as_syntax = NULL;
194 
195 static dissector_table_t ber_oid_dissector_table    = NULL;
196 static dissector_table_t ber_syntax_dissector_table = NULL;
197 
198 static GHashTable *syntax_table = NULL;
199 
200 static gint8    last_class;
201 static gboolean last_pc;
202 static gint32   last_tag;
203 static guint32  last_length;
204 static tvbuff_t *last_length_tvb;
205 static int      last_length_offset;
206 static int      last_length_len;
207 static gboolean last_ind;
208 
209 static const value_string ber_class_codes[] = {
210     { BER_CLASS_UNI,    "UNIVERSAL" },
211     { BER_CLASS_APP,    "APPLICATION" },
212     { BER_CLASS_CON,    "CONTEXT" },
213     { BER_CLASS_PRI,    "PRIVATE" },
214     { 0, NULL }
215 };
216 
217 static const true_false_string ber_pc_codes = {
218     "Constructed Encoding",
219     "Primitive Encoding"
220 };
221 
222 
223 static const value_string ber_uni_tag_codes[] = {
224     { BER_UNI_TAG_EOC,              "'end-of-content'" },
225     { BER_UNI_TAG_BOOLEAN,          "BOOLEAN" },
226     { BER_UNI_TAG_INTEGER,          "INTEGER" },
227     { BER_UNI_TAG_BITSTRING,        "BIT STRING" },
228     { BER_UNI_TAG_OCTETSTRING,      "OCTET STRING" },
229     { BER_UNI_TAG_NULL,             "NULL" },
230     { BER_UNI_TAG_OID,              "OBJECT IDENTIFIER" },
231     { BER_UNI_TAG_ObjectDescriptor, "ObjectDescriptor" },
232     { BER_UNI_TAG_EXTERNAL,         "EXTERNAL" },
233     { BER_UNI_TAG_REAL,             "REAL" },
234     { BER_UNI_TAG_ENUMERATED,       "ENUMERATED" },
235     { BER_UNI_TAG_EMBEDDED_PDV,     "EMBEDDED PDV" },
236     { BER_UNI_TAG_UTF8String,       "UTF8String" },
237     { BER_UNI_TAG_RELATIVE_OID,     "RELATIVE-OID" },
238     /* UNIVERSAL 14-15
239      * Reserved for future editions of this
240      * Recommendation | International Standard
241      */
242     {  14,      "Reserved for future editions" },
243     {  15 ,     "Reserved for future editions" },
244 
245     { BER_UNI_TAG_SEQUENCE,         "SEQUENCE" },
246     { BER_UNI_TAG_SET,              "SET" },
247     { BER_UNI_TAG_NumericString,    "NumericString" },
248     { BER_UNI_TAG_PrintableString,  "PrintableString" },
249     { BER_UNI_TAG_TeletexString,    "TeletexString, T61String" },
250     { BER_UNI_TAG_VideotexString,   "VideotexString" },
251     { BER_UNI_TAG_IA5String,        "IA5String" },
252     { BER_UNI_TAG_UTCTime,          "UTCTime" },
253     { BER_UNI_TAG_GeneralizedTime,  "GeneralizedTime" },
254     { BER_UNI_TAG_GraphicString,    "GraphicString" },
255     { BER_UNI_TAG_VisibleString,    "VisibleString, ISO64String" },
256     { BER_UNI_TAG_GeneralString,    "GeneralString" },
257     { BER_UNI_TAG_UniversalString,  "UniversalString" },
258     { BER_UNI_TAG_CHARACTERSTRING,  "CHARACTER STRING" },
259     { BER_UNI_TAG_BMPString,        "BMPString" },
260     { 31,                           "Continued" },
261     { 0, NULL }
262 };
263 static value_string_ext ber_uni_tag_codes_ext = VALUE_STRING_EXT_INIT(ber_uni_tag_codes);
264 
265 #if 0
266 static const true_false_string ber_real_binary_vals = {
267     "Binary encoding",
268     "Decimal encoding"
269 };
270 
271 static const true_false_string ber_real_decimal_vals = {
272     "SpecialRealValue",
273     "Decimal encoding"
274 };
275 #endif
276 
277 typedef struct _da_data {
278     GHFunc   func;
279     gpointer user_data;
280 } da_data;
281 
282 typedef struct _oid_user_t {
283     char *oid;
284     char *name;
285     char *syntax;
286 } oid_user_t;
287 
288 UAT_CSTRING_CB_DEF(oid_users, oid, oid_user_t)
289 UAT_CSTRING_CB_DEF(oid_users, name, oid_user_t)
290 UAT_VS_CSTRING_DEF(oid_users, syntax, oid_user_t, 0, "")
291 
292 static oid_user_t *oid_users;
293 static guint num_oid_users;
294 
295 #define MAX_SYNTAX_NAMES 128
296 /* Define non_const_value_string as a hack to prevent chackAPIs.pl from complaining */
297 #define non_const_value_string value_string
298 static non_const_value_string syntax_names[MAX_SYNTAX_NAMES+1] = {
299     {0, ""},
300     {0, NULL}
301 };
302 
303 static const fragment_items octet_string_frag_items = {
304     /* Fragment subtrees */
305     &ett_ber_fragment,
306     &ett_ber_fragments,
307     /* Fragment fields */
308     &hf_ber_fragments,
309     &hf_ber_fragment,
310     &hf_ber_fragment_overlap,
311     &hf_ber_fragment_overlap_conflicts,
312     &hf_ber_fragment_multiple_tails,
313     &hf_ber_fragment_too_long_fragment,
314     &hf_ber_fragment_error,
315     &hf_ber_fragment_count,
316     /* Reassembled in field */
317     &hf_ber_reassembled_in,
318     /* Reassembled length field */
319     &hf_ber_reassembled_length,
320     /* Reassembled data field */
321     NULL,
322     /* Tag */
323     "OCTET STRING fragments"
324 };
325 
326 static void *
oid_copy_cb(void * dest,const void * orig,size_t len _U_)327 oid_copy_cb(void *dest, const void *orig, size_t len _U_)
328 {
329     oid_user_t       *u = (oid_user_t *)dest;
330     const oid_user_t *o = (const oid_user_t *)orig;
331 
332     u->oid = g_strdup(o->oid);
333     u->name = g_strdup(o->name);
334     u->syntax = o->syntax;
335 
336     return dest;
337 }
338 
339 static void
oid_free_cb(void * r)340 oid_free_cb(void *r)
341 {
342     oid_user_t *u = (oid_user_t *)r;
343 
344     g_free(u->oid);
345     g_free(u->name);
346 }
347 
348 static int
cmp_value_string(const void * v1,const void * v2)349 cmp_value_string(const void *v1, const void *v2)
350 {
351     const value_string *vs1 = (const value_string *)v1;
352     const value_string *vs2 = (const value_string *)v2;
353 
354     return strcmp(vs1->strptr, vs2->strptr);
355 }
356 
357 static uat_field_t users_flds[] = {
358     UAT_FLD_OID(oid_users, oid, "OID", "Object Identifier"),
359     UAT_FLD_CSTRING(oid_users, name, "Name", "Human readable name for the OID"),
360     UAT_FLD_VS(oid_users, syntax, "Syntax", syntax_names, "Syntax of values associated with the OID"),
361     UAT_END_FIELDS
362 };
363 
364 
ber_prompt(packet_info * pinfo _U_,gchar * result)365 static void ber_prompt(packet_info *pinfo _U_, gchar* result)
366 {
367     g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Decode ASN.1 file as");
368 }
369 
ber_value(packet_info * pinfo _U_)370 static gpointer ber_value(packet_info *pinfo _U_)
371 {
372     /* Not used */
373     return NULL;
374 }
375 
376 struct ber_decode_as_populate
377 {
378     decode_as_add_to_list_func add_to_list;
379     gpointer ui_element;
380 };
381 
382 static void
decode_ber_add_to_list(gpointer key,gpointer value,gpointer user_data)383 decode_ber_add_to_list(gpointer key, gpointer value, gpointer user_data)
384 {
385     struct ber_decode_as_populate* populate = (struct ber_decode_as_populate*)user_data;
386     populate->add_to_list("ASN.1", (gchar *)key, value, populate->ui_element);
387 }
388 
ber_populate_list(const gchar * table_name _U_,decode_as_add_to_list_func add_to_list,gpointer ui_element)389 static void ber_populate_list(const gchar *table_name _U_, decode_as_add_to_list_func add_to_list, gpointer ui_element)
390 {
391     struct ber_decode_as_populate populate;
392 
393     populate.add_to_list = add_to_list;
394     populate.ui_element = ui_element;
395 
396     ber_decode_as_foreach(decode_ber_add_to_list, &populate);
397 }
398 
ber_decode_as_reset(const char * name _U_,gconstpointer pattern _U_)399 static gboolean ber_decode_as_reset(const char *name _U_, gconstpointer pattern _U_)
400 {
401     g_free(decode_as_syntax);
402     decode_as_syntax = NULL;
403     return FALSE;
404 }
405 
ber_decode_as_change(const char * name _U_,gconstpointer pattern _U_,gconstpointer handle _U_,const gchar * list_name)406 static gboolean ber_decode_as_change(const char *name _U_, gconstpointer pattern _U_, gconstpointer handle _U_, const gchar* list_name)
407 {
408     g_free(decode_as_syntax);
409     decode_as_syntax = g_strdup(list_name);
410     return FALSE;
411 }
412 
413 int
dissect_ber_oid_NULL_callback(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree _U_,void * data _U_)414 dissect_ber_oid_NULL_callback(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_, void* data _U_)
415 {
416     return tvb_captured_length(tvb);
417 }
418 
419 
420 void
register_ber_oid_dissector_handle(const char * oid,dissector_handle_t dissector,int proto _U_,const char * name)421 register_ber_oid_dissector_handle(const char *oid, dissector_handle_t dissector, int proto _U_, const char *name)
422 {
423     dissector_add_string("ber.oid", oid, dissector);
424     oid_add_from_string(name, oid);
425 }
426 
427 void
register_ber_oid_dissector(const char * oid,dissector_t dissector,int proto,const char * name)428 register_ber_oid_dissector(const char *oid, dissector_t dissector, int proto, const char *name)
429 {
430     dissector_handle_t dissector_handle;
431 
432     dissector_handle = create_dissector_handle(dissector, proto);
433     dissector_add_string("ber.oid", oid, dissector_handle);
434     oid_add_from_string(name, oid);
435 }
436 
437 void
register_ber_syntax_dissector(const char * syntax,int proto,dissector_t dissector)438 register_ber_syntax_dissector(const char *syntax, int proto, dissector_t dissector)
439 {
440     dissector_handle_t dissector_handle;
441 
442     dissector_handle = create_dissector_handle(dissector, proto);
443     dissector_add_string("ber.syntax", syntax, dissector_handle);
444 
445 }
446 
447 void
register_ber_oid_syntax(const char * oid,const char * name,const char * syntax)448 register_ber_oid_syntax(const char *oid, const char *name, const char *syntax)
449 {
450 
451     if (syntax && *syntax)
452         g_hash_table_insert(syntax_table, (gpointer)g_strdup(oid), (gpointer)g_strdup(syntax));
453 
454     if (name && *name)
455         register_ber_oid_name(oid, name);
456 }
457 
458 /* Register the oid name to get translation in proto dissection */
459 void
register_ber_oid_name(const char * oid,const char * name)460 register_ber_oid_name(const char *oid, const char *name)
461 {
462     oid_add_from_string(name, oid);
463 }
464 
465 static void
ber_add_syntax_name(gpointer key,gpointer value _U_,gpointer user_data)466 ber_add_syntax_name(gpointer key, gpointer value _U_, gpointer user_data)
467 {
468     guint *i = (guint*)user_data;
469 
470     if (*i < MAX_SYNTAX_NAMES) {
471         syntax_names[*i].value = *i;
472         syntax_names[*i].strptr = (const gchar*)key;
473 
474         (*i)++;
475     }
476 
477 }
478 
479 static void
ber_decode_as_dt(const gchar * table_name _U_,ftenum_t selector_type _U_,gpointer key,gpointer value,gpointer user_data)480 ber_decode_as_dt(const gchar *table_name _U_, ftenum_t selector_type _U_, gpointer key, gpointer value, gpointer user_data)
481 {
482     da_data *decode_as_data;
483 
484     decode_as_data = (da_data *)user_data;
485 
486     decode_as_data->func(key, value, decode_as_data->user_data);
487 }
488 
489 void
ber_decode_as_foreach(GHFunc func,gpointer user_data)490 ber_decode_as_foreach(GHFunc func, gpointer user_data)
491 {
492     da_data decode_as_data;
493 
494     decode_as_data.func = func;
495     decode_as_data.user_data = user_data;
496 
497     dissector_table_foreach("ber.syntax",  ber_decode_as_dt, &decode_as_data);
498 
499 }
500 
501 /* Get oid syntax from hash table to get translation in proto dissection(packet-per.c) */
502 static const gchar *
get_ber_oid_syntax(const char * oid)503 get_ber_oid_syntax(const char *oid)
504 {
505     return (const char *)g_hash_table_lookup(syntax_table, oid);
506 }
507 
508 static void
ber_update_oids(void)509 ber_update_oids(void)
510 {
511     guint i;
512 
513     for (i = 0; i < num_oid_users; i++)
514         register_ber_oid_syntax(oid_users[i].oid, oid_users[i].name, oid_users[i].syntax);
515 }
516 
517 static void
ber_check_length(guint32 length,gint32 min_len,gint32 max_len,asn1_ctx_t * actx,proto_item * item,gboolean bit)518 ber_check_length (guint32 length, gint32 min_len, gint32 max_len, asn1_ctx_t *actx, proto_item *item, gboolean bit)
519 {
520     if ((min_len != -1) && (length < (guint32)min_len)) {
521         expert_add_info_format(
522             actx->pinfo, item, &ei_ber_size_constraint_string,
523             "Size constraint: %sstring too short: %d (%d .. %d)",
524             bit ? "bit " : "", length, min_len, max_len);
525     } else if ((max_len != -1) && (length > (guint32)max_len)) {
526         expert_add_info_format(
527             actx->pinfo, item, &ei_ber_size_constraint_string,
528             "Size constraint: %sstring too long: %d (%d .. %d)",
529             bit ? "bit " : "", length, min_len, max_len);
530     }
531 }
532 
533 static void
ber_check_value64(gint64 value,gint64 min_len,gint64 max_len,asn1_ctx_t * actx,proto_item * item)534 ber_check_value64 (gint64 value, gint64 min_len, gint64 max_len, asn1_ctx_t *actx, proto_item *item)
535 {
536     if ((min_len != -1) && (value < min_len)) {
537         expert_add_info_format(
538             actx->pinfo, item, &ei_ber_size_constraint_value,
539             "Size constraint: value too small: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "d .. %" G_GINT64_MODIFIER "d)",
540             value, min_len, max_len);
541     } else if ((max_len != -1) && (value > max_len)) {
542         expert_add_info_format(
543             actx->pinfo, item, &ei_ber_size_constraint_value,
544             "Size constraint: value too big: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "d .. %" G_GINT64_MODIFIER "d)",
545             value, min_len, max_len);
546     }
547 }
548 
549 static void
ber_check_value(guint32 value,gint32 min_len,gint32 max_len,asn1_ctx_t * actx,proto_item * item)550 ber_check_value (guint32 value, gint32 min_len, gint32 max_len, asn1_ctx_t *actx, proto_item *item)
551 {
552     if ((min_len != -1) && (value < (guint32)min_len)) {
553         expert_add_info_format(
554             actx->pinfo, item, &ei_ber_size_constraint_value,
555             "Size constraint: value too small: %d (%d .. %d)",
556             value, min_len, max_len);
557     } else if ((max_len != -1) && (value > (guint32)max_len)) {
558         expert_add_info_format(
559             actx->pinfo, item, &ei_ber_size_constraint_value,
560             "Size constraint: value too big: %d (%d .. %d)",
561             value, min_len, max_len);
562     }
563 }
564 
565 static void
ber_check_items(int cnt,gint32 min_len,gint32 max_len,asn1_ctx_t * actx,proto_item * item)566 ber_check_items (int cnt, gint32 min_len, gint32 max_len, asn1_ctx_t *actx, proto_item *item)
567 {
568     if ((min_len != -1) && (cnt < min_len)) {
569         expert_add_info_format(
570             actx->pinfo, item, &ei_ber_size_constraint_items,
571             "Size constraint: too few items: %d (%d .. %d)",
572             cnt, min_len, max_len);
573     } else if ((max_len != -1) && (cnt > max_len)) {
574         expert_add_info_format(
575             actx->pinfo, item, &ei_ber_size_constraint_items,
576             "Size constraint: too many items: %d (%d .. %d)",
577             cnt, min_len, max_len);
578     }
579 }
580 
581 /*
582  * XXX - if the specified length is less than the remaining length
583  * of data in the tvbuff, either 1) the specified length is bad and
584  * we should report that with an expert info or 2) the tvbuff is
585  * unreassembled and we should make the new tvbuff also be an
586  * unreassembled tvbuff.
587  */
588 static tvbuff_t *
ber_tvb_new_subset_length(tvbuff_t * tvb,const gint backing_offset,const gint backing_length)589 ber_tvb_new_subset_length(tvbuff_t *tvb, const gint backing_offset, const gint backing_length)
590 {
591     gint length_remaining;
592 
593     length_remaining = tvb_reported_length_remaining(tvb, backing_offset);
594     return tvb_new_subset_length(tvb, backing_offset, (length_remaining > backing_length) ? backing_length : length_remaining);
595 }
596 
597 int
dissect_ber_tagged_type(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,gint8 tag_cls,gint32 tag_tag,gboolean tag_impl,ber_type_fn type)598 dissect_ber_tagged_type(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gint8 tag_cls, gint32 tag_tag, gboolean tag_impl, ber_type_fn type)
599 {
600     gint8       tmp_cls;
601     gint32      tmp_tag;
602     int         identifier_offset;
603     int         identifier_len;
604     guint32     tmp_len;
605     tvbuff_t   *next_tvb = tvb;
606 
607 #ifdef DEBUG_BER
608 {
609 const char *name;
610 header_field_info *hfinfo;
611 if (hf_id >= 0) {
612 hfinfo = proto_registrar_get_nth(hf_id);
613 name = hfinfo->name;
614 } else {
615 name = "unnamed";
616 }
617 if (tvb_reported_length_remaining(tvb, offset) > 3) {
618 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_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
619 } else {
620 proto_tree_add_debug_text(tree, "dissect_ber_tagged_type(%s) entered\n", name);
621 }
622 }
623 #endif
624 
625     if (implicit_tag) {
626         offset = type(tag_impl, tvb, offset, actx, tree, hf_id);
627         return offset;
628     }
629 
630     identifier_offset = offset;
631     offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &tmp_cls, NULL, &tmp_tag);
632     identifier_len = offset - identifier_offset;
633     offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &tmp_len, NULL);
634 
635     if ((tmp_cls != tag_cls) || (tmp_tag != tag_tag)) {
636         proto_tree_add_expert_format(
637             tree, actx->pinfo, &ei_ber_wrong_tag_in_tagged_type,
638             tvb, identifier_offset, identifier_len,
639             "BER Error: Wrong tag in tagged type - expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
640             val_to_str_const(tag_cls, ber_class_codes, "Unknown"),
641             tag_cls,
642             tag_tag,
643             val_to_str_ext_const(tag_tag, &ber_uni_tag_codes_ext, "Unknown"),
644             val_to_str_const(tmp_cls, ber_class_codes, "Unknown"),
645             tmp_cls,
646             tmp_tag);
647     }
648 
649     if (tag_impl) {
650         next_tvb = ber_tvb_new_subset_length(tvb, offset, tmp_len);
651         type(tag_impl, next_tvb, 0, actx, tree, hf_id);
652         offset += tmp_len;
653     } else {
654         offset = type(tag_impl, tvb, offset, actx, tree, hf_id);
655     }
656 
657     return offset;
658 }
659 
660 /*
661  * Add a "length bogus" error.
662  */
663 static proto_item *
ber_add_bad_length_error(packet_info * pinfo,proto_tree * tree,const char * name,tvbuff_t * tvb,const gint start,gint length)664 ber_add_bad_length_error(packet_info *pinfo, proto_tree *tree,
665                          const char *name, tvbuff_t *tvb, const gint start,
666                          gint length)
667 {
668     proto_item *ti;
669 
670     ti = proto_tree_add_expert_format(
671         tree, pinfo, &ei_ber_error_length, tvb, start, length,
672         "BER Error: %s: length of item (%d) is not valid",
673         name, length);
674     return ti;
675 }
676 
677 /*
678  * Add an "exceeds tvb length" error.
679  */
680 static void
ber_add_large_length_error(packet_info * pinfo,proto_tree * tree,tvbuff_t * tvb,int offset,int length,tvbuff_t * len_tvb,const gint len_offset,const guint32 len_length)681 ber_add_large_length_error(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
682                          int offset, int length, tvbuff_t *len_tvb,
683                          const gint len_offset, const guint32 len_length)
684 {
685     proto_tree_add_expert_format(
686         tree, pinfo, &ei_ber_error_length, len_tvb, len_offset, len_length,
687         "BER Error: length %u longer than tvb_reported_length_remaining: %d",
688         length,
689         tvb_reported_length_remaining(tvb, offset));
690 }
691 
692 /*
693  * Like proto_tree_add_item(), but checks whether the length of the item
694  * being added is appropriate for the type of the item being added, so
695  * if it's not, we report an error rather than a dissector bug.
696  *
697  * This is for use when a field that's nominally an OCTET STRING but
698  * where we want the string further interpreted, e.g. as a number or
699  * a network address or a UN*X-style time stamp.
700  *
701  * XXX - this duplicates the length checking in proto_tree_add_item()
702  * and the routines it calls; that should really be done in one
703  * place.  We *do* want to report a dissector bug in proto_tree_add_item()
704  * if the dissector explicitly says, for example, "this IPv4 address is
705  * 7 bytes long", but we don't want to report a dissector bug if the
706  * *packet* says "this IPv4 address is 7 bytes long", we want to report
707  * a malformed packet.
708  */
709 static proto_item *
ber_proto_tree_add_item(packet_info * pinfo,proto_tree * tree,const int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding)710 ber_proto_tree_add_item(packet_info *pinfo, proto_tree *tree,
711                         const int hfindex, tvbuff_t *tvb, const gint start,
712                         gint length, const guint encoding)
713 {
714     header_field_info *hfinfo;
715 
716     hfinfo = proto_registrar_get_nth((guint)hfindex);
717     if (hfinfo != NULL) {
718         switch (hfinfo->type) {
719 
720         case FT_BOOLEAN:
721         case FT_UINT8:
722         case FT_UINT16:
723         case FT_UINT24:
724         case FT_UINT32:
725         case FT_INT8:
726         case FT_INT16:
727         case FT_INT24:
728         case FT_INT32:
729             if ((length != 1) && (length != 2) && (length != 3) &&
730                 (length != 4))
731                 return ber_add_bad_length_error(pinfo, tree,
732                     hfinfo->name, tvb, start, length);
733             break;
734 
735         case FT_IPv4:
736             if (length != FT_IPv4_LEN)
737                 return ber_add_bad_length_error(pinfo, tree,
738                     hfinfo->name, tvb, start, length);
739             break;
740 
741         case FT_IPXNET:
742             if (length != FT_IPXNET_LEN)
743                 return ber_add_bad_length_error(pinfo, tree,
744                     hfinfo->name, tvb, start, length);
745             break;
746 
747         case FT_IPv6:
748             if ((length < 0) || (length > FT_IPv6_LEN))
749                 return ber_add_bad_length_error(pinfo, tree,
750                     hfinfo->name, tvb, start, length);
751             break;
752 
753         case FT_ETHER:
754             if (length != FT_ETHER_LEN)
755                 return ber_add_bad_length_error(pinfo, tree,
756                     hfinfo->name, tvb, start, length);
757             break;
758 
759         case FT_GUID:
760             if (length != FT_GUID_LEN)
761                 return ber_add_bad_length_error(pinfo, tree,
762                     hfinfo->name, tvb, start, length);
763             break;
764 
765         case FT_FLOAT:
766             if (length != 4)
767                 return ber_add_bad_length_error(pinfo, tree,
768                     hfinfo->name, tvb, start, length);
769             break;
770 
771         case FT_DOUBLE:
772             if (length != 8)
773                 return ber_add_bad_length_error(pinfo, tree,
774                     hfinfo->name, tvb, start, length);
775             break;
776 
777         case FT_ABSOLUTE_TIME:
778         case FT_RELATIVE_TIME:
779             if ((length != 4) && (length != 8))
780                 return ber_add_bad_length_error(pinfo, tree,
781                     hfinfo->name, tvb, start, length);
782             break;
783 
784         default:
785             break;
786         }
787     }
788     return proto_tree_add_item(tree, hfindex, tvb, start, length, encoding);
789 }
790 
791 static int
try_dissect_unknown_ber(packet_info * pinfo,tvbuff_t * tvb,volatile int offset,proto_tree * tree,gint nest_level)792 try_dissect_unknown_ber(packet_info *pinfo, tvbuff_t *tvb, volatile int offset, proto_tree *tree, gint nest_level)
793 {
794     int                start_offset;
795     gint8              ber_class;
796     gboolean           pc, ind;
797     gint32             tag;
798     int                identifier_offset;
799     int                identifier_len;
800     guint32            len;
801     int                len_offset;
802     int                len_len;
803     int                hdr_len;
804     proto_item        *item      = NULL;
805     proto_tree        *next_tree = NULL;
806     guint8             c;
807     guint32            i;
808     gboolean           is_printable;
809     volatile gboolean  is_decoded_as;
810     proto_item        *pi;
811     asn1_ctx_t         asn1_ctx;
812 
813     if (nest_level > BER_MAX_NESTING) {
814         /* Assume that we have a malformed packet. */
815         THROW(ReportedBoundsError);
816     }
817 
818     start_offset = offset;
819     asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
820 
821     offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
822     len_offset = offset;
823     offset = get_ber_length(tvb, offset, &len, &ind);
824     len_len = offset - len_offset;
825 
826     if (len > (guint32)tvb_reported_length_remaining(tvb, offset)) {
827         /* hmm   maybe something bad happened or the frame is short;
828            since these are not vital outputs just return instead of
829            throwing an exception.
830          */
831 
832         if (show_internal_ber_fields) {
833             offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, &ber_class, &pc, &tag);
834             offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
835         }
836         ber_add_large_length_error(pinfo, tree, tvb, offset, len, tvb, len_offset, len_len);
837         return tvb_reported_length(tvb);
838     }
839 /* we don't care about the class only on the constructor flag */
840     switch (pc) {
841 
842     case FALSE: /* this is not constructed */
843 
844         switch (ber_class) { /* we do care about the class */
845         case BER_CLASS_UNI: /* it a Universal tag - we can decode it */
846             switch (tag) {
847             case BER_UNI_TAG_EOC:
848                 /* XXX: shouldn't really get here */
849                 break;
850             case BER_UNI_TAG_INTEGER:
851                 offset = dissect_ber_integer(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_INTEGER, NULL);
852                 break;
853             case BER_UNI_TAG_REAL:
854                 offset = dissect_ber_real(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_REAL, NULL);
855                 break;
856             case BER_UNI_TAG_BITSTRING:
857                 offset = dissect_ber_bitstring(FALSE, &asn1_ctx, tree, tvb, start_offset, NULL, 0, hf_ber_unknown_BITSTRING, -1, NULL);
858                 break;
859             case BER_UNI_TAG_ENUMERATED:
860                 offset = dissect_ber_integer(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_ENUMERATED, NULL);
861                 break;
862             case BER_UNI_TAG_GraphicString:
863                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_GraphicString, NULL);
864                 break;
865             case BER_UNI_TAG_OCTETSTRING:
866                 is_decoded_as = FALSE;
867                 if (decode_octetstring_as_ber && (len >= 2)) {
868                     volatile int ber_offset = 0;
869                     guint32 ber_len = 0;
870                     TRY {
871                         ber_offset = get_ber_identifier(tvb, offset, NULL, &pc, NULL);
872                         ber_offset = get_ber_length(tvb, ber_offset, &ber_len, NULL);
873                     } CATCH_ALL {
874                     }
875                     ENDTRY;
876                     if (pc && (ber_len > 0) && (ber_len + (ber_offset - offset) == len)) {
877                         /* Decoded a constructed ASN.1 tag with a length indicating this
878                          * could be BER encoded data.  Try dissecting as unknown BER.
879                          */
880                         is_decoded_as = TRUE;
881                         if (show_internal_ber_fields) {
882                             offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, NULL, NULL, NULL);
883                             offset = dissect_ber_length(pinfo, tree, tvb, offset, NULL, NULL);
884                         }
885                         item = ber_proto_tree_add_item(pinfo, tree, hf_ber_unknown_BER_OCTETSTRING, tvb, offset, len, ENC_NA);
886                         next_tree = proto_item_add_subtree(item, ett_ber_octet_string);
887                         offset = try_dissect_unknown_ber(pinfo, tvb, offset, next_tree, nest_level+1);
888                     }
889                 }
890                 if (!is_decoded_as) {
891                     offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_OCTETSTRING, NULL);
892                 }
893                 break;
894             case BER_UNI_TAG_OID:
895                 offset = dissect_ber_object_identifier_str(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_OID, NULL);
896                 break;
897             case BER_UNI_TAG_RELATIVE_OID:
898                 offset = dissect_ber_relative_oid_str(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_relative_OID, NULL);
899                 break;
900             case BER_UNI_TAG_NumericString:
901                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_NumericString, NULL);
902                 break;
903             case BER_UNI_TAG_PrintableString:
904                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_PrintableString, NULL);
905                 break;
906             case BER_UNI_TAG_TeletexString:
907                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_TeletexString, NULL);
908                 break;
909             case BER_UNI_TAG_VisibleString:
910                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_VisibleString, NULL);
911                 break;
912             case BER_UNI_TAG_GeneralString:
913                 offset = dissect_ber_GeneralString(&asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_GeneralString, NULL, 0);
914                 break;
915             case BER_UNI_TAG_BMPString:
916                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_BMPString, NULL);
917                 break;
918             case BER_UNI_TAG_UniversalString:
919                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_UniversalString, NULL);
920                 break;
921             case BER_UNI_TAG_IA5String:
922                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_IA5String, NULL);
923                 break;
924             case BER_UNI_TAG_UTCTime:
925                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_UTCTime, NULL);
926                 break;
927             case BER_UNI_TAG_NULL:
928                 proto_tree_add_item(tree, hf_ber_null_tag, tvb, offset, len, ENC_NA);
929                 break;
930             case BER_UNI_TAG_UTF8String:
931                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_UTF8String, NULL);
932                 break;
933             case BER_UNI_TAG_GeneralizedTime:
934                 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_GeneralizedTime, NULL);
935                 break;
936             case BER_UNI_TAG_BOOLEAN:
937                 offset = dissect_ber_boolean(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_BOOLEAN, NULL);
938                 break;
939             default:
940                 identifier_offset = start_offset;
941                 offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, &ber_class, &pc, &tag);
942                 identifier_len = offset - identifier_offset;
943                 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
944                 proto_tree_add_expert_format(
945                     tree, pinfo, &ei_ber_universal_tag_unknown,
946                     tvb, identifier_offset, identifier_len,
947                     "BER Error: can not handle universal tag:%d",
948                     tag);
949                 offset += len;
950             }
951             break;
952         case BER_CLASS_APP:
953         case BER_CLASS_CON:
954         case BER_CLASS_PRI:
955         default:
956             /* we dissect again if show_internal_ber_fields is set */
957             if (show_internal_ber_fields) {
958                 offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, &ber_class, &pc, &tag);
959                 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
960             }
961 
962             /* we can't dissect this directly as it is specific */
963             pi = proto_tree_add_none_format(tree, hf_ber_unknown_BER_primitive, tvb, offset, len,
964                                             "[%s %d] ", val_to_str_const(ber_class, ber_class_codes, "Unknown"), tag);
965 
966             is_decoded_as = FALSE;
967             if (decode_primitive_as_ber && (len >= 2)) {
968                 volatile int ber_offset = 0;
969                 guint32 ber_len = 0;
970                 TRY {
971                     ber_offset = get_ber_identifier(tvb, offset, NULL, &pc, NULL);
972                     ber_offset = get_ber_length(tvb, ber_offset, &ber_len, NULL);
973                 } CATCH_ALL {
974                 }
975                 ENDTRY;
976                 if (pc && (ber_len > 0) && (ber_len + (ber_offset - offset) == len)) {
977                     /* Decoded a constructed ASN.1 tag with a length indicating this
978                      * could be BER encoded data.  Try dissecting as unknown BER.
979                      */
980                     is_decoded_as = TRUE;
981                     proto_item_append_text (pi, "[BER encoded]");
982                     next_tree = proto_item_add_subtree(pi, ett_ber_primitive);
983                     offset = try_dissect_unknown_ber(pinfo, tvb, offset, next_tree, nest_level+1);
984                 }
985             }
986 
987             if (!is_decoded_as && len) {
988                 /* we may want to do better and show the bytes */
989                 is_printable = TRUE;
990                 for (i=0; i<len; i++) {
991                     c = tvb_get_guint8(tvb, offset+i);
992 
993                     if (is_printable && !g_ascii_isprint(c))
994                         is_printable = FALSE;
995 
996                     proto_item_append_text(pi, "%02x", c);
997                 }
998 
999                 if (is_printable) { /* give a nicer representation if it looks like a string */
1000                     proto_item_append_text(pi, " (");
1001                     for (i=0; i<len; i++) {
1002                         proto_item_append_text(pi, "%c", tvb_get_guint8(tvb, offset+i));
1003                     }
1004                     proto_item_append_text(pi, ")");
1005                 }
1006                 offset += len;
1007             }
1008 
1009             break;
1010         }
1011         break;
1012 
1013     case TRUE: /* this is constructed */
1014 
1015         /* we dissect again if show_internal_ber_fields is set */
1016         if (show_internal_ber_fields) {
1017             offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, &ber_class, &pc, &tag);
1018             offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
1019         }
1020 
1021         hdr_len = offset-start_offset;
1022 
1023         switch (ber_class) {
1024         case BER_CLASS_UNI:
1025             next_tree = proto_tree_add_subtree(tree, tvb, offset, len, ett_ber_SEQUENCE, NULL,
1026                                                val_to_str_ext_const(tag, &ber_uni_tag_codes_ext, "Unknown"));
1027             while (offset < (int)(start_offset + len + hdr_len))
1028                 offset = try_dissect_unknown_ber(pinfo, tvb, offset, next_tree, nest_level+1);
1029             break;
1030         case BER_CLASS_APP:
1031         case BER_CLASS_CON:
1032         case BER_CLASS_PRI:
1033         default:
1034             next_tree = proto_tree_add_subtree_format(tree, tvb, offset, len, ett_ber_SEQUENCE, NULL,
1035                             "[%s %d]", val_to_str_const(ber_class, ber_class_codes, "Unknown"), tag);
1036             while (offset < (int)(start_offset + len + hdr_len))
1037                 offset = try_dissect_unknown_ber(pinfo, tvb, offset, next_tree, nest_level+1);
1038             break;
1039 
1040         }
1041         break;
1042 
1043     }
1044 
1045     return offset;
1046 }
1047 
1048 int
dissect_unknown_ber(packet_info * pinfo,tvbuff_t * tvb,int offset,proto_tree * tree)1049 dissect_unknown_ber(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree)
1050 {
1051     return try_dissect_unknown_ber(pinfo, tvb, offset, tree, 1);
1052 }
1053 
1054 int
call_ber_oid_callback(const char * oid,tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,void * data)1055 call_ber_oid_callback(const char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data)
1056 {
1057     tvbuff_t   *next_tvb;
1058     const char *syntax = NULL;
1059     int         len = 0;
1060 
1061     if (!tvb) {
1062         return offset;
1063     }
1064 
1065     next_tvb = tvb_new_subset_remaining(tvb, offset);
1066     if (oid == NULL ||
1067         ((((syntax = get_ber_oid_syntax(oid)) == NULL) ||
1068           /* First see if a syntax has been registered for this oid (user defined) */
1069           (len = dissector_try_string(ber_syntax_dissector_table, syntax, next_tvb, pinfo, tree, data)) == 0) &&
1070          /* Then try registered oid's */
1071          (len = dissector_try_string(ber_oid_dissector_table, oid, next_tvb, pinfo, tree, data)) == 0))
1072     {
1073         proto_item *item      = NULL;
1074         proto_tree *next_tree = NULL;
1075         gint        length_remaining;
1076 
1077         /* XXX we should probably use get_ber_length() here */
1078         length_remaining = tvb_reported_length_remaining(tvb, offset);
1079 
1080         if (oid == NULL) {
1081             item = proto_tree_add_expert(tree, pinfo, &ei_ber_no_oid, next_tvb, 0, length_remaining);
1082         } else if (tvb_get_ntohs (tvb, offset) != 0x0500) { /* Not NULL tag */
1083             if (syntax) {
1084                 item = proto_tree_add_expert_format(
1085                     tree, pinfo, &ei_ber_syntax_not_implemented, next_tvb, 0, length_remaining,
1086                     "BER: Dissector for syntax:%s not implemented."
1087                     " Contact Wireshark developers if you want this supported",
1088                     syntax);
1089             } else {
1090                 item = proto_tree_add_expert(tree, pinfo, &ei_ber_oid_not_implemented, next_tvb, 0, length_remaining);
1091             }
1092         } else {
1093             next_tree = tree;
1094         }
1095         if (decode_unexpected) {
1096             int ber_offset;
1097             gint32 ber_len;
1098 
1099             if (item) {
1100                 next_tree = proto_item_add_subtree(item, ett_ber_unknown);
1101             }
1102             ber_offset = get_ber_identifier(next_tvb, 0, NULL, NULL, NULL);
1103             ber_offset = get_ber_length(next_tvb, ber_offset, &ber_len, NULL);
1104             if ((ber_len + ber_offset) == length_remaining) {
1105                 /* Decoded an ASN.1 tag with a length indicating this
1106                  * could be BER encoded data.  Try dissecting as unknown BER.
1107                  */
1108                 dissect_unknown_ber(pinfo, next_tvb, 0, next_tree);
1109             } else {
1110                 proto_tree_add_item(next_tree, hf_ber_unknown_data, next_tvb, 0, length_remaining, ENC_NA);
1111             }
1112         }
1113         len = length_remaining;
1114     }
1115 
1116     offset += len;
1117 
1118     return offset;
1119 }
1120 
1121 static int
call_ber_syntax_callback(const char * syntax,tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree)1122 call_ber_syntax_callback(const char *syntax, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1123 {
1124     tvbuff_t *next_tvb;
1125     int       len = 0;
1126 
1127     next_tvb = tvb_new_subset_remaining(tvb, offset);
1128     if (syntax == NULL ||
1129         (len = dissector_try_string(ber_syntax_dissector_table, syntax, next_tvb, pinfo, tree, NULL)) == 0)
1130     {
1131         proto_item *item = NULL;
1132 
1133         if (syntax == NULL) {
1134             item = proto_tree_add_expert_format(
1135                     tree, pinfo, &ei_ber_no_oid, next_tvb, 0, tvb_reported_length_remaining(tvb, offset),
1136                     "BER Error: No syntax supplied to call_ber_syntax_callback");
1137         } else {
1138             item = proto_tree_add_expert_format(
1139                     tree, pinfo, &ei_ber_syntax_not_implemented, next_tvb, 0, tvb_reported_length_remaining(tvb, offset),
1140                     "BER: Dissector for syntax:%s not implemented."
1141                     " Contact Wireshark developers if you want this supported",
1142                     syntax);
1143         }
1144         if (decode_unexpected) {
1145             proto_tree *unknown_tree = proto_item_add_subtree(item, ett_ber_unknown);
1146             dissect_unknown_ber(pinfo, next_tvb, 0, unknown_tree);
1147         }
1148         len = tvb_reported_length_remaining(tvb, offset);
1149     }
1150 
1151     offset += len;
1152 
1153     return offset;
1154 }
1155 
1156 
1157 /* 8.1 General rules for encoding */
1158 
1159 /*  8.1.2 Identifier octets */
1160 int
get_ber_identifier(tvbuff_t * tvb,int offset,gint8 * ber_class,gboolean * pc,gint32 * tag)1161 get_ber_identifier(tvbuff_t *tvb, int offset, gint8 *ber_class, gboolean *pc, gint32 *tag) {
1162     guint8   id, t;
1163     gint8    tmp_class;
1164     gboolean tmp_pc;
1165     gint32   tmp_tag;
1166 
1167     id = tvb_get_guint8(tvb, offset);
1168     offset += 1;
1169 #ifdef DEBUG_BER
1170 ws_debug_printf("BER ID=%02x", id);
1171 #endif
1172     /* 8.1.2.2 */
1173     tmp_class = (id >> 6) & 0x03;
1174     tmp_pc = (id >> 5) & 0x01;
1175     tmp_tag = id & 0x1F;
1176     /* 8.1.2.4 */
1177     if (tmp_tag == 0x1F) {
1178         tmp_tag = 0;
1179         while (tvb_reported_length_remaining(tvb, offset) > 0) {
1180             t = tvb_get_guint8(tvb, offset);
1181 #ifdef DEBUG_BER
1182 ws_debug_printf(" %02x", t);
1183 #endif
1184             offset += 1;
1185             tmp_tag <<= 7;
1186             tmp_tag |= t & 0x7F;
1187             if (!(t & 0x80))
1188                 break;
1189         }
1190     }
1191 
1192 #ifdef DEBUG_BER
1193 ws_debug_printf("\n");
1194 #endif
1195     if (ber_class)
1196         *ber_class = tmp_class;
1197     if (pc)
1198         *pc  = tmp_pc;
1199     if (tag)
1200         *tag = tmp_tag;
1201 
1202     last_class = tmp_class;
1203     last_pc  = tmp_pc;
1204     last_tag = tmp_tag;
1205 
1206     return offset;
1207 }
1208 
1209 static void
get_last_ber_identifier(gint8 * ber_class,gboolean * pc,gint32 * tag)1210 get_last_ber_identifier(gint8 *ber_class, gboolean *pc, gint32 *tag)
1211 {
1212     if (ber_class)
1213         *ber_class = last_class;
1214     if (pc)
1215         *pc  = last_pc;
1216     if (tag)
1217         *tag = last_tag;
1218 
1219 }
1220 
1221 int
dissect_ber_identifier(packet_info * pinfo _U_,proto_tree * tree,tvbuff_t * tvb,int offset,gint8 * ber_class,gboolean * pc,gint32 * tag)1222 dissect_ber_identifier(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gint8 *ber_class, gboolean *pc, gint32 *tag)
1223 {
1224     int      old_offset = offset;
1225     gint8    tmp_class;
1226     gboolean tmp_pc;
1227     gint32   tmp_tag;
1228 
1229     offset = get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
1230 
1231     if (show_internal_ber_fields) {
1232         proto_tree_add_uint(tree, hf_ber_id_class, tvb, old_offset, 1, tmp_class << 6);
1233         proto_tree_add_boolean(tree, hf_ber_id_pc, tvb, old_offset, 1, (tmp_pc) ? 0x20 : 0x00);
1234         if (tmp_tag > 0x1F) {
1235             if (tmp_class == BER_CLASS_UNI) {
1236                 proto_tree_add_uint(tree, hf_ber_id_uni_tag_ext, tvb, old_offset + 1, offset - (old_offset + 1), tmp_tag);
1237             } else {
1238                 proto_tree_add_uint(tree, hf_ber_id_tag_ext, tvb, old_offset + 1, offset - (old_offset + 1), tmp_tag);
1239             }
1240         } else {
1241             if (tmp_class == BER_CLASS_UNI) {
1242                 proto_tree_add_uint(tree, hf_ber_id_uni_tag, tvb, old_offset, 1, tmp_tag);
1243             } else {
1244                 proto_tree_add_uint(tree, hf_ber_id_tag, tvb, old_offset, 1, tmp_tag);
1245             }
1246         }
1247     }
1248 
1249     if (ber_class)
1250         *ber_class = tmp_class;
1251     if (pc)
1252         *pc = tmp_pc;
1253     if (tag)
1254         *tag = tmp_tag;
1255 
1256     return offset;
1257 }
1258 
1259 /** Try to get the length octets of the BER TLV.
1260  * Only (TAGs and) LENGTHs that fit inside 32 bit integers are supported.
1261  *
1262  * @return TRUE if we have the entire length, FALSE if we're in the middle of
1263  * an indefinite length and haven't reached EOC.
1264  */
1265 /* 8.1.3 Length octets */
1266 
1267 static int
try_get_ber_length(tvbuff_t * tvb,int offset,guint32 * length,gboolean * ind,gint nest_level)1268 try_get_ber_length(tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind, gint nest_level) {
1269     guint8   oct, len;
1270     guint32  indef_len;
1271     guint32  tmp_length;
1272     gboolean tmp_ind;
1273     int      tmp_offset, s_offset;
1274     gint8    tclass;
1275     gboolean tpc;
1276     gint32   ttag;
1277 
1278     tmp_length = 0;
1279     tmp_ind    = FALSE;
1280 
1281     if (nest_level > BER_MAX_NESTING) {
1282         /* Assume that we have a malformed packet. */
1283         THROW(ReportedBoundsError);
1284     }
1285 
1286     oct = tvb_get_guint8(tvb, offset);
1287     offset += 1;
1288 
1289     if (!(oct & 0x80)) {
1290         /* 8.1.3.4 */
1291         tmp_length = oct;
1292     } else {
1293         len = oct & 0x7F;
1294         if (len) {
1295             /* 8.1.3.5 */
1296             while (len--) {
1297                 oct = tvb_get_guint8(tvb, offset);
1298                 offset++;
1299                 tmp_length = (tmp_length<<8) + oct;
1300             }
1301         } else {
1302             /* 8.1.3.6 */
1303 
1304             tmp_offset = offset;
1305             /* ok in here we can traverse the BER to find the length, this will fix most indefinite length issues */
1306             /* Assumption here is that indefinite length is always used on constructed types*/
1307             /* check for EOC */
1308             while (tvb_get_guint8(tvb, offset) || tvb_get_guint8(tvb, offset+1)) {
1309                 /* not an EOC at offset */
1310                 s_offset = offset;
1311                 offset= get_ber_identifier(tvb, offset, &tclass, &tpc, &ttag);
1312                 offset= try_get_ber_length(tvb, offset, &indef_len, NULL, nest_level+1);
1313                 tmp_length += indef_len+(offset-s_offset); /* length + tag and length */
1314                 offset += indef_len;
1315                                 /* Make sure we've moved forward in the packet */
1316                 if (offset <= s_offset)
1317                     THROW(ReportedBoundsError);
1318             }
1319             tmp_length += 2;
1320             tmp_ind = TRUE;
1321             offset = tmp_offset;
1322         }
1323     }
1324 
1325     /* Several users treat the length as signed value, clamp the value to avoid
1326      * an overflow to negative values. */
1327     if (tmp_length > (guint32)G_MAXINT32)
1328         tmp_length = (guint32)G_MAXINT32;
1329 
1330     if (length)
1331         *length = tmp_length;
1332     if (ind)
1333         *ind = tmp_ind;
1334 
1335 #ifdef DEBUG_BER
1336 ws_debug_printf("get BER length %d, offset %d (remaining %d)\n", tmp_length, offset, tvb_reported_length_remaining(tvb, offset));
1337 #endif
1338 
1339     return offset;
1340 }
1341 
1342 int
get_ber_length(tvbuff_t * tvb,int offset,guint32 * length,gboolean * ind)1343 get_ber_length(tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind)
1344 {
1345     return try_get_ber_length(tvb, offset, length, ind, 1);
1346 }
1347 
1348 static void
get_last_ber_length(guint32 * length,gboolean * ind,tvbuff_t ** len_tvb,int * len_offset,int * len_len)1349 get_last_ber_length(guint32 *length, gboolean *ind, tvbuff_t **len_tvb, int *len_offset, int *len_len)
1350 {
1351     if (length)
1352         *length = last_length;
1353     if (ind)
1354         *ind = last_ind;
1355     if (len_tvb)
1356         *len_tvb = last_length_tvb;
1357     if (len_offset)
1358         *len_offset = last_length_offset;
1359     if (len_len)
1360         *len_len = last_length_len;
1361 }
1362 
1363 /* this function dissects the length octets of the BER TLV.
1364  * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
1365  */
1366 int
dissect_ber_length(packet_info * pinfo _U_,proto_tree * tree,tvbuff_t * tvb,int offset,guint32 * length,gboolean * ind)1367 dissect_ber_length(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind)
1368 {
1369     int      old_offset = offset;
1370     guint32  tmp_length;
1371     gboolean tmp_ind;
1372 
1373     offset = get_ber_length(tvb, offset, &tmp_length, &tmp_ind);
1374 
1375     if (show_internal_ber_fields) {
1376         if (tmp_ind) {
1377             proto_tree_add_uint_format_value(tree, hf_ber_length, tvb, old_offset, 1, tmp_length, "Indefinite length %d", tmp_length);
1378         } else {
1379             proto_tree_add_uint(tree, hf_ber_length, tvb, old_offset, offset - old_offset, tmp_length);
1380         }
1381     }
1382     if (length)
1383         *length = tmp_length;
1384     if (ind)
1385         *ind = tmp_ind;
1386 
1387 #ifdef DEBUG_BER
1388 proto_tree_add_debug_text(tree, "dissect BER length %d, offset %d (remaining %d)\n", tmp_length, offset, tvb_reported_length_remaining(tvb, offset));
1389 #endif
1390 
1391     last_length = tmp_length;
1392     last_ind = tmp_ind;
1393     last_length_tvb = tvb;
1394     last_length_offset = old_offset;
1395     last_length_len = offset - old_offset;
1396 
1397     return offset;
1398 }
1399 
1400 static reassembly_table octet_segment_reassembly_table;
1401 
1402 static int
1403 dissect_ber_constrained_octet_string_impl(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, tvbuff_t **out_tvb, guint nest_level, guint encoding);
1404 
1405 static int
reassemble_octet_string(asn1_ctx_t * actx,proto_tree * tree,gint hf_id,tvbuff_t * tvb,int offset,guint32 con_len,gboolean ind,tvbuff_t ** out_tvb,guint nest_level)1406 reassemble_octet_string(asn1_ctx_t *actx, proto_tree *tree, gint hf_id, tvbuff_t *tvb, int offset, guint32 con_len, gboolean ind, tvbuff_t **out_tvb, guint nest_level)
1407 {
1408     fragment_head *fd_head         = NULL;
1409     tvbuff_t      *next_tvb        = NULL;
1410     tvbuff_t      *reassembled_tvb = NULL;
1411     guint16        dst_ref         = 0;
1412     int            start_offset    = offset;
1413     gboolean       fragment        = TRUE;
1414     gboolean       firstFragment   = TRUE;
1415 
1416     if (nest_level > BER_MAX_NESTING) {
1417         /* Assume that we have a malformed packet. */
1418         THROW(ReportedBoundsError);
1419     }
1420 
1421     /* so we need to consume octet strings for the given length */
1422 
1423     if (out_tvb)
1424         *out_tvb = NULL;
1425 
1426     if (con_len == 0) /* Zero encodings (8.7.3) */
1427         return offset;
1428 
1429     /* not sure we need this */
1430     actx->pinfo->fragmented = TRUE;
1431 
1432     while(!fd_head) {
1433 
1434         offset = dissect_ber_constrained_octet_string_impl(FALSE, actx, NULL,
1435                 tvb, offset, NO_BOUND, NO_BOUND, hf_id, &next_tvb, nest_level + 1, 0);
1436 
1437         if (next_tvb == NULL) {
1438             /* Assume that we have a malformed packet. */
1439             THROW(ReportedBoundsError);
1440         }
1441 
1442         if (ind) {
1443             /* this was indefinite length - so check for EOC */
1444 
1445             if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
1446                 fragment = FALSE;
1447                 /* skip past EOC */
1448                 offset +=2;
1449             }
1450         } else {
1451 
1452             if ((guint32)(offset - start_offset) >= con_len)
1453                 fragment = FALSE;
1454         }
1455 
1456         if (!fragment && firstFragment) {
1457             /* there is only one fragment (I'm sure there's a reason it was constructed) */
1458             /* anyway, we can get out of here */
1459             gboolean pc;
1460             get_ber_identifier(tvb, start_offset, NULL, &pc, NULL);
1461             if (!pc && tree) {
1462                 /* Only display here if not constructed */
1463                 dissect_ber_octet_string(FALSE, actx, tree, tvb, start_offset, hf_id, NULL);
1464             }
1465             reassembled_tvb = next_tvb;
1466             break;
1467         }
1468 
1469 
1470         if (tvb_reported_length(next_tvb) < 1) {
1471             /* Don't cause an assertion in the reassembly code. */
1472             THROW(ReportedBoundsError);
1473         }
1474         fd_head = fragment_add_seq_next(&octet_segment_reassembly_table,
1475                                         next_tvb, 0, actx->pinfo, dst_ref, NULL,
1476                                         tvb_reported_length(next_tvb),
1477                                         fragment);
1478 
1479         firstFragment = FALSE;
1480     }
1481 
1482     if (fd_head) {
1483         if (fd_head->next) {
1484             /* not sure I really want to do this here - should be nearer the application where we can give it a better name*/
1485             proto_tree *next_tree;
1486             proto_item *frag_tree_item;
1487 
1488             reassembled_tvb = tvb_new_chain(next_tvb, fd_head->tvb_data);
1489 
1490             actx->created_item = proto_tree_add_item(tree, hf_id, reassembled_tvb, 0, -1, ENC_BIG_ENDIAN);
1491             next_tree = proto_item_add_subtree (actx->created_item, ett_ber_reassembled_octet_string);
1492 
1493             add_new_data_source(actx->pinfo, reassembled_tvb, "Reassembled OCTET STRING");
1494             show_fragment_seq_tree(fd_head, &octet_string_frag_items, next_tree, actx->pinfo, reassembled_tvb, &frag_tree_item);
1495         }
1496     }
1497 
1498     if (out_tvb)
1499         *out_tvb = reassembled_tvb;
1500 
1501     /* again - not sure we need this */
1502     actx->pinfo->fragmented = FALSE;
1503 
1504     return offset;
1505 
1506 }
1507 
1508 /* 8.7 Encoding of an octetstring value */
1509 int
dissect_ber_constrained_octet_string(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint32 min_len,gint32 max_len,gint hf_id,tvbuff_t ** out_tvb)1510 dissect_ber_constrained_octet_string(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, tvbuff_t **out_tvb) {
1511   return dissect_ber_constrained_octet_string_impl(implicit_tag, actx, tree, tvb, offset, min_len, max_len, hf_id, out_tvb, 0, 0);
1512 }
1513 
1514 static int
dissect_ber_constrained_octet_string_impl(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint32 min_len,gint32 max_len,gint hf_id,tvbuff_t ** out_tvb,guint nest_level,guint encoding)1515 dissect_ber_constrained_octet_string_impl(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, tvbuff_t **out_tvb, guint nest_level, guint encoding) {
1516     gint8       ber_class;
1517     gboolean    pc, ind;
1518     gint32      tag;
1519     int         identifier_offset;
1520     int         identifier_len;
1521     guint32     len;
1522     tvbuff_t   *len_tvb;
1523     int         len_offset;
1524     int         len_len;
1525     int         hoffset;
1526     int         end_offset;
1527     proto_item *it, *cause;
1528     guint32     len_remain;
1529 
1530 #ifdef DEBUG_BER
1531 {
1532 const char *name;
1533 header_field_info *hfinfo;
1534 if (hf_id >= 0) {
1535 hfinfo = proto_registrar_get_nth(hf_id);
1536 name = hfinfo->name;
1537 } else {
1538 name = "unnamed";
1539 }
1540 if (tvb_reported_length_remaining(tvb, offset) > 3) {
1541 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_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
1542 } else {
1543 proto_tree_add_debug_text(tree, "OCTET STRING dissect_ber_octet_string(%s) entered\n", name);
1544 }
1545 }
1546 #endif
1547 
1548     if (out_tvb)
1549         *out_tvb = NULL;
1550 
1551     if (!implicit_tag) {
1552         hoffset = offset;
1553         /* read header and len for the octet string */
1554         identifier_offset = offset;
1555         offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
1556         identifier_len = offset - identifier_offset;
1557         offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
1558         end_offset = offset+len;
1559 
1560         /* sanity check: we only handle Constructed Universal Sequences */
1561         if ((ber_class != BER_CLASS_APP) && (ber_class != BER_CLASS_PRI)) {
1562             if ( (ber_class != BER_CLASS_UNI)
1563               || ((tag < BER_UNI_TAG_NumericString) && (tag != BER_UNI_TAG_OCTETSTRING) && (tag != BER_UNI_TAG_UTF8String)) ) {
1564                 tvb_ensure_bytes_exist(tvb, hoffset, 2);
1565                 cause = proto_tree_add_expert_format(
1566                     tree, actx->pinfo, &ei_ber_expected_octet_string,
1567                     tvb, identifier_offset, identifier_len,
1568                     "BER Error: OctetString expected but class:%s(%d) %s tag:%d was unexpected",
1569                     val_to_str_const(ber_class, ber_class_codes, "Unknown"),
1570                     ber_class,
1571                     tfs_get_string(pc, &tfs_constructed_primitive),
1572                     tag);
1573                 if (decode_unexpected) {
1574                     proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
1575                     dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1576                 }
1577                 return end_offset;
1578             }
1579         }
1580     } else {
1581         /* implicit tag so get from last tag/length */
1582 
1583         get_last_ber_identifier(&ber_class, &pc, &tag);
1584         get_last_ber_length(&len, &ind, &len_tvb, &len_offset, &len_len);
1585 
1586         end_offset = offset+len;
1587 
1588         /* caller may have created new buffer for indefinite length data Verify via length */
1589         len_remain = (guint32)tvb_reported_length_remaining(tvb, offset);
1590         if (ind && (len_remain == (len - 2))) {
1591             /* new buffer received so adjust length and indefinite flag */
1592             len -= 2;
1593             end_offset -= 2;
1594             ind = FALSE;
1595         } else if (len_remain < len) {
1596             /*
1597              * error - short frame, or this item runs past the
1598              * end of the item containing it
1599              */
1600             ber_add_large_length_error(actx->pinfo, tree, tvb, offset, len, len_tvb, len_offset, len_len);
1601             return end_offset;
1602         }
1603 
1604     }
1605 
1606     actx->created_item = NULL;
1607 
1608     if (pc) {
1609         /* constructed */
1610         end_offset = reassemble_octet_string(actx, tree, hf_id, tvb, offset, len, ind, out_tvb, nest_level);
1611     } else {
1612         /* primitive */
1613         gint length_remaining;
1614 
1615         length_remaining = tvb_reported_length_remaining(tvb, offset);
1616 #if 0
1617         if (length_remaining < 1) {
1618             return end_offset;
1619         }
1620 #endif
1621 
1622         if (len <= (guint32)length_remaining) {
1623             length_remaining = len;
1624         }
1625         if (hf_id >= 0) {
1626             /*
1627              * Strings are special.  See X.680 section 41 "Definition of
1628              * restricted character string types" and X.690 section 8.20
1629              * "Encoding for values of the restricted character string
1630              * types".
1631              *
1632              * Some restricted character string types are defined in X.680
1633              * "by reference to a registration number in the ISO International
1634              * Register of Character Sets" - or, in Table 8, by multiple
1635              * registration numbers, or one or more registration numbers
1636              * plus some characters such as SPACE and/or DELETE, or a
1637              * reference to "all G sets" or "all G sets and all C sets".
1638              * Presumably this indicates which characters are allowed
1639              * in strings of those character types, with "all {G,C} sets"
1640              * meaning the only restriction is to character sets registered
1641              * in said registry.
1642              *
1643              * The encodings of those types are specified in X.690 as
1644              * containing "the octets specified in ISO/IEC 2022 for
1645              * encodings in an 8-bit environment, using the escape sequence
1646              * and character codings registered in accordance with ISO/IEC
1647              * 2375".
1648              *
1649              * ISO/IEC 2022 is also ECMA-35:
1650              *
1651              *    http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-035.pdf
1652              *
1653              * ISO/IEC 2375 is the procedure for registering character
1654              * codings in the ISO International Register of Character Sets.
1655              * See
1656              *
1657              *     http://kikaku.itscj.ipsj.or.jp/ISO-IR/
1658              *
1659              * and
1660              *
1661              *     http://kikaku.itscj.ipsj.or.jp/ISO-IR/overview.htm
1662              *
1663              * for that registry.
1664              *
1665              * If we've been provided with a non-zero encoding, use
1666              * that; otherwise, calculate it based on the tag.  (A
1667              * zero encoding is ENC_ASCII|ENC_NA/ENC_BIG_ENDIAN, which
1668              * is the default, so it's OK to use here; this is for
1669              * protcols such as LDAP that use OCTET STRING for UTF-8
1670              * strings.)
1671              */
1672             if (encoding == 0) {
1673                 switch (tag) {
1674 
1675                 case BER_UNI_TAG_UTF8String:
1676                     /*
1677                      * UTF-8, obviously.
1678                      */
1679                     encoding = ENC_UTF_8|ENC_NA;
1680                     break;
1681 
1682                 case BER_UNI_TAG_NumericString:
1683                 case BER_UNI_TAG_PrintableString:
1684                 case BER_UNI_TAG_VisibleString:
1685                 case BER_UNI_TAG_IA5String:
1686                     /*
1687                      * (Subsets of) Boring Old ASCII, with no(?) ISO 2022
1688                      * escape sequences.
1689                      */
1690                     encoding = ENC_ASCII|ENC_NA;
1691                     break;
1692 
1693                 case BER_UNI_TAG_TeletexString:
1694                     encoding = ENC_T61|ENC_NA;
1695                     break;
1696 
1697                 case BER_UNI_TAG_VideotexString:
1698                     encoding = ENC_T61|ENC_NA;
1699                     break;
1700 
1701                 case BER_UNI_TAG_GraphicString:
1702                 case BER_UNI_TAG_GeneralString:
1703                     /*
1704                      * One of the types defined in terms of character sets
1705                      * in the ISO International Register of Character Sets,
1706                      * with the BER encoding being ISO 2022-based.
1707                      *
1708                      * XXX - treat as ASCII for now.
1709                      */
1710                     encoding = ENC_ASCII|ENC_NA;
1711                     break;
1712 
1713                 case BER_UNI_TAG_UniversalString:
1714                     /*
1715                      * UCS-4.
1716                      */
1717                     encoding = ENC_UCS_4|ENC_BIG_ENDIAN;
1718                     break;
1719 
1720                 case BER_UNI_TAG_CHARACTERSTRING:
1721                     /*
1722                      * XXX - what's the transfer syntax?
1723                      * Treat as ASCII for now.
1724                      */
1725                     encoding = ENC_ASCII|ENC_NA;
1726                     break;
1727 
1728                 case BER_UNI_TAG_BMPString:
1729                     /*
1730                      * UCS-2, not UTF-16; as it says, BMP, as in Basic
1731                      * Multilingual Plane.
1732                      */
1733                     encoding = ENC_UCS_2|ENC_BIG_ENDIAN;
1734                     break;
1735 
1736                 default:
1737                      encoding = ENC_BIG_ENDIAN;
1738                      break;
1739                 }
1740             }
1741             it = ber_proto_tree_add_item(actx->pinfo, tree, hf_id, tvb, offset, length_remaining, encoding);
1742             actx->created_item = it;
1743             ber_check_length(length_remaining, min_len, max_len, actx, it, FALSE);
1744         } else {
1745 
1746             proto_tree_add_item(tree, hf_ber_unknown_octetstring, tvb, offset, len, ENC_NA);
1747         }
1748 
1749         if (out_tvb) {
1750             *out_tvb = ber_tvb_new_subset_length(tvb, offset, len);
1751         }
1752     }
1753     return end_offset;
1754 }
1755 
1756 int
dissect_ber_octet_string(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,tvbuff_t ** out_tvb)1757 dissect_ber_octet_string(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb) {
1758   return dissect_ber_constrained_octet_string_impl(implicit_tag, actx, tree, tvb, offset, NO_BOUND, NO_BOUND, hf_id, out_tvb, 0, 0);
1759 }
1760 
1761 int
dissect_ber_octet_string_with_encoding(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,tvbuff_t ** out_tvb,guint encoding)1762 dissect_ber_octet_string_with_encoding(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb, guint encoding) {
1763   return dissect_ber_constrained_octet_string_impl(implicit_tag, actx, tree, tvb, offset, NO_BOUND, NO_BOUND, hf_id, out_tvb, 0, encoding);
1764 }
1765 
1766 int
dissect_ber_octet_string_wcb(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,ber_callback func)1767 dissect_ber_octet_string_wcb(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, ber_callback func)
1768 {
1769     tvbuff_t *out_tvb = NULL;
1770 
1771     offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_id, (func) ? &out_tvb : NULL);
1772     if (func && out_tvb && (tvb_reported_length(out_tvb) > 0)) {
1773         if (hf_id >= 0)
1774             tree = proto_item_add_subtree(actx->created_item, ett_ber_octet_string);
1775         /* TODO Should hf_id2 be pased as last parameter???*/
1776         func(FALSE, out_tvb, 0, actx, tree, -1);
1777     }
1778     return offset;
1779 }
1780 
1781 /* 8.8 Encoding of a null value */
1782 int
dissect_ber_null(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id)1783 dissect_ber_null(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id) {
1784     gint8       ber_class;
1785     gboolean    pc;
1786     gint32      tag;
1787     int         identifier_offset;
1788     int         identifier_len;
1789     guint32     len;
1790     int         len_offset;
1791     int         len_len;
1792 
1793     if (!implicit_tag) {
1794         identifier_offset = offset;
1795         offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
1796         identifier_len = offset - identifier_offset;
1797         if (pc ||
1798             ((ber_class != BER_CLASS_UNI) || (tag != BER_UNI_TAG_NULL))) {
1799             proto_tree_add_expert_format(
1800                 tree, actx->pinfo, &ei_ber_expected_null,
1801                 tvb, identifier_offset, identifier_len,
1802                 "BER Error: NULL expected but class:%s(%d) %s tag:%d was unexpected",
1803                 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
1804                 ber_class,
1805                 tfs_get_string(pc, &tfs_constructed_primitive),
1806                 tag);
1807         }
1808 
1809         len_offset = offset;
1810         offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
1811         len_len = offset - len_offset;
1812         if (len) {
1813             proto_tree_add_expert_format(
1814                 tree, actx->pinfo, &ei_ber_expected_null_zero_length,
1815                 tvb, len_offset, len_len,
1816                 "BER Error: NULL type expects zero length data but Length=%d",
1817                 len);
1818             proto_tree_add_item(tree, hf_ber_extra_data, tvb, offset, len, ENC_NA);
1819             offset += len;
1820         }
1821     }
1822     if (hf_id >= 0)
1823         proto_tree_add_item(tree, hf_id, tvb, offset, 0, ENC_BIG_ENDIAN);
1824     return offset;
1825 }
1826 
1827 int
dissect_ber_integer64(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,gint64 * value)1828 dissect_ber_integer64(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gint64 *value)
1829 {
1830     gint8    ber_class;
1831     gboolean pc;
1832     gint32   tag;
1833     guint32  len;
1834     gint64   val;
1835     guint32  i;
1836     gboolean used_too_many_bytes = FALSE;
1837     guint8 first;
1838 #ifdef DEBUG_BER
1839 {
1840 const char *name;
1841 header_field_info *hfinfo;
1842 if (hf_id >= 0) {
1843 hfinfo = proto_registrar_get_nth(hf_id);
1844 name = hfinfo->name;
1845 } else {
1846 name = "unnamed";
1847 }
1848 if (tvb_reported_length_remaining(tvb, offset) > 3) {
1849 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_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
1850 } else {
1851 proto_tree_add_debug_text(tree, "INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d \n", name, implicit_tag);
1852 }
1853 }
1854 #endif
1855 
1856 
1857     if (value) {
1858         *value = 0;
1859     }
1860 
1861     if (!implicit_tag) {
1862       offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
1863       offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
1864     } else {
1865       gint32 remaining = tvb_reported_length_remaining(tvb, offset);
1866       len = remaining>0 ? remaining : 0;
1867     }
1868 
1869     first = tvb_get_guint8(tvb, offset);
1870     /* we can't handle integers > 64 bits */
1871     /* take into account the use case of a 64bits unsigned integer: you will have a 9th byte set to 0 */
1872     if ((len > 9) || ((len == 9) && (first != 0))) {
1873         if (hf_id >= 0) {
1874             header_field_info *hfinfo = proto_registrar_get_nth(hf_id);
1875 
1876             /* use the original field only if it is suitable for bytes */
1877             if (hfinfo->type != FT_BYTES)
1878                 hf_id = hf_ber_64bit_uint_as_bytes;
1879 
1880             proto_tree_add_bytes_format(tree, hf_id, tvb, offset, len, NULL,
1881                 "%s: 0x%s", hfinfo->name, tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, len));
1882         }
1883 
1884         offset += len;
1885         return offset;
1886     }
1887 
1888     val=0;
1889     if (len > 0) {
1890         /* extend sign bit for signed fields */
1891         enum ftenum type  = FT_INT32; /* Default to signed, is this correct? */
1892         if (hf_id >= 0) {
1893             type = proto_registrar_get_ftype(hf_id);
1894         }
1895         if (first & 0x80 && IS_FT_INT(type)) {
1896             val = -1;
1897         }
1898         if ((len > 1) && decode_warning_leading_zero_bits) {
1899             guint8 second = tvb_get_guint8(tvb, offset+1);
1900             if (((first == 0x00) && ((second & 0x80) == 0)) ||
1901                 ((first == 0xff) && ((second & 0x80) != 0))) {
1902                 used_too_many_bytes = TRUE;
1903             }
1904         }
1905         for (i=0; i<len; i++) {
1906             val = ((guint64)val<<8) | tvb_get_guint8(tvb, offset);
1907             offset++;
1908         }
1909     }
1910 
1911     actx->created_item = NULL;
1912 
1913     if (hf_id >= 0) {
1914         /*  */
1915         if ((len < 1) || (len > 9) || ((len == 9) && (first != 0))) {
1916           proto_tree_add_expert_format(
1917               tree, actx->pinfo, &ei_ber_error_length, tvb, offset-len, len,
1918               "BER Error: Can't handle integer length: %u",
1919               len);
1920         } else {
1921             header_field_info* hfi;
1922 
1923             hfi = proto_registrar_get_nth(hf_id);
1924             switch (hfi->type) {
1925             case FT_UINT8:
1926             case FT_UINT16:
1927             case FT_UINT24:
1928             case FT_UINT32:
1929                 actx->created_item = proto_tree_add_uint(tree, hf_id, tvb, offset-len, len, (guint32)val);
1930                 break;
1931             case FT_INT8:
1932             case FT_INT16:
1933             case FT_INT24:
1934             case FT_INT32:
1935                 actx->created_item = proto_tree_add_int(tree, hf_id, tvb, offset-len, len, (gint32)val);
1936                 break;
1937             case FT_INT64:
1938                 actx->created_item = proto_tree_add_int64(tree, hf_id, tvb, offset-len, len, val);
1939                 break;
1940             case FT_UINT64:
1941                 actx->created_item = proto_tree_add_uint64(tree, hf_id, tvb, offset-len, len, (guint64)val);
1942                 break;
1943             case FT_BYTES:
1944                 /*
1945                  * Some protocols have INTEGER fields that can store values
1946                  * larger than 64 bits and therefore have to use FT_BYTES.
1947                  * Values larger than 64 bits are handled above while smaller
1948                  * values are handled here.
1949                  */
1950                 actx->created_item = proto_tree_add_bytes_format(tree, hf_id, tvb, offset-len, len, NULL,
1951                         "%s: 0x%s", hfi->name, tvb_bytes_to_str(wmem_packet_scope(), tvb, offset-len, len));
1952                 break;
1953             default:
1954                 DISSECTOR_ASSERT_NOT_REACHED();
1955             }
1956 
1957             if (used_too_many_bytes) {
1958                 expert_add_info_format(
1959                     actx->pinfo, actx->created_item, &ei_ber_value_too_many_bytes,
1960                     "Value is encoded with too many bytes(9 leading zero or one bits), hf_abbr: %s",
1961                     hfi->abbrev);
1962             }
1963         }
1964     }
1965 
1966     if (value) {
1967         *value = val;
1968     }
1969 
1970     return offset;
1971 }
1972 
1973 int
dissect_ber_constrained_integer64(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint64 min_len,gint64 max_len,gint hf_id,gint64 * value)1974 dissect_ber_constrained_integer64(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint64 min_len, gint64 max_len, gint hf_id, gint64 *value)
1975 {
1976     gint64 val;
1977 
1978     offset = dissect_ber_integer64(implicit_tag, actx, tree, tvb, offset, hf_id, &val);
1979     if (value) {
1980         *value = val;
1981     }
1982 
1983     ber_check_value64 (val, min_len, max_len, actx, actx->created_item);
1984 
1985     return offset;
1986 }
1987 
1988 int
dissect_ber_integer(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,guint32 * value)1989 dissect_ber_integer(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, guint32 *value)
1990 {
1991     gint64 val;
1992 
1993     offset = dissect_ber_integer64(implicit_tag, actx, tree, tvb, offset, hf_id, &val);
1994     if (value) {
1995         *value = (guint32)val;
1996     }
1997 
1998     return offset;
1999 }
2000 
2001 int
dissect_ber_constrained_integer(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint32 min_len,gint32 max_len,gint hf_id,guint32 * value)2002 dissect_ber_constrained_integer(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, guint32 *value)
2003 {
2004     gint64 val;
2005 
2006     offset = dissect_ber_integer64(implicit_tag, actx, tree, tvb, offset, hf_id, &val);
2007     if (value) {
2008         *value = (guint32)val;
2009     }
2010 
2011     ber_check_value ((guint32)val, min_len, max_len, actx, actx->created_item);
2012 
2013     return offset;
2014 }
2015 
2016 int
dissect_ber_boolean(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,gboolean * value)2017 dissect_ber_boolean(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gboolean *value)
2018 {
2019     gint8    ber_class;
2020     gboolean pc;
2021     gint32   tag;
2022     guint32  len;
2023     guint8   val;
2024     header_field_info *hfi;
2025 
2026     if (!implicit_tag) {
2027         offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
2028         offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
2029         /*if (ber_class != BER_CLASS_UNI)*/
2030     } else {
2031         /* nothing to do here, yet */
2032     }
2033 
2034     val = tvb_get_guint8(tvb, offset);
2035     offset += 1;
2036 
2037     actx->created_item = NULL;
2038 
2039     if (hf_id >= 0) {
2040         hfi = proto_registrar_get_nth(hf_id);
2041         if (hfi->type == FT_BOOLEAN)
2042             actx->created_item = proto_tree_add_boolean(tree, hf_id, tvb, offset-1, 1, val);
2043         else
2044             actx->created_item = proto_tree_add_uint(tree, hf_id, tvb, offset-1, 1, val ? 1 : 0);
2045     }
2046 
2047     if (value) {
2048         *value = (val ? TRUE : FALSE);
2049     }
2050 
2051     return offset;
2052 }
2053 
2054 
2055 /* 8.5  Encoding of a real value */
2056 /* Somewhat tested */
2057 int
dissect_ber_real(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,double * value)2058 dissect_ber_real(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, double *value)
2059 {
2060     gint8    ber_class;
2061     gboolean pc;
2062     gint32   tag;
2063     guint32  val_length = 0, len_remain, end_offset;
2064     tvbuff_t *len_tvb;
2065     int      len_offset;
2066     int      len_len;
2067     double   val        = 0;
2068 
2069     if (!implicit_tag) {
2070         offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
2071         offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &val_length, NULL);
2072 
2073         end_offset = offset + val_length;
2074     } else {
2075         /* implicit tag so get from last tag/length */
2076         get_last_ber_identifier(&ber_class, &pc, &tag);
2077         get_last_ber_length(&val_length, NULL, &len_tvb, &len_offset, &len_len);
2078 
2079         end_offset = offset + val_length;
2080 
2081         /* Check is buffer has (at least) the expected length */
2082         len_remain = (guint32)tvb_reported_length_remaining(tvb, offset);
2083         if (len_remain < val_length) {
2084             /* error - this item runs past the end of the item containing it */
2085             ber_add_large_length_error(actx->pinfo, tree, tvb, offset, val_length, len_tvb, len_offset, len_len);
2086             return end_offset;
2087         }
2088     }
2089     /* 8.5.1    The encoding of a real value shall be primitive. */
2090     if(pc) {
2091       /*  Constructed (not primitive) */
2092       proto_tree_add_expert(
2093           tree, actx->pinfo, &ei_ber_real_not_primitive, tvb, offset - 2, 1);
2094     }
2095 
2096     val = asn1_get_real(tvb_get_ptr(tvb, offset, val_length), val_length);
2097     actx->created_item = proto_tree_add_double(tree, hf_id, tvb, end_offset - val_length, val_length, val);
2098 
2099     if (value)
2100         *value = val;
2101 
2102     return end_offset;
2103 
2104 }
2105 /* this function dissects a BER sequence
2106  */
2107 int
dissect_ber_sequence(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * parent_tree,tvbuff_t * tvb,int offset,const ber_sequence_t * seq,gint hf_id,gint ett_id)2108 dissect_ber_sequence(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
2109     gint8       classx;
2110     gboolean    pcx, ind   = 0, ind_field, imp_tag = FALSE;
2111     gint32      tagx;
2112     int         identifier_offset;
2113     int         identifier_len;
2114     guint32     lenx;
2115     proto_tree *tree       = parent_tree;
2116     proto_item *item       = NULL;
2117     proto_item *cause;
2118     int         end_offset = 0;
2119     int         hoffset;
2120     tvbuff_t   *next_tvb;
2121 
2122 #ifdef DEBUG_BER
2123 {
2124 const char *name;
2125 header_field_info *hfinfo;
2126 if (hf_id >= 0) {
2127 hfinfo = proto_registrar_get_nth(hf_id);
2128 name = hfinfo->name;
2129 } else {
2130 name = "unnamed";
2131 }
2132 if (tvb_reported_length_remaining(tvb, offset) > 3) {
2133 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_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
2134 } else {
2135 proto_tree_add_debug_text(tree, "SEQUENCE dissect_ber_sequence(%s) entered\n", name);
2136 }
2137 }
2138 #endif
2139     hoffset = offset;
2140     if (!implicit_tag) {
2141         offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
2142         offset = get_ber_length(tvb, offset, &lenx, NULL);
2143     } else {
2144         /* was implicit tag so just use the length of the tvb */
2145         lenx = tvb_reported_length_remaining(tvb, offset);
2146         end_offset = offset+lenx;
2147     }
2148     /* create subtree */
2149     if (hf_id >= 0) {
2150         if (parent_tree) {
2151             item = proto_tree_add_item(parent_tree, hf_id, tvb, hoffset, lenx + offset - hoffset, ENC_BIG_ENDIAN);
2152             tree = proto_item_add_subtree(item, ett_id);
2153         }
2154     }
2155     offset = hoffset;
2156 
2157     if (!implicit_tag) {
2158         /* first we must read the sequence header */
2159         identifier_offset = offset;
2160         offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
2161         identifier_len = offset - identifier_offset;
2162         offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
2163         if (ind) {
2164         /*  Fixed the length is correctly returned from dissect ber_length
2165           end_offset = tvb_reported_length(tvb);*/
2166           end_offset = offset + lenx -2;
2167         } else {
2168           end_offset = offset + lenx;
2169         }
2170 
2171         /* sanity check: we only handle Constructed Universal Sequences */
2172         if ((classx != BER_CLASS_APP) && (classx != BER_CLASS_PRI)) {
2173             if (!pcx
2174              || ((classx != BER_CLASS_UNI) || (tagx != BER_UNI_TAG_SEQUENCE))) {
2175                 tvb_ensure_bytes_exist(tvb, hoffset, 2);
2176                 cause = proto_tree_add_expert_format(
2177                     tree, actx->pinfo, &ei_ber_expected_sequence,
2178                     tvb, identifier_offset, identifier_len,
2179                     "BER Error: Sequence expected but class:%s(%d) %s tag:%d was unexpected",
2180                     val_to_str_const(classx, ber_class_codes, "Unknown"),
2181                     classx,
2182                     tfs_get_string(pcx, &tfs_constructed_primitive),
2183                     tagx);
2184                 if (decode_unexpected) {
2185                     proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2186                     dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2187                 }
2188                 return end_offset;
2189             }
2190         }
2191     }
2192     if(offset == end_offset){
2193         proto_item_append_text(item, " [0 length]");
2194     }
2195     /* loop over all entries until we reach the end of the sequence */
2196     while (offset < end_offset) {
2197         gint8    ber_class;
2198         gboolean pc;
2199         gint32   tag;
2200         guint32  len;
2201         int      eoffset, count;
2202 
2203         /*if (ind) {  this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2204                     but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2205             if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
2206                 /* If the first bytes is 00 00 of a indefenert length field it's a zero length field*/
2207                 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
2208                 dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
2209                 proto_item_append_text(item, " 0 items");
2210                 return end_offset;
2211                 /*
2212                 if (show_internal_ber_fields) {
2213                     proto_tree_add_expert(tree, pinfo, &ei_ber_error_seq_eoc, tvb, s_offset, offset+2, "ERROR WRONG SEQ EOC");
2214                 }
2215                 return end_offset;
2216                 */
2217             }
2218         /* } */
2219         hoffset = offset;
2220         /* read header and len for next field */
2221         offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
2222         offset = get_ber_length(tvb, offset, &len, &ind_field);
2223         eoffset = offset + len;
2224                 /* Make sure we move forward */
2225         if (eoffset <= hoffset)
2226             THROW(ReportedBoundsError);
2227 
2228         /*if (ind_field && (len == 2)) {
2229                 / disgusting indefinite length zero length field, what are these people doing /
2230             offset = eoffset;
2231             continue;
2232         }
2233         */
2234 
2235 ber_sequence_try_again:
2236         /* have we run out of known entries in the sequence ?*/
2237         if (!seq->func) {
2238             /* it was not,  move to the next one and try again */
2239             offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2240             dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
2241             cause = proto_tree_add_expert_format(
2242                 tree, actx->pinfo, &ei_ber_unknown_field_sequence,
2243                 tvb, hoffset, -1,
2244                 "BER Error: This field lies beyond the end of the known sequence definition.");
2245             if (decode_unexpected) {
2246                 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2247                 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2248             }
2249             offset = eoffset;
2250             continue;
2251         }
2252 
2253         /* Verify that this one is the one we want.
2254          * Skip check completely if ber_class == ANY
2255          * of if NOCHKTAG is set
2256          */
2257 /* XXX Bug in asn2wrs,
2258  * for   scope            [7]  Scope OPTIONAL,
2259  * it generates
2260  *   { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_scope },
2261  * and there should not be a NOTCHKTAG here
2262  */
2263         if ( ((seq->ber_class == BER_CLASS_CON) || (seq->ber_class == BER_CLASS_APP) || (seq->ber_class == BER_CLASS_PRI))
2264           && (!(seq->flags & BER_FLAGS_NOOWNTAG)) ) {
2265             if ( (seq->ber_class != BER_CLASS_ANY)
2266              &&  (seq->tag != -1)
2267              &&  ( (seq->ber_class != ber_class)
2268                 || (seq->tag != tag) ) ) {
2269                 /* it was not,  move to the next one and try again */
2270                 if (seq->flags & BER_FLAGS_OPTIONAL) {
2271                     /* well this one was optional so just skip to the next one and try again. */
2272                     seq++;
2273                     goto ber_sequence_try_again;
2274                 }
2275                 identifier_offset = hoffset;
2276                 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2277                 identifier_len = offset - identifier_offset;
2278                 dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
2279                 if (seq->ber_class == BER_CLASS_UNI) {
2280                     cause = proto_tree_add_expert_format(
2281                         tree, actx->pinfo, &ei_ber_sequence_field_wrong,
2282                         tvb, identifier_offset, identifier_len,
2283                         "BER Error: Wrong field in SEQUENCE: expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
2284                         val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2285                         seq->ber_class,
2286                         seq->tag,
2287                         val_to_str_ext_const(seq->tag, &ber_uni_tag_codes_ext, "Unknown"),
2288                         val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2289                         ber_class,
2290                         tag);
2291                 } else {
2292                     cause = proto_tree_add_expert_format(
2293                         tree, actx->pinfo, &ei_ber_sequence_field_wrong,
2294                         tvb, identifier_offset, identifier_len,
2295                         "BER Error: Wrong field in SEQUENCE: expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2296                         val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2297                         seq->ber_class,
2298                         seq->tag,
2299                         val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2300                         ber_class,
2301                         tag);
2302                 }
2303                 if (decode_unexpected) {
2304                     proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2305                     dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2306                 }
2307                 seq++;
2308                 offset = eoffset;
2309                 continue;
2310             }
2311         } else if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
2312             if ( (seq->ber_class != BER_CLASS_ANY)
2313               && (seq->tag != -1)
2314               && ( (seq->ber_class != ber_class)
2315                 || (seq->tag != tag) ) ) {
2316                 /* it was not,  move to the next one and try again */
2317                 if (seq->flags & BER_FLAGS_OPTIONAL) {
2318                     /* well this one was optional so just skip to the next one and try again. */
2319                     seq++;
2320                     goto ber_sequence_try_again;
2321                 }
2322 
2323                 identifier_offset = hoffset;
2324                 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2325                 identifier_len = offset - identifier_offset;
2326                 dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
2327                 if ( seq->ber_class == BER_CLASS_UNI) {
2328                     cause = proto_tree_add_expert_format(
2329                         tree, actx->pinfo, &ei_ber_sequence_field_wrong,
2330                         tvb, identifier_offset, identifier_len,
2331                         "BER Error: Wrong field in SEQUENCE: expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d",
2332                         val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2333                         seq->ber_class,
2334                         seq->tag,
2335                         val_to_str_ext_const(seq->tag, &ber_uni_tag_codes_ext, "Unknown"),
2336                         val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2337                         ber_class, tag);
2338                 } else {
2339                     cause = proto_tree_add_expert_format(
2340                         tree, actx->pinfo, &ei_ber_sequence_field_wrong,
2341                         tvb, identifier_offset, identifier_len,
2342                         "BER Error: Wrong field in SEQUENCE: expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2343                         val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2344                         seq->ber_class,
2345                         seq->tag,
2346                         val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2347                         ber_class,
2348                         tag);
2349                 }
2350                 if (decode_unexpected) {
2351                     proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2352                     dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2353                 }
2354                 seq++;
2355                 offset = eoffset;
2356                 continue;
2357             }
2358         }
2359 
2360         if (!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
2361             /* dissect header and len for field */
2362             if (ind_field && (len == 2)) {
2363                 /* This is a Zero length field */
2364                 next_tvb = ber_tvb_new_subset_length(tvb, offset, len);
2365                 hoffset = eoffset;
2366             } else {
2367                 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2368                 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
2369                 next_tvb = ber_tvb_new_subset_length(tvb, hoffset, eoffset - hoffset - (2 * ind_field));
2370             }
2371         } else {
2372             next_tvb = ber_tvb_new_subset_length(tvb, hoffset, eoffset - hoffset);
2373         }
2374 
2375 #if 0
2376         /* call the dissector for this field */
2377         if ((eoffset-hoffset) > length_remaining) {
2378         /* If the field is indefinite (i.e. we don't know the
2379          * length) of if the tvb is short, then just
2380          * give it all of the tvb and hope for the best.
2381          */
2382             next_tvb = tvb_new_subset_remaining(tvb, hoffset);
2383         } else {
2384 
2385         }
2386 #endif
2387 
2388 #ifdef DEBUG_BER
2389 {
2390 const char *name;
2391 header_field_info *hfinfo;
2392 if (hf_id >= 0) {
2393 hfinfo = proto_registrar_get_nth(hf_id);
2394 name = hfinfo->name;
2395 } else {
2396 name = "unnamed";
2397 }
2398 if (tvb_reported_length_remaining(next_tvb, 0) > 3) {
2399 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_guint8(next_tvb, 0), tvb_get_guint8(next_tvb, 1), tvb_get_guint8(next_tvb, 2));
2400 } else {
2401 proto_tree_add_debug_text(tree, "SEQUENCE dissect_ber_sequence(%s) calling subdissector\n", name);
2402 }
2403 }
2404 #endif
2405         if (next_tvb == NULL) {
2406             /* Assume that we have a malformed packet. */
2407             THROW(ReportedBoundsError);
2408         }
2409         imp_tag = FALSE;
2410         if (seq->flags & BER_FLAGS_IMPLTAG) {
2411             imp_tag = TRUE;
2412         }
2413 
2414         count = seq->func(imp_tag, next_tvb, 0, actx, tree, *seq->p_id);
2415 
2416 #ifdef DEBUG_BER
2417 {
2418 const char *name;
2419 header_field_info *hfinfo;
2420 if (hf_id >= 0) {
2421 hfinfo = proto_registrar_get_nth(hf_id);
2422 name = hfinfo->name;
2423 } else {
2424 name = "unnamed";
2425 }
2426 proto_tree_add_debug_text(tree, "SEQUENCE dissect_ber_sequence(%s) subdissector ate %d bytes\n", name, count);
2427 }
2428 #endif
2429         /* if it was optional and no bytes were eaten and it was */
2430         /* supposed to (len <> 0), just try again. */
2431         if ((len != 0) && (count == 0) && (seq->flags & BER_FLAGS_OPTIONAL)) {
2432             seq++;
2433             goto ber_sequence_try_again;
2434         /* move the offset to the beginning of the next sequenced item */
2435         }
2436         offset = eoffset;
2437         if (!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
2438             /* if we stripped the tag and length we should also strip the EOC is ind_len
2439              * Unless it's a zero length field (len = 2)
2440              */
2441             if ((ind_field == 1) && (len > 2))
2442             {
2443                 /* skip over EOC */
2444                 if (show_internal_ber_fields) {
2445                     proto_tree_add_item(tree, hf_ber_seq_field_eoc, tvb, offset-2, 2, ENC_NA);
2446                 }
2447             }
2448         }
2449         seq++;
2450     }
2451 
2452     /* if we didn't end up at exactly offset, then we ate too many bytes */
2453     if (offset != end_offset) {
2454         tvb_ensure_bytes_exist(tvb, offset-2, 2);
2455         proto_tree_add_expert_format(
2456             tree, actx->pinfo, &ei_ber_error_length, tvb, offset-2, 2,
2457             "BER Error: SEQUENCE is %d too many bytes long",
2458             offset - end_offset);
2459     }
2460     if (ind) {
2461         /*  need to eat this EOC
2462         end_offset = tvb_reported_length(tvb);*/
2463         end_offset += 2;
2464         if (show_internal_ber_fields) {
2465             proto_tree_add_item(tree, hf_ber_seq_eoc, tvb, end_offset-2, 2, ENC_NA);
2466         }
2467     }
2468     return end_offset;
2469 }
2470 
2471 /* This function dissects a BER set
2472  */
2473 int
dissect_ber_set(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * parent_tree,tvbuff_t * tvb,int offset,const ber_sequence_t * set,gint hf_id,gint ett_id)2474 dissect_ber_set(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *set, gint hf_id, gint ett_id) {
2475     gint8       classx;
2476     gboolean    pcx, ind = 0, ind_field, imp_tag;
2477     gint32      tagx;
2478     int         identifier_offset;
2479     int         identifier_len;
2480     guint32     lenx;
2481     int         len_offset;
2482     int         len_len;
2483     proto_tree *tree     = parent_tree;
2484     proto_item *item     = NULL;
2485     proto_item *cause;
2486     int         end_offset, s_offset;
2487     int         hoffset;
2488     tvbuff_t   *next_tvb;
2489     guint32     mandatory_fields = 0;
2490     guint8      set_idx;
2491     gboolean    first_pass;
2492     const ber_sequence_t *cset = NULL;
2493 
2494 #define MAX_SET_ELEMENTS 32
2495 
2496     s_offset = offset;
2497 
2498 #ifdef DEBUG_BER
2499     {
2500 const char *name;
2501 header_field_info *hfinfo;
2502 if (hf_id >= 0) {
2503 hfinfo = proto_registrar_get_nth(hf_id);
2504 name = hfinfo->name;
2505 } else {
2506 name = "unnamed";
2507 }
2508 if (tvb_reported_length_remaining(tvb, offset) > 3) {
2509 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_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
2510 } else {
2511 proto_tree_add_debug_text(tree, "SET dissect_ber_set(%s) entered\n", name);
2512 }
2513 }
2514 #endif
2515 
2516     if (!implicit_tag) {
2517         hoffset = offset;
2518         /* first we must read the sequence header */
2519         identifier_offset = offset;
2520         offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
2521         identifier_len = offset - identifier_offset;
2522         offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
2523         if (ind) {
2524         /*  Fixed the length is correctly returned from dissect ber_length
2525           end_offset = tvb_reported_length(tvb);*/
2526           end_offset = offset + lenx -2;
2527         } else {
2528           end_offset = offset + lenx;
2529         }
2530 
2531         /* sanity check: we only handle Constructed Universal Sets */
2532         if ((classx != BER_CLASS_APP) && (classx != BER_CLASS_PRI)) {
2533             if (!pcx
2534              || ((classx != BER_CLASS_UNI) || (tagx != BER_UNI_TAG_SET))) {
2535                 tvb_ensure_bytes_exist(tvb, hoffset, 2);
2536                 cause = proto_tree_add_expert_format(
2537                     tree, actx->pinfo, &ei_ber_expected_set,
2538                     tvb, identifier_offset, identifier_len,
2539                     "BER Error: SET expected but class:%s(%d) %s tag:%d was found",
2540                     val_to_str_const(classx, ber_class_codes, "Unknown"),
2541                     classx,
2542                     tfs_get_string(pcx, &tfs_constructed_primitive),
2543                     tagx);
2544                 if (decode_unexpected) {
2545                     proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2546                     dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2547                 }
2548                 return end_offset;
2549             }
2550         }
2551     } else {
2552         /* was implicit tag so just use the length of the tvb */
2553         lenx = tvb_reported_length_remaining(tvb, offset);
2554         end_offset = offset+lenx;
2555         identifier_offset = 0;
2556         identifier_len = 0;
2557     }
2558 
2559     /* create subtree */
2560     if (hf_id >= 0) {
2561         if (parent_tree) {
2562             item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, lenx, ENC_BIG_ENDIAN);
2563             tree = proto_item_add_subtree(item, ett_id);
2564         }
2565     }
2566 
2567     /* record the mandatory elements of the set so we can check we found everything at the end
2568        we can only record 32 elements for now ... */
2569     for (set_idx = 0; (set_idx < MAX_SET_ELEMENTS) && (cset = &set[set_idx])->func; set_idx++) {
2570 
2571         if (!(cset->flags & BER_FLAGS_OPTIONAL))
2572             mandatory_fields |= 1 << set_idx;
2573 
2574     }
2575 
2576     /* loop over all entries until we reach the end of the set */
2577     while (offset < end_offset) {
2578         gint8    ber_class;
2579         gboolean pc;
2580         gint32   tag;
2581         guint32  len;
2582         int      eoffset, count;
2583 
2584         /*if (ind) {  this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2585           but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2586 
2587             if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
2588                 if (show_internal_ber_fields) {
2589                     proto_tree_add_item(tree, hf_ber_seq_eoc, tvb, s_offset, offset+2, ENC_NA);
2590                 }
2591                 return end_offset;
2592             }
2593         /* } */
2594         hoffset = offset;
2595         /* read header and len for next field */
2596         identifier_offset = offset;
2597         offset  = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
2598         identifier_len = offset - identifier_offset;
2599         len_offset = offset;
2600         offset  = get_ber_length(tvb, offset, &len, &ind_field);
2601         len_len = offset - len_offset;
2602         eoffset = offset + len;
2603 
2604         if (len > (guint32)(end_offset - offset) || len > (guint32) tvb_reported_length_remaining(tvb, offset)) {
2605             ber_add_large_length_error(actx->pinfo, tree, tvb, offset, len, tvb, len_offset, len_len);
2606             return end_offset;
2607         }
2608 
2609         /* Look through the Set to see if this class/id exists and
2610          * hasn't been seen before
2611          * Skip check completely if ber_class == ANY
2612          * of if NOCHKTAG is set
2613          */
2614 
2615         for (first_pass = TRUE, cset = set, set_idx = 0; cset->func || first_pass; cset++, set_idx++) {
2616 
2617             /* we reset for a second pass when we will look for choices */
2618             if (!cset->func) {
2619                 first_pass = FALSE;
2620 
2621                 cset = set; /* reset to the beginning */
2622                 set_idx = 0;
2623                 /* If the set has no values, there is no point in trying again. */
2624                 if (!cset->func) {
2625                     break;
2626                 }
2627             }
2628 
2629             if ((first_pass && ((cset->ber_class == ber_class) && (cset->tag == tag))) ||
2630                 (!first_pass && ((cset->ber_class == BER_CLASS_ANY) && (cset->tag == -1))) ) /* choices */
2631             {
2632                 if (!(cset->flags & BER_FLAGS_NOOWNTAG) ) {
2633                     /* dissect header and len for field */
2634                     hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2635                     hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
2636                     next_tvb = ber_tvb_new_subset_length(tvb, hoffset, eoffset - hoffset - (2 * ind_field));
2637                 } else {
2638                     next_tvb = ber_tvb_new_subset_length(tvb, hoffset, eoffset - hoffset);
2639                 }
2640 
2641 
2642 #if 0
2643                 /* call the dissector for this field */
2644                 if    ((eoffset-hoffset)>length_remaining) {
2645                     /* If the field is indefinite (i.e. we don't know the
2646                      * length) of if the tvb is short, then just
2647                      * give it all of the tvb and hope for the best.
2648                      */
2649                     next_tvb = tvb_new_subset_remaining(tvb, hoffset);
2650                 } else {
2651 
2652                 }
2653 #endif
2654 
2655 #ifdef DEBUG_BER
2656 {
2657 const char *name;
2658 header_field_info *hfinfo;
2659 if (hf_id >= 0) {
2660 hfinfo = proto_registrar_get_nth(hf_id);
2661 name = hfinfo->name;
2662 } else {
2663 name = "unnamed";
2664 }
2665 if (tvb_reported_length_remaining(next_tvb, 0) > 3) {
2666 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_guint8(next_tvb, 0), tvb_get_guint8(next_tvb, 1), tvb_get_guint8(next_tvb, 2));
2667 } else {
2668 proto_tree_add_debug_text(tree, "SET dissect_ber_set(%s) calling subdissector\n", name);
2669 }
2670 }
2671 #endif
2672                 if (next_tvb == NULL) {
2673                     /* Assume that we have a malformed packet. */
2674                     THROW(ReportedBoundsError);
2675                 }
2676                 imp_tag = FALSE;
2677                 if ((cset->flags & BER_FLAGS_IMPLTAG))
2678                     imp_tag = TRUE;
2679                 count = cset->func(imp_tag, next_tvb, 0, actx, tree, *cset->p_id);
2680 
2681                 /* if we consumed some bytes,
2682                    or we knew the length was zero (during the first pass only) */
2683                 if (count || (first_pass && ((len == 0) || ((ind_field == 1) && (len == 2))))) {
2684                     /* we found it! */
2685                     if (set_idx < MAX_SET_ELEMENTS)
2686                         mandatory_fields &= ~(1 << set_idx);
2687 
2688                     offset = eoffset;
2689 
2690                     if (!(cset->flags & BER_FLAGS_NOOWNTAG) ) {
2691                         /* if we stripped the tag and length we should also strip the EOC is ind_len */
2692                         if (ind_field == 1) {
2693                             /* skip over EOC */
2694                             if (show_internal_ber_fields) {
2695                                 proto_tree_add_item(tree, hf_ber_set_field_eoc, tvb, offset, count, ENC_NA);
2696                             }
2697                         }
2698                     }
2699                     break;
2700                 }
2701             }
2702         }
2703 
2704         if (!cset->func) {
2705             /* we didn't find a match */
2706             cause = proto_tree_add_expert_format(
2707                 tree, actx->pinfo, &ei_ber_unknown_field_set,
2708                 tvb, identifier_offset, identifier_len,
2709                 "BER Error: Unknown field in SET class:%s(%d) tag:%d",
2710                 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2711                 ber_class,
2712                 tag);
2713             if (decode_unexpected) {
2714                 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2715                 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2716             }
2717             offset = eoffset;
2718         }
2719     }
2720 
2721     if (mandatory_fields) {
2722 
2723         /* OK - we didn't find some of the elements we expected */
2724 
2725         for (set_idx = 0; (set_idx < MAX_SET_ELEMENTS) && (cset = &set[set_idx])->func; set_idx++) {
2726             if (mandatory_fields & (1U << set_idx)) {
2727                 /* here is something we should have seen - but didn't! */
2728                 proto_tree_add_expert_format(
2729                     tree, actx->pinfo, &ei_ber_missing_field_set,
2730                     tvb, identifier_offset, identifier_len,
2731                     "BER Error: Missing field in SET class:%s(%d) tag:%d expected",
2732                     val_to_str_const(cset->ber_class, ber_class_codes, "Unknown"),
2733                     cset->ber_class,
2734                     cset->tag);
2735             }
2736 
2737         }
2738     }
2739 
2740     /* if we didn't end up at exactly offset, then we ate too many bytes */
2741     if (offset != end_offset) {
2742         tvb_ensure_bytes_exist(tvb, offset-2, 2);
2743         proto_tree_add_expert_format(
2744             tree, actx->pinfo, &ei_ber_error_length, tvb, offset-2, 2,
2745             "BER Error: SET is %d too many bytes long",
2746             offset - end_offset);
2747     }
2748 
2749     if (ind) {
2750         /*  need to eat this EOC
2751           end_offset = tvb_reported_length(tvb);*/
2752         end_offset += 2;
2753         if (show_internal_ber_fields) {
2754             proto_tree_add_item(tree, hf_ber_set_eoc, tvb, end_offset-2, 2, ENC_NA);
2755         }
2756     }
2757 
2758     return end_offset;
2759 
2760 }
2761 
2762 #ifdef DEBUG_BER
2763 #define DEBUG_BER_CHOICE
2764 #endif
2765 
2766 int
dissect_ber_choice(asn1_ctx_t * actx,proto_tree * parent_tree,tvbuff_t * tvb,int offset,const ber_choice_t * choice,gint hf_id,gint ett_id,gint * branch_taken)2767 dissect_ber_choice(asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_choice_t *choice, gint hf_id, gint ett_id, gint *branch_taken)
2768 {
2769     gint8       ber_class;
2770     gboolean    pc, ind, imp_tag = FALSE;
2771     gint32      tag;
2772     int         identifier_offset;
2773     int         identifier_len;
2774     guint32     len;
2775     proto_tree *tree = parent_tree;
2776     proto_item *item = NULL;
2777     int         end_offset, start_offset, count;
2778     int         hoffset = offset;
2779     gint        length;
2780     tvbuff_t   *next_tvb;
2781     gboolean    first_pass;
2782     header_field_info  *hfinfo;
2783     const ber_choice_t *ch;
2784 
2785 #ifdef DEBUG_BER_CHOICE
2786 {
2787 const char *name;
2788 if (hf_id >= 0) {
2789 hfinfo = proto_registrar_get_nth(hf_id);
2790 name = hfinfo->name;
2791 } else {
2792 name = "unnamed";
2793 }
2794 if (tvb_reported_length_remaining(tvb, offset) > 3) {
2795 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_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
2796 } else {
2797 proto_tree_add_debug_text(tree, "CHOICE dissect_ber_choice(%s) entered len:%d\n", name, tvb_reported_length_remaining(tvb, offset));
2798 }
2799 }
2800 #endif
2801 
2802     start_offset = offset;
2803 
2804     if (branch_taken) {
2805         *branch_taken = -1;
2806     }
2807 
2808     if (tvb_reported_length_remaining(tvb, offset) == 0) {
2809         proto_tree_add_expert(
2810             parent_tree, actx->pinfo, &ei_ber_empty_choice, tvb, offset, 0);
2811         return offset;
2812     }
2813 
2814     /* read header and len for choice field */
2815     identifier_offset = offset;
2816     offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
2817     identifier_len = offset - identifier_offset;
2818     offset = get_ber_length(tvb, offset, &len, &ind);
2819     end_offset = offset + len ;
2820 
2821     /* Some sanity checks.
2822      * The hf field passed to us MUST be an integer type
2823      */
2824     if (hf_id >= 0) {
2825         hfinfo = proto_registrar_get_nth(hf_id);
2826         switch (hfinfo->type) {
2827         case FT_UINT8:
2828         case FT_UINT16:
2829         case FT_UINT24:
2830         case FT_UINT32:
2831             break;
2832         default:
2833             proto_tree_add_expert_format(
2834                 tree, actx->pinfo, &ei_hf_field_not_integer_type,
2835                 tvb, identifier_offset, identifier_len,
2836                 "BER Error: dissect_ber_choice(): frame:%u offset:%d Was passed an HF field that was not integer type : %s",
2837                 actx->pinfo->num, offset, hfinfo->abbrev);
2838             return end_offset;
2839         }
2840     }
2841 
2842     /* loop over all entries until we find the right choice or
2843        run out of entries */
2844     ch = choice;
2845     first_pass = TRUE;
2846     while (ch->func || first_pass) {
2847         if (branch_taken) {
2848             (*branch_taken)++;
2849         }
2850         /* we reset for a second pass when we will look for choices */
2851         if (!ch->func) {
2852             first_pass = FALSE;
2853             ch = choice; /* reset to the beginning */
2854             if (branch_taken) {
2855                 *branch_taken = -1;
2856             }
2857             continue;
2858         }
2859 
2860 #ifdef DEBUG_BER_CHOICE
2861 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);
2862 #endif
2863         if ( (first_pass
2864            && (((ch->ber_class == ber_class) && (ch->tag == tag))
2865             || ((ch->ber_class == ber_class) && (ch->tag == -1) && (ch->flags & BER_FLAGS_NOOWNTAG))))
2866           || (!first_pass && (((ch->ber_class == BER_CLASS_ANY) && (ch->tag == -1)))) /* we failed on the first pass so now try any choices */
2867         ) {
2868             if (!(ch->flags & BER_FLAGS_NOOWNTAG)) {
2869                 /* dissect header and len for field */
2870                 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, start_offset, NULL, NULL, NULL);
2871                 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
2872                 start_offset = hoffset;
2873                 if (ind) {
2874                     length = len - 2;
2875                 } else {
2876                     length = len;
2877                 }
2878             } else {
2879                 length = end_offset- hoffset;
2880             }
2881             /* create subtree */
2882             if (hf_id >= 0) {
2883                 if (parent_tree) {
2884                     item = proto_tree_add_uint(parent_tree, hf_id, tvb, hoffset, end_offset - hoffset, ch->value);
2885                     tree = proto_item_add_subtree(item, ett_id);
2886                 }
2887             }
2888 
2889 #ifdef REMOVED
2890             /* This is bogus and makes the OID_1.0.9506.1.1.cap file
2891              * in Steven J Schaeffer's email of 2005-09-12 fail to dissect
2892              * properly.  Maybe we should get rid of 'first_pass'
2893              * completely.
2894              * It was added as a qad workaround for some problem CMIP
2895              * traces anyway.
2896              * God, this file is a mess and it is my fault. /ronnie
2897              */
2898             if (first_pass)
2899                 next_tvb = ber_tvb_new_subset_length(tvb, hoffset, length);
2900             else
2901                 next_tvb = tvb; /* we didn't make selection on this class/tag so pass it on */
2902 #endif
2903             next_tvb = ber_tvb_new_subset_length(tvb, hoffset, length);
2904 
2905 
2906 #ifdef DEBUG_BER_CHOICE
2907 {
2908 const char *name;
2909 if (hf_id >= 0) {
2910 hfinfo = proto_registrar_get_nth(hf_id);
2911 name = hfinfo->name;
2912 } else {
2913 name = "unnamed";
2914 }
2915 if (tvb_reported_length_remaining(next_tvb, 0) > 3) {
2916 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_guint8(next_tvb, 0), tvb_get_guint8(next_tvb, 1), tvb_get_guint8(next_tvb, 2));
2917 } else {
2918 proto_tree_add_debug_text(tree, "CHOICE dissect_ber_choice(%s) calling subdissector len:%d\n", name, tvb_reported_length(next_tvb));
2919 }
2920 }
2921 #endif
2922             if (next_tvb == NULL) {
2923                 /* Assume that we have a malformed packet. */
2924                 THROW(ReportedBoundsError);
2925             }
2926             imp_tag = FALSE;
2927             if ((ch->flags & BER_FLAGS_IMPLTAG))
2928                 imp_tag = TRUE;
2929             count = ch->func(imp_tag, next_tvb, 0, actx, tree, *ch->p_id);
2930 #ifdef DEBUG_BER_CHOICE
2931 {
2932 const char *name;
2933 if (hf_id >= 0) {
2934 hfinfo = proto_registrar_get_nth(hf_id);
2935 name = hfinfo->name;
2936 } else {
2937 name = "unnamed";
2938 }
2939 proto_tree_add_debug_text(tree, "CHOICE dissect_ber_choice(%s) subdissector ate %d bytes\n", name, count);
2940 }
2941 #endif
2942             if ((count == 0) && (((ch->ber_class == ber_class) && (ch->tag == -1) && (ch->flags & BER_FLAGS_NOOWNTAG)) || !first_pass)) {
2943                 /* wrong one, break and try again */
2944                 ch++;
2945 #ifdef DEBUG_BER_CHOICE
2946 {
2947 const char *name;
2948 if (hf_id >= 0) {
2949 hfinfo = proto_registrar_get_nth(hf_id);
2950 name = hfinfo->name;
2951 } else {
2952 name = "unnamed";
2953 }
2954 proto_tree_add_debug_text(tree, "CHOICE dissect_ber_choice(%s) trying again\n", name);
2955 }
2956 #endif
2957                 continue;
2958             }
2959             if (!(ch->flags & BER_FLAGS_NOOWNTAG)) {
2960                 if (ind) {
2961                 /* we are traversing a indfinite length choice where we did not pass the tag length */
2962                 /* we need to eat the EOC */
2963                     if (show_internal_ber_fields) {
2964                         proto_tree_add_item(tree, hf_ber_choice_eoc, tvb, end_offset-2, 2, ENC_NA);
2965                     }
2966                 }
2967             }
2968             return end_offset;
2969         }
2970         ch++;
2971     }
2972     if (branch_taken) {
2973         /* none of the branches were taken so set the param
2974            back to -1 */
2975         *branch_taken = -1;
2976     }
2977 
2978 #ifdef REMOVED
2979     /*XXX here we should have another flag to the CHOICE to distinguish
2980      * between the case when we know it is a mandatory   or if the CHOICE is optional == no arm matched */
2981 
2982     /* oops no more entries and we still haven't found
2983      * our guy :-(
2984      */
2985     proto_tree_add_expert(
2986         tree, actx->pinfo, &ei_ber_choice_not_found, tvb, offset, len);
2987     return end_offset;
2988 #endif
2989 
2990     return start_offset;
2991 }
2992 
2993 #if 0
2994 /* this function dissects a BER GeneralString
2995  */
2996 int
2997 dissect_ber_GeneralString(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, int name_len)
2998 {
2999     gint8       ber_class;
3000     gboolean    pc;
3001     gint32      tag;
3002     int         identifier_offset;
3003     int         identifier_len;
3004     guint32     len;
3005     int         end_offset;
3006     int         hoffset;
3007     char        str_arr[256];
3008     guint32     max_len;
3009     char       *str;
3010     proto_item *cause;
3011 
3012     str = str_arr;
3013     max_len = 255;
3014     if (name_string) {
3015         str = name_string;
3016         max_len = name_len;
3017     }
3018 
3019     hoffset = offset;
3020     /* first we must read the GeneralString header */
3021     identifier_offset = offset;
3022     offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
3023     identifier_len = offset - identifier_offset;
3024     offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
3025     end_offset = offset + len;
3026 
3027     /* sanity check: we only handle Universal GeneralString*/
3028     if ( (ber_class != BER_CLASS_UNI)
3029       || (tag != BER_UNI_TAG_GENSTR) ) {
3030         tvb_ensure_bytes_exist(tvb, hoffset, 2);
3031         cause = proto_tree_add_expert_format(
3032             tree, actx->pinfo, &ei_ber_expected_general_string,
3033             tvb, identifier_offset, identifier_len,
3034             "BER Error: GeneralString expected but class:%s(%d) %s tag:%d was unexpected",
3035             val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3036             ber_class, tfs_get_string(pc, &tfs_constructed_primitive),
3037             tag);
3038         if (decode_unexpected) {
3039             proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3040             dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3041         }
3042         return end_offset;
3043     }
3044 
3045     if (len >= (max_len - 1)) {
3046         len = max_len - 1;
3047     }
3048 
3049     tvb_memcpy(tvb, str, offset, len);
3050     str[len]=0;
3051 
3052     if (hf_id >= 0) {
3053         proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
3054     }
3055 
3056     return end_offset;
3057 }
3058 #endif
3059 
3060 int
dissect_ber_constrained_restricted_string(gboolean implicit_tag,gint32 type,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint32 min_len,gint32 max_len,gint hf_id,tvbuff_t ** out_tvb)3061 dissect_ber_constrained_restricted_string(gboolean implicit_tag, gint32 type,  asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, tvbuff_t **out_tvb) {
3062     gint8       ber_class;
3063     gboolean    pc;
3064     gint32      tag;
3065     int         identifier_offset;
3066     int         identifier_len;
3067     guint32     len;
3068     int         eoffset;
3069     int         hoffset = offset;
3070     proto_item *cause;
3071 
3072 #ifdef DEBUG_BER
3073 {
3074 const char *name;
3075 header_field_info *hfinfo;
3076 if (hf_id >= 0) {
3077 hfinfo = proto_registrar_get_nth(hf_id);
3078 name = hfinfo->name;
3079 } else {
3080 name = "unnamed";
3081 }
3082 if (tvb_reported_length_remaining(tvb, offset) > 3) {
3083 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_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
3084 } else {
3085 proto_tree_add_debug_text(tree, "RESTRICTED STRING dissect_ber_octet_string(%s) entered\n", name);
3086 }
3087 }
3088 #endif
3089 
3090     if (!implicit_tag) {
3091         identifier_offset = offset;
3092         offset  = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
3093         identifier_len = offset - identifier_offset;
3094         offset  = get_ber_length(tvb, offset, &len, NULL);
3095         eoffset = offset + len;
3096 
3097         /* sanity check */
3098         if ( (ber_class != BER_CLASS_UNI)
3099           || (tag != type) ) {
3100             tvb_ensure_bytes_exist(tvb, hoffset, 2);
3101             cause = proto_tree_add_expert_format(
3102                 tree, actx->pinfo, &ei_ber_expected_string,
3103                 tvb, identifier_offset, identifier_len,
3104                 "BER Error: String with tag=%d expected but class:%s(%d) %s tag:%d was unexpected",
3105                 type,
3106                 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3107                 ber_class, tfs_get_string(pc, &tfs_constructed_primitive),
3108                 tag);
3109             if (decode_unexpected) {
3110                 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3111                 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3112             }
3113             return eoffset;
3114         }
3115     }
3116 
3117     /* 8.21.3 */
3118     return dissect_ber_constrained_octet_string(implicit_tag, actx, tree, tvb, hoffset, min_len, max_len, hf_id, out_tvb);
3119 }
3120 
dissect_ber_restricted_string(gboolean implicit_tag,gint32 type,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,tvbuff_t ** out_tvb)3121 int dissect_ber_restricted_string(gboolean implicit_tag, gint32 type, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb)
3122 {
3123     return dissect_ber_constrained_restricted_string(implicit_tag, type, actx, tree, tvb, offset, NO_BOUND, NO_BOUND, hf_id, out_tvb);
3124 }
3125 
3126 int
dissect_ber_GeneralString(asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,char * name_string,guint name_len)3127 dissect_ber_GeneralString(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, guint name_len)
3128 {
3129     tvbuff_t *out_tvb = NULL;
3130     gint      tvb_len;
3131 
3132     offset = dissect_ber_restricted_string(FALSE, BER_UNI_TAG_GeneralString, actx, tree, tvb, offset, hf_id, (name_string) ? &out_tvb : NULL);
3133 
3134     if (name_string) {
3135         /*
3136          * XXX - do we want to just get what's left in the tvbuff
3137          * if the full length isn't available in the tvbuff, or
3138          * do we want to throw an exception?
3139          */
3140         if (out_tvb) {
3141             tvb_len = tvb_reported_length(out_tvb);
3142             if ((guint)tvb_len >= name_len) {
3143                 tvb_memcpy(out_tvb, (guint8*)name_string, 0, name_len-1);
3144                 name_string[name_len-1] = '\0';
3145             } else {
3146                 tvb_memcpy(out_tvb, (guint8*)name_string, 0, tvb_len);
3147                 name_string[tvb_len] = '\0';
3148             }
3149         }
3150     }
3151 
3152     return offset;
3153 }
3154 
3155 /* 8.19 Encoding of a relative or absolute object identifier value.
3156  */
3157 static int
dissect_ber_any_oid(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,tvbuff_t ** value_tvb,gboolean is_absolute)3158 dissect_ber_any_oid(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **value_tvb, gboolean is_absolute)
3159 {
3160     gint8        ber_class;
3161     gboolean     pc;
3162     gint32       tag;
3163     int          identifier_offset;
3164     int          identifier_len;
3165     guint32      len;
3166     int          eoffset;
3167     int          hoffset;
3168     const char  *str;
3169     proto_item  *cause;
3170     const gchar *name;
3171     header_field_info *hfi;
3172 
3173 #ifdef DEBUG_BER
3174 {
3175 header_field_info *hfinfo;
3176 if (hf_id >= 0) {
3177 hfinfo = proto_registrar_get_nth(hf_id);
3178 name = hfinfo->name;
3179 } else {
3180 name = "unnamed";
3181 }
3182 if (tvb_reported_length_remaining(tvb, offset) > 3) {
3183 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_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
3184 } else {
3185 proto_tree_add_debug_text(tree, "OBJECT IDENTIFIER dissect_ber_any_oid(%s) entered\n", name);
3186 }
3187 }
3188 #endif
3189 
3190     if (!implicit_tag) {
3191         hoffset = offset;
3192         /* sanity check */
3193         identifier_offset = offset;
3194         offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
3195         identifier_len = offset - identifier_offset;
3196         offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
3197         eoffset = offset + len;
3198         if ( (ber_class != BER_CLASS_UNI)
3199           || (is_absolute && tag != BER_UNI_TAG_OID)
3200           || (!is_absolute && tag != BER_UNI_TAG_RELATIVE_OID) ) {
3201                 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3202             cause = proto_tree_add_expert_format(
3203                 tree, actx->pinfo, &ei_ber_expected_object_identifier,
3204                 tvb, identifier_offset, identifier_len,
3205                 "BER Error: Object Identifier expected but class:%s(%d) %s tag:%d was unexpected",
3206                 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3207                 ber_class,
3208                 tfs_get_string(pc, &tfs_constructed_primitive),
3209                 tag);
3210             if (decode_unexpected) {
3211                 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3212                 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3213             }
3214             return eoffset;
3215         }
3216     } else {
3217         len = tvb_reported_length_remaining(tvb, offset);
3218         eoffset = offset+len;
3219     }
3220 
3221     actx->created_item = NULL;
3222     hfi = proto_registrar_get_nth(hf_id);
3223     if ((is_absolute && hfi->type == FT_OID) || (!is_absolute && hfi->type == FT_REL_OID)) {
3224         actx->created_item = proto_tree_add_item(tree, hf_id, tvb, offset, len, ENC_BIG_ENDIAN);
3225     } else if (IS_FT_STRING(hfi->type)) {
3226         str = oid_encoded2string(wmem_packet_scope(), tvb_get_ptr(tvb, offset, len), len);
3227         actx->created_item = proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
3228         if (actx->created_item) {
3229             /* see if we know the name of this oid */
3230             name = oid_resolved_from_encoded(wmem_packet_scope(), tvb_get_ptr(tvb, offset, len), len);
3231             if (name) {
3232                 proto_item_append_text(actx->created_item, " (%s)", name);
3233             }
3234         }
3235     } else {
3236         DISSECTOR_ASSERT_NOT_REACHED();
3237     }
3238 
3239     if (value_tvb)
3240         *value_tvb = ber_tvb_new_subset_length(tvb, offset, len);
3241 
3242     return eoffset;
3243 }
3244 
3245 static int
dissect_ber_any_oid_str(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,const char ** value_stringx,gboolean is_absolute)3246 dissect_ber_any_oid_str(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, const char **value_stringx, gboolean is_absolute)
3247 {
3248     tvbuff_t *value_tvb = NULL;
3249     guint     length;
3250 
3251     offset = dissect_ber_any_oid(implicit_tag, actx, tree, tvb, offset, hf_id, (value_stringx) ? &value_tvb : NULL, is_absolute);
3252 
3253     if (value_stringx) {
3254         if (value_tvb && (length = tvb_reported_length(value_tvb))) {
3255             *value_stringx = oid_encoded2string(wmem_packet_scope(), tvb_get_ptr(value_tvb, 0, length), length);
3256         } else {
3257             *value_stringx = "";
3258         }
3259     }
3260 
3261     return offset;
3262 }
3263 
3264 /* 8.19 Encoding of a relative object identifier value.
3265  */
3266 int
dissect_ber_relative_oid(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,tvbuff_t ** value_tvb)3267 dissect_ber_relative_oid(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **value_tvb)
3268 {
3269     return dissect_ber_any_oid(implicit_tag, actx, tree, tvb, offset, hf_id, value_tvb, FALSE);
3270 }
3271 
3272 int
dissect_ber_relative_oid_str(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,const char ** value_stringx)3273 dissect_ber_relative_oid_str(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, const char **value_stringx)
3274 {
3275     return dissect_ber_any_oid_str(implicit_tag, actx, tree, tvb, offset, hf_id, value_stringx, FALSE);
3276 }
3277 
3278 /* 8.19 Encoding of an object identifier value.
3279  */
3280 int
dissect_ber_object_identifier(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,tvbuff_t ** value_tvb)3281 dissect_ber_object_identifier(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **value_tvb)
3282 {
3283     return dissect_ber_any_oid(implicit_tag, actx, tree, tvb, offset, hf_id, value_tvb, TRUE);
3284 }
3285 
3286 int
dissect_ber_object_identifier_str(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,const char ** value_stringx)3287 dissect_ber_object_identifier_str(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, const char **value_stringx)
3288 {
3289     return dissect_ber_any_oid_str(implicit_tag, actx, tree, tvb, offset, hf_id, value_stringx, TRUE);
3290 }
3291 
3292 #ifdef DEBUG_BER
3293 #define DEBUG_BER_SQ_OF
3294 #endif
3295 
3296 static int
dissect_ber_sq_of(gboolean implicit_tag,gint32 type,asn1_ctx_t * actx,proto_tree * parent_tree,tvbuff_t * tvb,int offset,gint32 min_len,gint32 max_len,const ber_sequence_t * seq,gint hf_id,gint ett_id)3297 dissect_ber_sq_of(gboolean implicit_tag, gint32 type, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
3298     gint8              classx;
3299     gboolean           pcx, ind = FALSE, ind_field;
3300     gint32             tagx;
3301     int                identifier_offset;
3302     int                identifier_len;
3303     guint32            lenx;
3304 
3305     proto_tree        *tree     = parent_tree;
3306     proto_item        *item     = NULL;
3307     proto_item        *causex;
3308     int                cnt, hoffsetx, end_offset;
3309     gboolean           have_cnt;
3310     header_field_info *hfi;
3311     tvbuff_t          *next_tvb;
3312 
3313 #ifdef DEBUG_BER_SQ_OF
3314 {
3315 const char *name;
3316 header_field_info *hfinfo;
3317 if (hf_id >= 0) {
3318 hfinfo = proto_registrar_get_nth(hf_id);
3319 name = hfinfo->name;
3320 } else {
3321 name = "unnamed";
3322 }
3323 if (tvb_reported_length_remaining(tvb,offset) > 3) {
3324 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_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
3325 } else {
3326 proto_tree_add_debug_text(tree, "SQ OF dissect_ber_sq_of(%s) entered\n", name);
3327 }
3328 }
3329 #endif
3330 
3331     if (!implicit_tag) {
3332         hoffsetx = offset;
3333         /* first we must read the sequence header */
3334         identifier_offset = offset;
3335         offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
3336         identifier_len = offset - identifier_offset;
3337         offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
3338         end_offset = offset + lenx;
3339 
3340         /* sanity check: we only handle Constructed Universal Sequences */
3341         if ((classx != BER_CLASS_APP) && (classx != BER_CLASS_PRI)) {
3342             if (!pcx
3343              || ((classx != BER_CLASS_UNI) || (tagx != type))) {
3344                 tvb_ensure_bytes_exist(tvb, hoffsetx, 2);
3345                 causex = proto_tree_add_expert_format(
3346                     tree, actx->pinfo,
3347                     (type == BER_UNI_TAG_SEQUENCE) ? &ei_ber_expected_set : &ei_ber_expected_sequence,
3348                     tvb, identifier_offset, identifier_len,
3349                     "BER Error: %s OF expected but class:%s(%d) %s tag:%d was unexpected",
3350                     (type == BER_UNI_TAG_SEQUENCE) ? "SET" : "SEQUENCE",
3351                     val_to_str_const(classx, ber_class_codes, "Unknown"),
3352                     classx, tfs_get_string(pcx, &tfs_constructed_primitive),
3353                     tagx);
3354                 if (decode_unexpected) {
3355                     proto_tree *unknown_tree = proto_item_add_subtree(causex, ett_ber_unknown);
3356                     dissect_unknown_ber(actx->pinfo, tvb, hoffsetx, unknown_tree);
3357                 }
3358                 return end_offset;
3359             }
3360         }
3361     } else {
3362         /* the tvb length should be correct now nope we could be coming from an implicit choice or sequence, thus we
3363         read the items we match and return the length*/
3364         lenx = tvb_reported_length_remaining(tvb, offset);
3365         end_offset = offset + lenx;
3366     }
3367 
3368     /* count number of items */
3369     cnt = 0;
3370     have_cnt = FALSE;
3371     hoffsetx = offset;
3372     /* only count the number of items IFF we have the full blob,
3373      * else this will just generate a [short frame] before we even start
3374      * dissecting a single item.
3375      */
3376     /* XXX Do we really need to count them at all ?  ronnie */
3377     if (tvb_captured_length_remaining(tvb, offset) == tvb_reported_length_remaining(tvb, offset)) {
3378         have_cnt = TRUE;
3379         while (offset < end_offset) {
3380             guint32 len;
3381             gint    s_offset;
3382 
3383             s_offset = offset;
3384 
3385             /*if (ind) {  this sequence of was of indefinite length, if this is implicit indefinite impossible maybe
3386               but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
3387                 if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
3388                     break;
3389                 }
3390             /* } */
3391 
3392             /* read header and len for next field */
3393             offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
3394             offset = get_ber_length(tvb, offset, &len, &ind);
3395             /* best place to get real length of implicit sequence of or set of is here... */
3396             /* adjust end_offset if we find somthing that doesn't match */
3397             offset += len;
3398             cnt++;
3399             if (offset <= s_offset) {
3400                 /* Underflow - give up; this can happen with a very large
3401                  * length.
3402                  */
3403                 have_cnt = FALSE;
3404                 cnt = 0;
3405                 break;
3406             }
3407         }
3408     }
3409     offset = hoffsetx;
3410 
3411     /* create subtree */
3412     if (hf_id >= 0) {
3413         hfi = proto_registrar_get_nth(hf_id);
3414         if (parent_tree) {
3415             if (hfi->type == FT_NONE) {
3416                 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, lenx, ENC_BIG_ENDIAN);
3417                 proto_item_append_text(item, ":");
3418             } else {
3419                 if (have_cnt) {
3420                     item = proto_tree_add_uint(parent_tree, hf_id, tvb, offset, lenx, cnt);
3421                     proto_item_append_text(item, (cnt == 1) ? " item" : " items");
3422                 } else
3423                     item = proto_tree_add_uint_format_value(parent_tree, hf_id, tvb, offset, lenx, cnt, "unknown number of items");
3424             }
3425             tree = proto_item_add_subtree(item, ett_id);
3426             ber_check_items (cnt, min_len, max_len, actx, item);
3427         }
3428     }
3429 
3430     /* loop over all entries until we reach the end of the sequence */
3431     while (offset < end_offset) {
3432         gint8       ber_class;
3433         gboolean    pc;
3434         gint32      tag;
3435         guint32     len;
3436         int         eoffset;
3437         int         hoffset;
3438         proto_item *cause;
3439         gboolean    imp_tag;
3440 
3441         hoffset = offset;
3442         /*if (ind) {  this sequence was of indefinite length, if this is implicit indefinite impossible maybe
3443           but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
3444             if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
3445                 if (show_internal_ber_fields) {
3446                     proto_tree_add_item(tree, hf_ber_seq_of_eoc, tvb, hoffset, end_offset-hoffset, ENC_NA);
3447                 }
3448                 return offset+2;
3449             }
3450         /*}*/
3451         /* read header and len for next field */
3452         identifier_offset = offset;
3453         offset  = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
3454         identifier_len = offset - identifier_offset;
3455         offset  = get_ber_length(tvb, offset, &len, &ind_field);
3456         eoffset = offset + len;
3457                 /* Make sure we move forward */
3458         if (eoffset <= hoffset)
3459             THROW(ReportedBoundsError);
3460 
3461         if ((ber_class == BER_CLASS_UNI) && (tag == BER_UNI_TAG_EOC)) {
3462             /* This is a zero length sequence of*/
3463             hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
3464             dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3465             return eoffset;
3466         }
3467         /* verify that this one is the one we want */
3468         /* ahup if we are implicit then we return to the upper layer how much we have used */
3469         if (seq->ber_class != BER_CLASS_ANY) {
3470           if ((seq->ber_class != ber_class)
3471            || (seq->tag != tag) ) {
3472             if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
3473                 if ( seq->ber_class == BER_CLASS_UNI) {
3474                     cause = proto_tree_add_expert_format(
3475                         tree, actx->pinfo, &ei_ber_sequence_field_wrong,
3476                         tvb, identifier_offset, identifier_len,
3477                         "BER Error: Wrong field in SEQUENCE OF: expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d",
3478                         val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
3479                         seq->ber_class,
3480                         seq->tag,
3481                         val_to_str_ext_const(seq->tag, &ber_uni_tag_codes_ext, "Unknown"),
3482                         val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3483                         ber_class, tag);
3484                 } else {
3485                     cause = proto_tree_add_expert_format(
3486                         tree, actx->pinfo, &ei_ber_sequence_field_wrong,
3487                         tvb, identifier_offset, identifier_len,
3488                         "BER Error: Wrong field in SEQUENCE OF: expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
3489                         val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
3490                         seq->ber_class,
3491                         seq->tag,
3492                         val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3493                         ber_class,
3494                         tag);
3495                 }
3496                 if (decode_unexpected) {
3497                     proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3498                     dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3499                 }
3500                 offset = eoffset;
3501                 continue;
3502                 /* wrong.... */
3503             }
3504           }
3505         }
3506 
3507         if (!(seq->flags & BER_FLAGS_NOOWNTAG) && !(seq->flags & BER_FLAGS_IMPLTAG)) {
3508             /* dissect header and len for field */
3509             hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
3510             hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3511         }
3512         if ((seq->flags == BER_FLAGS_IMPLTAG) && (seq->ber_class == BER_CLASS_CON)) {
3513             /* Constructed sequence of with a tag */
3514             /* dissect header and len for field */
3515             hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
3516             hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3517             /* Function has IMPLICIT TAG */
3518         }
3519 
3520         next_tvb = ber_tvb_new_subset_length(tvb, hoffset, eoffset-hoffset);
3521 
3522         imp_tag = FALSE;
3523         if (seq->flags == BER_FLAGS_IMPLTAG)
3524             imp_tag = TRUE;
3525         /* call the dissector for this field */
3526         seq->func(imp_tag, next_tvb, 0, actx, tree, *seq->p_id);
3527         /* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
3528            doesn't match the next item, thus this implicit sequence is over, return the number of bytes
3529            we have eaten to allow the possible upper sequence continue... */
3530         cnt++; /* rubbish*/
3531         offset = eoffset;
3532     }
3533 
3534     /* if we didn't end up at exactly offset, then we ate too many bytes */
3535     if (offset != end_offset) {
3536         tvb_ensure_bytes_exist(tvb, offset-2, 2);
3537         proto_tree_add_expert_format(
3538             tree, actx->pinfo, &ei_ber_error_length, tvb, offset-2, 2,
3539             "BER Error: %s OF contained %d too many bytes",
3540             (type == BER_UNI_TAG_SEQUENCE) ? "SET" : "SEQUENCE",
3541             offset - end_offset);
3542     }
3543 
3544     return end_offset;
3545 }
3546 
3547 int
dissect_ber_constrained_sequence_of(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * parent_tree,tvbuff_t * tvb,int offset,gint32 min_len,gint32 max_len,const ber_sequence_t * seq,gint hf_id,gint ett_id)3548 dissect_ber_constrained_sequence_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
3549     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);
3550 }
3551 
3552 int
dissect_ber_sequence_of(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * parent_tree,tvbuff_t * tvb,int offset,const ber_sequence_t * seq,gint hf_id,gint ett_id)3553 dissect_ber_sequence_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
3554     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);
3555 }
3556 
3557 int
dissect_ber_constrained_set_of(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * parent_tree,tvbuff_t * tvb,int offset,gint32 min_len,gint32 max_len,const ber_sequence_t * seq,gint hf_id,gint ett_id)3558 dissect_ber_constrained_set_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
3559     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);
3560 }
3561 
3562 int
dissect_ber_set_of(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * parent_tree,tvbuff_t * tvb,int offset,const ber_sequence_t * seq,gint hf_id,gint ett_id)3563 dissect_ber_set_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
3564     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);
3565 }
3566 
3567 int
dissect_ber_GeneralizedTime(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id)3568 dissect_ber_GeneralizedTime(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
3569 {
3570     char          str[35];
3571     int           tmp_int;
3572     const guint8 *tmpstr;
3573     char         *strptr;
3574     char          first_delim[2];
3575     int           first_digits;
3576     char          second_delim[2];
3577     int           second_digits;
3578     int           ret;
3579     gint8         ber_class;
3580     gboolean      pc;
3581     gint32        tag;
3582     int           identifier_offset;
3583     int           identifier_len;
3584     guint32       len;
3585     int           len_offset;
3586     int           len_len;
3587     int           end_offset;
3588     int           hoffset;
3589     proto_item   *cause;
3590 
3591     if (!implicit_tag) {
3592         hoffset = offset;
3593         identifier_offset = offset;
3594         offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
3595         identifier_len = offset - identifier_offset;
3596         len_offset = offset;
3597         offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
3598         len_len = offset - len_offset;
3599         end_offset = offset+len;
3600 
3601         /* sanity check. we only handle universal/generalized time */
3602         if ( (ber_class != BER_CLASS_UNI) || (tag != BER_UNI_TAG_GeneralizedTime)) {
3603             tvb_ensure_bytes_exist(tvb, hoffset, 2);
3604             cause = proto_tree_add_expert_format(
3605                 tree, actx->pinfo, &ei_ber_expected_generalized_time,
3606                 tvb, identifier_offset, identifier_len,
3607                 "BER Error: GeneralizedTime expected but class:%s(%d) %s tag:%d was unexpected",
3608                 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3609                 ber_class,
3610                 tfs_get_string(pc, &tfs_constructed_primitive),
3611                 tag);
3612             if (decode_unexpected) {
3613                 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3614                 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3615             }
3616             return end_offset;
3617         }
3618     } else {
3619         len = tvb_reported_length_remaining(tvb, offset);
3620         len_offset = 0;
3621         len_len = 0;
3622         end_offset = offset+len;
3623     }
3624 
3625     if ((len < 14) || (len > 23)) {
3626         cause = proto_tree_add_expert_format(
3627             tree, actx->pinfo, &ei_ber_error_length,
3628             tvb, len_offset, len_len,
3629             "BER Error: GeneralizedTime invalid length: %u",
3630             len);
3631         if (decode_unexpected) {
3632             proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3633             dissect_unknown_ber(actx->pinfo, tvb, offset, unknown_tree);
3634         }
3635         return end_offset;
3636     }
3637 
3638     tmpstr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_ASCII);
3639     strptr = str;
3640     /* those fields are allways present */
3641     strptr += g_snprintf(str, 20, "%.4s-%.2s-%.2s %.2s:%.2s:%.2s",
3642                          tmpstr, tmpstr+4, tmpstr+6, tmpstr+8,
3643                          tmpstr+10, tmpstr+12);
3644 
3645     first_delim[0]  = 0;
3646     second_delim[0] = 0;
3647     ret = sscanf(tmpstr, "%14d%1[.,+-Z]%4d%1[+-Z]%4d", &tmp_int, first_delim, &first_digits, second_delim, &second_digits);
3648     /* tmp_int does not contain valid value because of overflow but we use it just for format checking */
3649     if (ret < 1) {
3650         /* Nothing matched */
3651         goto invalid;
3652     }
3653 
3654     if (ret >= 2) {
3655         /*
3656          * We saw the date+time and the first delimiter.
3657          *
3658          * Either:
3659          *
3660          *    it's '.' or ',', in which case we have a fraction of a
3661          *    minute or hour;
3662          *
3663          *    it's '+' or '-', in which case we have an offset from UTC;
3664          *
3665          *    it's 'Z', in which case the time is UTC.
3666          */
3667         switch (first_delim[0]) {
3668         case '.':
3669         case ',':
3670             /*
3671              * Fraction of a minute or an hour.
3672              */
3673             if (ret == 2 || first_digits < 0 || first_digits > 999) {
3674                 /*
3675                  * We saw the decimal sign, but didn't see the fraction
3676                  * or
3677                  * we got a number outside the valid range.
3678                  */
3679                 goto invalid;
3680             }
3681             strptr += g_snprintf(strptr, 5, "%c%.3d", first_delim[0], first_digits);
3682             if (ret >= 4) {
3683                 /*
3684                  * We saw the fraction and the second delimiter.
3685                  *
3686                  * Either:
3687                  *
3688                  *    it's '+' or '-', in which case we have an offset
3689                  *    from UTC;
3690                  *
3691                  *    it's 'Z', in which case the time is UTC.
3692                  */
3693                 switch (second_delim[0]) {
3694                 case '+':
3695                 case '-':
3696                     if (ret == 4) {
3697                         /*
3698                          * We saw the + or -, but didn't see the offset
3699                          * from UTC.
3700                          */
3701                         goto invalid;
3702                     }
3703                     g_snprintf(strptr, 12, " (UTC%c%.4d)", second_delim[0], second_digits);
3704                     break;
3705                 case 'Z':
3706                     g_snprintf(strptr, 7, " (UTC)");
3707                     break;
3708                 default:
3709                     /* handle the malformed field */
3710                     break;
3711                 }
3712             }
3713             break;
3714         case '+':
3715         case '-':
3716             /*
3717              * Offset from UTC.
3718              */
3719             if (ret == 2) {
3720                 /*
3721                  * We saw the + or -1, but didn't see the offset.
3722                  */
3723                 goto invalid;
3724             }
3725             g_snprintf(strptr, 12, " (UTC%c%.4d)", first_delim[0], first_digits);
3726             break;
3727         case 'Z':
3728             g_snprintf(strptr, 7, " (UTC)");
3729             break;
3730         default:
3731             /* handle the malformed field */
3732             break;
3733         }
3734     }
3735 
3736     if (hf_id >= 0) {
3737         proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
3738     }
3739 
3740     offset+=len;
3741     return offset;
3742 
3743 invalid:
3744     cause = proto_tree_add_expert_format(
3745         tree, actx->pinfo, &ei_ber_invalid_format_generalized_time,
3746         tvb, offset, len,
3747         "BER Error: GeneralizedTime invalid format: %s",
3748         tmpstr);
3749     if (decode_unexpected) {
3750         proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3751         dissect_unknown_ber(actx->pinfo, tvb, offset, unknown_tree);
3752     }
3753     return end_offset;
3754 }
3755 
3756 /* datestrptr: if not NULL return datetime string instead of adding to tree or NULL when packet is malformed
3757  * tvblen: if not NULL return consumed packet bytes
3758  */
3759 int
dissect_ber_UTCTime(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * tree,tvbuff_t * tvb,int offset,gint hf_id,char ** datestrptr,guint32 * tvblen)3760 dissect_ber_UTCTime(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char **datestrptr, guint32 *tvblen)
3761 {
3762     char         *outstr, *outstrptr;
3763     const guint8 *instr;
3764     gint8         ber_class;
3765     gboolean      pc;
3766     gint32        tag;
3767     int           identifier_offset;
3768     int           identifier_len;
3769     guint32       len, i, n;
3770     int           hoffset;
3771     proto_item   *cause;
3772     proto_tree   *error_tree;
3773     const gchar  *error_str = NULL;
3774 
3775     outstrptr = outstr = (char *)wmem_alloc(wmem_packet_scope(), 29);
3776 
3777     if (datestrptr) *datestrptr = NULL; /* mark invalid */
3778     if (tvblen) *tvblen = 0;
3779 
3780     if (!implicit_tag) {
3781         hoffset = offset;
3782         identifier_offset = offset;
3783         offset  = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
3784         identifier_len = offset - identifier_offset;
3785         offset  = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
3786 
3787         /* sanity check: we only handle UTCTime */
3788         if ( (ber_class != BER_CLASS_UNI) || (tag != BER_UNI_TAG_UTCTime) ) {
3789             tvb_ensure_bytes_exist(tvb, hoffset, 2);
3790             cause = proto_tree_add_expert_format(
3791                 tree, actx->pinfo, &ei_ber_expected_utc_time,
3792                 tvb, identifier_offset, identifier_len,
3793                 "BER Error: UTCTime expected but class:%s(%d) %s tag:%d was unexpected",
3794                 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3795                 ber_class,
3796                 tfs_get_string(pc, &tfs_constructed_primitive),
3797                 tag);
3798             if (decode_unexpected) {
3799                 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3800                 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3801             }
3802             return offset+len;
3803         }
3804     } else {
3805         len = tvb_reported_length_remaining(tvb, offset);
3806     }
3807 
3808     if ((len < 10) || (len > 19)) {
3809         error_str = wmem_strdup_printf(wmem_packet_scope(), "BER Error: UTCTime invalid length: %u", len);
3810         instr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len > 19 ? 19 : len, ENC_ASCII);
3811         goto malformed;
3812     }
3813 
3814     instr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_ASCII);
3815 
3816     /* YYMMDDhhmm */
3817     for (i=0; i<10; i++) {
3818         if ((instr[i] < '0') || (instr[i] > '9')) {
3819             error_str = "BER Error: malformed UTCTime encoding, "
3820                         "first 10 octets have to contain YYMMDDhhmm in digits";
3821             goto malformed;
3822         }
3823     }
3824     g_snprintf(outstrptr, 15, "%.2s-%.2s-%.2s %.2s:%.2s", instr, instr+2, instr+4, instr+6, instr+8);
3825     outstrptr+= 14;
3826 
3827     /* (ss)? */
3828     if (len >= 12) {
3829         if ((instr[i] >= '0') && (instr[i] <= '9')) {
3830             i++;
3831             if ((instr[i] >= '0') && (instr[i] <= '9')) {
3832                 i++;
3833                 g_snprintf(outstrptr, 4, ":%.2s", instr+10);
3834                 outstrptr+=3;
3835             } else {
3836                 error_str = "BER Error: malformed UTCTime encoding, "
3837                         "if 11th octet is a digit for seconds, "
3838                         "the 12th octet has to be a digit, too";
3839                 goto malformed;
3840             }
3841         }
3842     }
3843 
3844     /* Z|([+-]hhmm) */
3845     switch (instr[i]) {
3846     case 'Z':
3847         if (len != (i+1)) {
3848             error_str = "BER Error: malformed UTCTime encoding, "
3849                         "there must be no further octets after \'Z\'";
3850             goto malformed;
3851         }
3852         g_snprintf(outstrptr, 7, " (UTC)");
3853         i++;
3854         break;
3855     case '-':
3856     case '+':
3857         if (len != (i+5)) {
3858             error_str = "BER Error: malformed UTCTime encoding, "
3859                         "4 digits must follow on \'+\' resp. \'-\'";
3860             goto malformed;
3861         }
3862         for (n=i+1; n<i+5; n++) {
3863             if ((instr[n] < '0') || (instr[n] > '9')) {
3864                 error_str = "BER Error: malformed UTCTime encoding, "
3865                             "4 digits must follow on \'+\' resp. \'-\'";
3866                 goto malformed;
3867             }
3868         }
3869         g_snprintf(outstrptr, 12, " (UTC%c%.4s)", instr[i], instr+i+1);
3870         i+=5;
3871         break;
3872     default:
3873         error_str = wmem_strdup_printf(wmem_packet_scope(),
3874                                        "BER Error: malformed UTCTime encoding, "
3875                                        "unexpected character in %dth octet, "
3876                                        "must be \'Z\', \'+\' or \'-\'", i+1);
3877         goto malformed;
3878         break;
3879     }
3880 
3881     if (len != i) {
3882         error_str = wmem_strdup_printf(wmem_packet_scope(),
3883             "BER Error: malformed UTCTime encoding, %d unexpected character%s after %dth octet",
3884             len - i,
3885             (len == (i - 1) ? "s" : ""),
3886             i);
3887         goto malformed;
3888     }
3889 
3890     if (datestrptr) {
3891        *datestrptr = outstr; /* mark as valid */
3892     } else {
3893         if (hf_id >= 0) {
3894             proto_tree_add_string(tree, hf_id, tvb, offset, len, outstr);
3895         }
3896     }
3897     if (tvblen) *tvblen = len;
3898 
3899     return offset+len;
3900 malformed:
3901     if (hf_id >= 0) {
3902         cause = proto_tree_add_string(tree, hf_id, tvb, offset, len, instr);
3903         error_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3904     } else {
3905         error_tree = tree;
3906     }
3907 
3908     proto_tree_add_expert_format(
3909         error_tree, actx->pinfo, &ei_ber_invalid_format_utctime,
3910         tvb, offset, len,
3911         "%s",
3912         error_str);
3913 
3914     if (tvblen) *tvblen = len;
3915 
3916     return offset+len;
3917 }
3918 
3919 /* 8.6 Encoding of a bitstring value */
3920 
3921 int
dissect_ber_constrained_bitstring(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * parent_tree,tvbuff_t * tvb,int offset,gint32 min_len,gint32 max_len,int * const * named_bits,int num_named_bits,gint hf_id,gint ett_id,tvbuff_t ** out_tvb)3922 dissect_ber_constrained_bitstring(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, int * const *named_bits, int num_named_bits, gint hf_id, gint ett_id, tvbuff_t **out_tvb)
3923 {
3924     gint8       ber_class;
3925     gboolean    pc, ind;
3926     gint32      tag;
3927     int         identifier_offset;
3928     int         identifier_len;
3929     gint        len;
3930     guint8      pad = 0;
3931     int         end_offset;
3932     int         hoffset;
3933     proto_item *item = NULL;
3934     proto_item *cause;
3935     proto_tree *tree = NULL;
3936     /*const char *sep;*/
3937     /*const int **nb;*/
3938 
3939     if (!implicit_tag) {
3940         hoffset = offset;
3941         /* read header and len for the octet string */
3942         identifier_offset = offset;
3943         offset = dissect_ber_identifier(actx->pinfo, parent_tree, tvb, offset, &ber_class, &pc, &tag);
3944         identifier_len = offset - identifier_offset;
3945         offset = dissect_ber_length(actx->pinfo, parent_tree, tvb, offset, &len, &ind);
3946         end_offset = offset + len;
3947 
3948         /* sanity check: we only handle Universal BitStrings */
3949 
3950         /* for an IMPLICIT APPLICATION tag asn2wrs seems to call this
3951            function with implicit_tag = FALSE. BER_FLAGS_NOOWNTAG was
3952            set so the APPLICATION tag was still present.
3953            So here we relax it for APPLICATION tags. CONTEXT tags may
3954            still cause a problem. */
3955 
3956         if (ber_class != BER_CLASS_APP) {
3957             if ((ber_class != BER_CLASS_UNI)
3958                 || (tag != BER_UNI_TAG_BITSTRING)) {
3959                 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3960                 cause = proto_tree_add_expert_format(
3961                     parent_tree, actx->pinfo, &ei_ber_expected_bitstring,
3962                     tvb, identifier_offset, identifier_len,
3963                     "BER Error: BitString expected but class:%s(%d) %s tag:%d was unexpected",
3964                     val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3965                     ber_class, tfs_get_string(pc, &tfs_constructed_primitive),
3966                     tag);
3967                 if (decode_unexpected) {
3968                     proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3969                     dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3970                 }
3971                 return end_offset;
3972             }
3973         }
3974     } else {
3975         pc = 0;
3976         len = tvb_reported_length_remaining(tvb, offset);
3977         end_offset = offset + len;
3978     }
3979     if ((int)len <= 0) {
3980         proto_tree_add_expert_format(
3981             parent_tree, actx->pinfo, &ei_ber_constr_bitstr, tvb, offset, len,
3982             "BER Error: dissect_ber_constrained_bitstring(): frame:%u offset:%d Was passed an illegal length of %d",
3983             actx->pinfo->num, offset, len);
3984         return offset;
3985     }
3986     actx->created_item = NULL;
3987 
3988     if (pc) {
3989         /* constructed */
3990         /* TO DO */
3991     } else {
3992         /* primitive */
3993         pad = tvb_get_guint8(tvb, offset);
3994         /* 8.6.2.4 If a bitstring value has no 1 bits, then an encoder (as a sender's option)
3995          * may encode the value with a length of 1 and with an initial octet set to 0
3996          * or may encode it as a bit string with one or more 0 bits following the initial octet.
3997          */
3998         if ((pad == 0) && (len == 1)) {
3999             /* empty */
4000             item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, ENC_BIG_ENDIAN);
4001             actx->created_item = item;
4002             proto_tree_add_item(parent_tree, hf_ber_bitstring_empty, tvb, offset, 1, ENC_BIG_ENDIAN);
4003             if (out_tvb) {
4004                 *out_tvb = ber_tvb_new_subset_length(tvb, offset, len);
4005             }
4006             ber_check_length(8 * len - pad, min_len, max_len, actx, item, TRUE);
4007             return end_offset;
4008         } else {
4009             /* padding */
4010             proto_item *pad_item = proto_tree_add_item(parent_tree, hf_ber_bitstring_padding, tvb, offset, 1, ENC_BIG_ENDIAN);
4011             if (pad > 7) {
4012                 expert_add_info_format(
4013                     actx->pinfo, pad_item, &ei_ber_illegal_padding,
4014                     "Illegal padding (0 .. 7): %d", pad);
4015             }
4016         }
4017         offset++;
4018         len--;
4019         if (hf_id >= 0) {
4020             item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, ENC_NA);
4021             actx->created_item = item;
4022             if (named_bits) {
4023                 guint8 *bitstring = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset, len);
4024                 const int named_bits_bytelen = (num_named_bits + 7) / 8;
4025                 if (show_internal_ber_fields) {
4026                     if (len < named_bits_bytelen) {
4027                         guint zero_bits_omitted = num_named_bits - ((len * 8) - pad);
4028                         proto_item_append_text(item, " [%u zero bits not encoded, but displayed]", zero_bits_omitted);
4029                     }
4030                 }
4031                 if (ett_id != -1) {
4032                     tree = proto_item_add_subtree(item, ett_id);
4033                 }
4034                 for (int i = 0; i < named_bits_bytelen; i++) {
4035                     // Process 8 bits at a time instead of 64, each field masks a
4036                     // single byte.
4037                     const int bit_offset = 8 * i;
4038                     int* const* section_named_bits = named_bits + bit_offset;
4039                     int* flags[9];
4040                     if (num_named_bits - bit_offset > 8) {
4041                         memcpy(&flags[0], named_bits + bit_offset, 8 * sizeof(int*));
4042                         flags[8] = NULL;
4043                         section_named_bits = (int* const*)flags;
4044                     }
4045 
4046                     // If less data is available than the number of named bits, then
4047                     // the trailing (right) bits are assumed to be 0.
4048                     guint64 value = 0;
4049                     if (i < len) {
4050                         value = bitstring[i];
4051                         if (num_named_bits - bit_offset > 7) {
4052                             bitstring[i] = 0;
4053                         } else {
4054                             bitstring[i] &= 0xff >> (num_named_bits - bit_offset);
4055                         }
4056                     }
4057 
4058                     // TODO should non-zero pad bits be masked from the value?
4059                     // When trailing zeroes are not present in the data, mark the
4060                     // last byte for the lack of a better alternative.
4061                     proto_tree_add_bitmask_list_value(tree, tvb, offset + MIN(i, len - 1), 1, section_named_bits, value);
4062                 }
4063                 // If more data is available than the number of named bits, then
4064                 // either the spec was updated or the packet is malformed.
4065                 for (int i = 0; i < len; i++) {
4066                     if (bitstring[i]) {
4067                         expert_add_info_format(actx->pinfo, item, &ei_ber_bits_unknown, "Unknown bit(s): 0x%s",
4068                              bytes_to_str(wmem_packet_scope(), bitstring, len));
4069                         break;
4070                     }
4071                 }
4072             }
4073         }
4074         if (out_tvb) {
4075             *out_tvb = ber_tvb_new_subset_length(tvb, offset, len);
4076         }
4077     }
4078 
4079 
4080     if ((pad > 0) && (pad < 8) && (len > 0)) {
4081         guint8 bits_in_pad = tvb_get_guint8(tvb, offset + len - 1) & (0xFF >> (8 - pad));
4082         if (bits_in_pad) {
4083             expert_add_info_format(
4084                 actx->pinfo, item, &ei_ber_bits_set_padded,
4085                 "Bits set in padded area: 0x%02x", bits_in_pad);
4086         }
4087     }
4088 
4089     ber_check_length(8 * len - pad, min_len, max_len, actx, item, TRUE);
4090 
4091     return end_offset;
4092 }
4093 
4094 
4095 int
dissect_ber_bitstring(gboolean implicit_tag,asn1_ctx_t * actx,proto_tree * parent_tree,tvbuff_t * tvb,int offset,int * const * named_bits,gint num_named_bits,gint hf_id,gint ett_id,tvbuff_t ** out_tvb)4096 dissect_ber_bitstring(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, int * const *named_bits, gint num_named_bits, gint hf_id, gint ett_id, tvbuff_t **out_tvb)
4097 {
4098     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);
4099 }
4100 
4101 /*
4102  *  8.18    Encoding of a value of the external type
4103  *  8.18.1  The encoding of a value of the external type shall be the BER encoding of the following
4104  *          sequence type, assumed to be defined in an environment of EXPLICIT TAGS,
4105  *          with a value as specified in the subclauses below:
4106  *
4107  *  [UNIVERSAL 8] IMPLICIT SEQUENCE {
4108  *      direct-reference            OBJECT IDENTIFIER OPTIONAL,
4109  *      indirect-reference      INTEGER OPTIONAL,
4110  *      data-value-descriptor       ObjectDescriptor OPTIONAL,
4111  *      encoding                CHOICE {
4112  *      single-ASN1-type                [0] ABSTRACT-SYNTAX.&Type,
4113  *      octet-aligned                   [1] IMPLICIT OCTET STRING,
4114  *      arbitrary                       [2] IMPLICIT BIT STRING } }
4115  *
4116  */
4117 
4118 static int
dissect_ber_INTEGER(gboolean implicit_tag,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,proto_tree * tree,int hf_index)4119 dissect_ber_INTEGER(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index) {
4120   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
4121                                   &actx->external.indirect_reference);
4122   actx->external.indirect_ref_present = TRUE;
4123 
4124   return offset;
4125 }
4126 
4127 static int
dissect_ber_T_octet_aligned(gboolean implicit_tag,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,proto_tree * tree,int hf_index)4128 dissect_ber_T_octet_aligned(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index)
4129 {
4130     if (actx->external.u.ber.ber_callback) {
4131         offset = actx->external.u.ber.ber_callback(FALSE, tvb, offset, actx, tree, hf_index);
4132     } else if (actx->external.direct_ref_present &&
4133                dissector_get_string_handle(ber_oid_dissector_table, actx->external.direct_reference)) {
4134         offset = call_ber_oid_callback(actx->external.direct_reference, tvb, offset, actx->pinfo, tree, NULL);
4135     } else {
4136         offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index, &actx->external.octet_aligned);
4137     }
4138 
4139     return offset;
4140 }
4141 static int
dissect_ber_OBJECT_IDENTIFIER(gboolean implicit_tag,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,proto_tree * tree,int hf_index)4142 dissect_ber_OBJECT_IDENTIFIER(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index)
4143 {
4144     DISSECTOR_ASSERT(actx);
4145     offset = dissect_ber_object_identifier_str(implicit_tag, actx, tree, tvb, offset, hf_index, &actx->external.direct_reference);
4146     actx->external.direct_ref_present = TRUE;
4147 
4148     return offset;
4149 }
4150 
4151 static int
dissect_ber_ObjectDescriptor(gboolean implicit_tag,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,proto_tree * tree,int hf_index)4152 dissect_ber_ObjectDescriptor(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index)
4153 {
4154     DISSECTOR_ASSERT(actx);
4155     offset = dissect_ber_restricted_string(implicit_tag, BER_UNI_TAG_ObjectDescriptor,
4156                                            actx, tree, tvb, offset, hf_index,
4157                                            &actx->external.data_value_descriptor);
4158 
4159     return offset;
4160 }
4161 
4162 static int
dissect_ber_T_single_ASN1_type(gboolean implicit_tag _U_,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,proto_tree * tree,int hf_index)4163 dissect_ber_T_single_ASN1_type(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index)
4164 {
4165     if (actx->external.u.ber.ber_callback) {
4166         offset = actx->external.u.ber.ber_callback(FALSE, tvb, offset, actx, tree, hf_index);
4167     } else {
4168         offset = call_ber_oid_callback(actx->external.direct_reference, tvb, offset, actx->pinfo, tree, NULL);
4169     }
4170 
4171     return offset;
4172 }
4173 
4174 static int
dissect_ber_T_arbitrary(gboolean implicit_tag,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,proto_tree * tree,int hf_index)4175 dissect_ber_T_arbitrary(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index)
4176 {
4177     if (actx->external.u.ber.ber_callback) {
4178         offset = actx->external.u.ber.ber_callback(FALSE, tvb, offset, actx, tree, hf_index);
4179     } else {
4180         offset = dissect_ber_bitstring(implicit_tag, actx, tree, tvb, offset,
4181                                        NULL, 0, hf_index, -1, &actx->external.arbitrary);
4182     }
4183 
4184     return offset;
4185 }
4186 
4187 static const value_string ber_T_encoding_vals[] = {
4188     {   0, "single-ASN1-type" },
4189     {   1, "octet-aligned" },
4190     {   2, "arbitrary" },
4191     { 0, NULL }
4192 };
4193 
4194 static const ber_choice_t T_encoding_choice[] = {
4195     {   0, &hf_ber_single_ASN1_type, BER_CLASS_CON, 0, 0, dissect_ber_T_single_ASN1_type },
4196     {   1, &hf_ber_octet_aligned  ,  BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_ber_T_octet_aligned },
4197     {   2, &hf_ber_arbitrary      ,  BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_ber_T_arbitrary },
4198     { 0, NULL, 0, 0, 0, NULL }
4199 };
4200 
4201 
4202 static int
dissect_ber_T_encoding(gboolean implicit_tag _U_,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,proto_tree * tree,int hf_index)4203 dissect_ber_T_encoding(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index) {
4204     // This assertion is used to remove clang's warning.
4205     DISSECTOR_ASSERT(actx);
4206     offset = dissect_ber_choice(actx, tree, tvb, offset,
4207                                 T_encoding_choice, hf_index, ett_ber_T_encoding,
4208                                 &actx->external.encoding);
4209 
4210     return offset;
4211 }
4212 
4213 
4214 static const ber_sequence_t external_U_sequence[] = {
4215     { &hf_ber_direct_reference,      BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ber_OBJECT_IDENTIFIER },
4216     { &hf_ber_indirect_reference,    BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ber_INTEGER },
4217     { &hf_ber_data_value_descriptor, BER_CLASS_UNI, BER_UNI_TAG_ObjectDescriptor, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ber_ObjectDescriptor },
4218     { &hf_ber_encoding,              BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_ber_T_encoding },
4219     { NULL, 0, 0, 0, NULL }
4220 };
4221 static int
dissect_ber_external_U(gboolean implicit_tag,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,proto_tree * tree,int hf_index)4222 dissect_ber_external_U(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx , proto_tree *tree, int hf_index)
4223 {
4224     offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
4225                                   external_U_sequence, hf_index, ett_ber_EXTERNAL);
4226 
4227     return offset;
4228 }
4229 
4230 int
dissect_ber_external_type(gboolean implicit_tag,proto_tree * tree,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,gint hf_id,ber_callback func)4231 dissect_ber_external_type(gboolean implicit_tag, proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, gint hf_id, ber_callback func) {
4232 
4233     actx->external.u.ber.ber_callback =  func;
4234 
4235     offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
4236                      hf_id, BER_CLASS_UNI, BER_UNI_TAG_EXTERNAL, TRUE, dissect_ber_external_U);
4237 
4238     asn1_ctx_clean_external(actx);
4239 
4240     return offset;
4241 }
4242 /* Experimental */
4243 int
dissect_ber_EmbeddedPDV_Type(gboolean implicit_tag,proto_tree * tree,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,gint hf_id,ber_callback func _U_)4244 dissect_ber_EmbeddedPDV_Type(gboolean implicit_tag, proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, gint hf_id, ber_callback func _U_) {
4245 
4246 
4247     offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
4248                                      hf_id, BER_CLASS_UNI, BER_UNI_TAG_EMBEDDED_PDV, TRUE, dissect_ber_external_U);
4249 
4250     return offset;
4251 }
4252 
4253 static int
dissect_ber_syntax(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4254 dissect_ber_syntax(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4255 {
4256     return dissect_unknown_ber(pinfo, tvb, 0, tree);
4257 }
4258 
4259 static int
dissect_ber_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,const char * syntax)4260 dissect_ber_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const char *syntax)
4261 {
4262     const char *name;
4263     int offset;
4264 
4265     col_set_str(pinfo->cinfo, COL_PROTOCOL, "BER");
4266 
4267     col_set_str(pinfo->cinfo, COL_DEF_SRC, "BER encoded value");
4268 
4269     if (!syntax) {
4270 
4271         /* if we got here we couldn't find anything better */
4272         col_set_str(pinfo->cinfo, COL_INFO, "Unknown BER");
4273 
4274         offset = dissect_unknown_ber(pinfo, tvb, 0, tree);
4275 
4276     } else {
4277 
4278         offset = call_ber_syntax_callback(syntax, tvb, 0, pinfo, tree);
4279 
4280         /* see if we have a better name */
4281         name = get_ber_oid_syntax(syntax);
4282         col_add_fstr(pinfo->cinfo, COL_INFO, "Decoded as %s", name ? name : syntax);
4283     }
4284 
4285     return offset;
4286 }
4287 
4288 static int
dissect_ber(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4289 dissect_ber(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
4290 {
4291     return dissect_ber_common(tvb, pinfo, tree, decode_as_syntax);
4292 }
4293 
4294 static int
dissect_ber_file(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4295 dissect_ber_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
4296 {
4297     struct ber_phdr *ber = (struct ber_phdr *)data;
4298     const char *ptr;
4299     const char *file_syntax = NULL;
4300 
4301     if ((ptr = strrchr(ber->pathname, '.')) != NULL)
4302         file_syntax = get_ber_oid_syntax(ptr);
4303     return dissect_ber_common(tvb, pinfo, tree, file_syntax);
4304 }
4305 
4306 gboolean
oid_has_dissector(const char * oid)4307 oid_has_dissector(const char *oid) {
4308     return(dissector_get_string_handle(ber_oid_dissector_table, oid) != NULL);
4309 }
4310 
4311 static void
ber_shutdown(void)4312 ber_shutdown(void)
4313 {
4314     g_hash_table_destroy(syntax_table);
4315 }
4316 
4317 void
proto_register_ber(void)4318 proto_register_ber(void)
4319 {
4320     static hf_register_info hf[] = {
4321         { &hf_ber_id_class, {
4322                 "Class", "ber.id.class", FT_UINT8, BASE_DEC,
4323                 VALS(ber_class_codes), 0xc0, "Class of BER TLV Identifier", HFILL }},
4324         { &hf_ber_bitstring_padding, {
4325                 "Padding", "ber.bitstring.padding", FT_UINT8, BASE_DEC,
4326                 NULL, 0x0, "Number of unused bits in the last octet of the bitstring", HFILL }},
4327         { &hf_ber_bitstring_empty, {
4328                 "Empty", "ber.bitstring.empty", FT_UINT8, BASE_DEC,
4329                 NULL, 0x0, "This is an empty bitstring", HFILL }},
4330         { &hf_ber_id_pc, {
4331                 "P/C", "ber.id.pc", FT_BOOLEAN, 8,
4332                 TFS(&ber_pc_codes), 0x20, "Primitive or Constructed BER encoding", HFILL }},
4333         { &hf_ber_id_uni_tag, {
4334                 "Tag", "ber.id.uni_tag", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
4335                 &ber_uni_tag_codes_ext, 0x1f, "Universal tag type", HFILL }},
4336         { &hf_ber_id_uni_tag_ext, {
4337                 "Tag", "ber.id.uni_tag", FT_UINT32, BASE_DEC,
4338                 NULL, 0, "Universal tag type", HFILL }},
4339         { &hf_ber_id_tag, {
4340                 "Tag", "ber.id.tag", FT_UINT8, BASE_DEC,
4341                 NULL, 0x1f, "Tag value for non-Universal classes", HFILL }},
4342         { &hf_ber_id_tag_ext, {
4343                 "Tag", "ber.id.tag", FT_UINT32, BASE_DEC,
4344                 NULL, 0, "Tag value for non-Universal classes", HFILL }},
4345         { &hf_ber_length, {
4346                 "Length", "ber.length", FT_UINT32, BASE_DEC,
4347                 NULL, 0, "Length of contents", HFILL }},
4348         { &hf_ber_unknown_OCTETSTRING, {
4349                 "OCTETSTRING", "ber.unknown.OCTETSTRING", FT_BYTES, BASE_NONE,
4350                 NULL, 0, "This is an unknown OCTETSTRING", HFILL }},
4351         { &hf_ber_unknown_BER_OCTETSTRING, {
4352                 "OCTETSTRING [BER encoded]", "ber.unknown.OCTETSTRING", FT_NONE, BASE_NONE,
4353                 NULL, 0, "This is an BER encoded OCTETSTRING", HFILL }},
4354         { &hf_ber_unknown_BER_primitive, {
4355                 "Primitive [BER encoded]", "ber.unknown.primitive", FT_NONE, BASE_NONE,
4356                 NULL, 0, "This is a BER encoded Primitive", HFILL }},
4357         { &hf_ber_unknown_OID, {
4358                 "OID", "ber.unknown.OID", FT_OID, BASE_NONE,
4359                 NULL, 0, "This is an unknown Object Identifier", HFILL }},
4360         { &hf_ber_unknown_relative_OID, {
4361                 "OID", "ber.unknown.relative_OID", FT_REL_OID, BASE_NONE,
4362                 NULL, 0, "This is an unknown relative Object Identifier", HFILL }},
4363         { &hf_ber_unknown_GraphicString, {
4364                 "GRAPHICSTRING", "ber.unknown.GRAPHICSTRING", FT_STRING, BASE_NONE,
4365                 NULL, 0, "This is an unknown GRAPHICSTRING", HFILL }},
4366         { &hf_ber_unknown_NumericString, {
4367                 "NumericString", "ber.unknown.NumericString", FT_STRING, BASE_NONE,
4368                 NULL, 0, "This is an unknown NumericString", HFILL }},
4369         { &hf_ber_unknown_PrintableString, {
4370                 "PrintableString", "ber.unknown.PrintableString", FT_STRING, BASE_NONE,
4371                 NULL, 0, "This is an unknown PrintableString", HFILL }},
4372         { &hf_ber_unknown_TeletexString, {
4373                 "TeletexString", "ber.unknown.TeletexString", FT_STRING, BASE_NONE,
4374                 NULL, 0, "This is an unknown TeletexString", HFILL }},
4375         { &hf_ber_unknown_VisibleString, {
4376                 "VisibleString", "ber.unknown.VisibleString", FT_STRING, BASE_NONE,
4377                 NULL, 0, "This is an unknown VisibleString", HFILL }},
4378         { &hf_ber_unknown_GeneralString, {
4379                 "GeneralString", "ber.unknown.GeneralString", FT_STRING, BASE_NONE,
4380                 NULL, 0, "This is an unknown GeneralString", HFILL }},
4381         { &hf_ber_unknown_UniversalString, {
4382                 "UniversalString", "ber.unknown.UniversalString", FT_STRING, BASE_NONE,
4383                 NULL, 0, "This is an unknown UniversalString", HFILL }},
4384         { &hf_ber_unknown_BMPString, {
4385                 "BMPString", "ber.unknown.BMPString", FT_STRING, BASE_NONE,
4386                 NULL, 0, "This is an unknown BMPString", HFILL }},
4387         { &hf_ber_unknown_IA5String, {
4388                 "IA5String", "ber.unknown.IA5String", FT_STRING, BASE_NONE,
4389                 NULL, 0, "This is an unknown IA5String", HFILL }},
4390         { &hf_ber_unknown_UTCTime, {
4391                 "UTCTime", "ber.unknown.UTCTime", FT_STRING, BASE_NONE,
4392                 NULL, 0, "This is an unknown UTCTime", HFILL }},
4393         { &hf_ber_unknown_UTF8String, {
4394                 "UTF8String", "ber.unknown.UTF8String", FT_STRING, BASE_NONE,
4395                 NULL, 0, "This is an unknown UTF8String", HFILL }},
4396         { &hf_ber_unknown_GeneralizedTime, {
4397                 "GeneralizedTime", "ber.unknown.GeneralizedTime", FT_STRING, BASE_NONE,
4398                 NULL, 0, "This is an unknown GeneralizedTime", HFILL }},
4399         { &hf_ber_unknown_INTEGER, {
4400                 "INTEGER", "ber.unknown.INTEGER", FT_INT64, BASE_DEC,
4401                 NULL, 0, "This is an unknown INTEGER", HFILL }},
4402         { &hf_ber_unknown_REAL, {
4403                 "REAL", "ber.unknown.REAL", FT_DOUBLE, BASE_NONE,
4404                 NULL, 0, "This is an unknown REAL", HFILL }},
4405         { &hf_ber_unknown_BITSTRING, {
4406                 "BITSTRING", "ber.unknown.BITSTRING", FT_BYTES, BASE_NONE,
4407                 NULL, 0, "This is an unknown BITSTRING", HFILL }},
4408         { &hf_ber_unknown_BOOLEAN, {
4409                 "BOOLEAN", "ber.unknown.BOOLEAN", FT_UINT8, BASE_HEX,
4410                 NULL, 0, "This is an unknown BOOLEAN", HFILL }},
4411         { &hf_ber_unknown_ENUMERATED, {
4412                 "ENUMERATED", "ber.unknown.ENUMERATED", FT_UINT32, BASE_DEC,
4413                 NULL, 0, "This is an unknown ENUMERATED", HFILL }},
4414         { &hf_ber_direct_reference,
4415           { "direct-reference", "ber.direct_reference",
4416             FT_OID, BASE_NONE, NULL, 0,
4417             "ber.OBJECT_IDENTIFIER", HFILL }},
4418         { &hf_ber_indirect_reference,
4419           { "indirect-reference", "ber.indirect_reference",
4420             FT_INT32, BASE_DEC, NULL, 0,
4421             "ber.INTEGER", HFILL }},
4422         { &hf_ber_data_value_descriptor,
4423           { "data-value-descriptor", "ber.data_value_descriptor",
4424             FT_STRING, BASE_NONE, NULL, 0,
4425             "ber.ObjectDescriptor", HFILL }},
4426         { &hf_ber_encoding,
4427           { "encoding", "ber.encoding",
4428             FT_UINT32, BASE_DEC, VALS(ber_T_encoding_vals), 0,
4429             "ber.T_encoding", HFILL }},
4430         { &hf_ber_octet_aligned,
4431           { "octet-aligned", "ber.octet_aligned",
4432             FT_BYTES, BASE_NONE, NULL, 0,
4433             "ber.T_octet_aligned", HFILL }},
4434         { &hf_ber_arbitrary,
4435           { "arbitrary", "ber.arbitrary",
4436             FT_BYTES, BASE_NONE, NULL, 0,
4437             "ber.T_arbitrary", HFILL }},
4438         { &hf_ber_single_ASN1_type,
4439           { "single-ASN1-type", "ber.single_ASN1_type",
4440             FT_NONE, BASE_NONE, NULL, 0,
4441             "ber.T_single_ASN1_type", HFILL }},
4442         { &hf_ber_extra_data,
4443           { "Extra data", "ber.extra_data",
4444             FT_BYTES, BASE_NONE, NULL, 0,
4445             NULL, HFILL }},
4446 
4447         /* Fragment entries */
4448         { &hf_ber_fragments,
4449           { "OCTET STRING fragments", "ber.octet_string.fragments", FT_NONE, BASE_NONE,
4450             NULL, 0x00, NULL, HFILL } },
4451         { &hf_ber_fragment,
4452           { "OCTET STRING fragment", "ber.octet_string.fragment", FT_FRAMENUM, BASE_NONE,
4453             NULL, 0x00, NULL, HFILL } },
4454         { &hf_ber_fragment_overlap,
4455           { "OCTET STRING fragment overlap", "ber.octet_string.fragment.overlap", FT_BOOLEAN,
4456             BASE_NONE, NULL, 0x0, NULL, HFILL } },
4457         { &hf_ber_fragment_overlap_conflicts,
4458           { "OCTET STRING fragment overlapping with conflicting data",
4459             "ber.octet_string.fragment.overlap.conflicts", FT_BOOLEAN, BASE_NONE, NULL,
4460             0x0, NULL, HFILL } },
4461         { &hf_ber_fragment_multiple_tails,
4462           { "OCTET STRING has multiple tail fragments",
4463             "ber.octet_string.fragment.multiple_tails", FT_BOOLEAN, BASE_NONE,
4464             NULL, 0x0, NULL, HFILL } },
4465         { &hf_ber_fragment_too_long_fragment,
4466           { "OCTET STRING fragment too long", "ber.octet_string.fragment.too_long_fragment",
4467             FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL,
4468             HFILL } },
4469         { &hf_ber_fragment_error,
4470           { "OCTET STRING defragmentation error", "ber.octet_string.fragment.error", FT_FRAMENUM,
4471             BASE_NONE, NULL, 0x00, NULL, HFILL } },
4472         { &hf_ber_fragment_count,
4473           { "OCTET STRING fragment count", "ber.octet_string.fragment.count", FT_UINT32, BASE_DEC,
4474             NULL, 0x00, NULL, HFILL } },
4475         { &hf_ber_reassembled_in,
4476           { "Reassembled in", "ber.octet_string.reassembled.in", FT_FRAMENUM, BASE_NONE,
4477             NULL, 0x00, NULL, HFILL } },
4478         { &hf_ber_reassembled_length,
4479           { "Reassembled OCTET STRING length", "ber.octet_string.reassembled.length", FT_UINT32, BASE_DEC,
4480             NULL, 0x00, NULL, HFILL } },
4481 
4482       /* Generated from convert_proto_tree_add_text.pl */
4483       { &hf_ber_null_tag, { "NULL tag", "ber.null_tag", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4484       { &hf_ber_unknown_data, { "Unknown Data", "ber.unknown_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4485       { &hf_ber_unknown_octetstring, { "Unknown OctetString", "ber.unknown_octetstring", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4486       { &hf_ber_seq_field_eoc, { "SEQ FIELD EOC", "ber.seq_field_eoc", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4487       { &hf_ber_seq_eoc, { "SEQ EOC", "ber.seq_eoc", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4488       { &hf_ber_set_field_eoc, { "SET FIELD EOC", "ber.set_field_eoc", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4489       { &hf_ber_set_eoc, { "SET EOC", "ber.set_eoc", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4490       { &hf_ber_choice_eoc, { "CHOICE EOC", "ber.choice_eoc", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4491       { &hf_ber_seq_of_eoc, { "SEQ OF EOC", "ber.seq_of_eoc", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4492       { &hf_ber_64bit_uint_as_bytes, { "64bits unsigned integer", "ber.64bit_uint_as_bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4493     };
4494 
4495 
4496     static gint *ett[] = {
4497         &ett_ber_octet_string,
4498         &ett_ber_reassembled_octet_string,
4499         &ett_ber_primitive,
4500         &ett_ber_unknown,
4501         &ett_ber_SEQUENCE,
4502         &ett_ber_EXTERNAL,
4503         &ett_ber_T_encoding,
4504         &ett_ber_fragment,
4505         &ett_ber_fragments
4506     };
4507     static ei_register_info ei[] = {
4508         { &ei_ber_size_constraint_string, { "ber.size_constraint.string", PI_PROTOCOL, PI_WARN, "Size constraint: string", EXPFILL }},
4509         { &ei_ber_size_constraint_value, { "ber.size_constraint.value", PI_PROTOCOL, PI_WARN, "Size constraint: values", EXPFILL }},
4510         { &ei_ber_size_constraint_items, { "ber.size_constraint.items", PI_PROTOCOL, PI_WARN, "Size constraint: items", EXPFILL }},
4511         { &ei_ber_sequence_field_wrong, { "ber.error.sequence.field_wrong", PI_MALFORMED, PI_WARN, "BER Error: Wrong field in SEQUENCE", EXPFILL }},
4512         { &ei_ber_expected_octet_string, { "ber.error.expected.octet_string", PI_MALFORMED, PI_WARN, "BER Error: OctetString expected", EXPFILL }},
4513         { &ei_ber_expected_null, { "ber.error.expected.null", PI_MALFORMED, PI_WARN, "BER Error: NULL expected", EXPFILL }},
4514         { &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 }},
4515         { &ei_ber_expected_sequence, { "ber.error.expected.sequence", PI_MALFORMED, PI_WARN, "BER Error: Sequence expected", EXPFILL }},
4516         { &ei_ber_expected_set, { "ber.error.expected.set", PI_MALFORMED, PI_WARN, "BER Error: SET expected", EXPFILL }},
4517         { &ei_ber_expected_string, { "ber.error.expected.string", PI_MALFORMED, PI_WARN, "BER Error: String expected", EXPFILL }},
4518         { &ei_ber_expected_object_identifier, { "ber.error.expected.object_identifier", PI_MALFORMED, PI_WARN, "BER Error: Object Identifier expected", EXPFILL }},
4519         { &ei_ber_expected_generalized_time, { "ber.error.expected.generalized_time", PI_MALFORMED, PI_WARN, "BER Error: GeneralizedTime expected", EXPFILL }},
4520         { &ei_ber_expected_utc_time, { "ber.error.expected.utc_time", PI_MALFORMED, PI_WARN, "BER Error: UTCTime expected", EXPFILL }},
4521         { &ei_ber_expected_bitstring, { "ber.error.expected.bitstring", PI_MALFORMED, PI_WARN, "BER Error: BitString expected", EXPFILL }},
4522         { &ei_ber_error_length, { "ber.error.length", PI_MALFORMED, PI_WARN, "BER Error: length is not valid", EXPFILL }},
4523         { &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 }},
4524         { &ei_ber_universal_tag_unknown, { "ber.error.universal_tag_unknown", PI_MALFORMED, PI_WARN, "BER Error: can not handle universal", EXPFILL }},
4525         { &ei_ber_no_oid, { "ber.error.no_oid", PI_MALFORMED, PI_WARN, "BER Error: No OID supplied to call_ber_oid_callback", EXPFILL }},
4526         { &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 }},
4527         { &ei_ber_syntax_not_implemented, { "ber.error.syntax_not_implemented", PI_UNDECODED, PI_WARN, "BER: Dissector for syntax not implemented", EXPFILL }},
4528         { &ei_ber_value_too_many_bytes, { "ber.error.value_too_many_bytes", PI_MALFORMED, PI_WARN, "Value is encoded with too many bytes", EXPFILL }},
4529         { &ei_ber_unknown_field_sequence, { "ber.error.unknown_field.sequence", PI_MALFORMED, PI_WARN, "BER Error: Unknown field in Sequence", EXPFILL }},
4530         { &ei_ber_unknown_field_set, { "ber.error.unknown_field.set", PI_MALFORMED, PI_WARN, "BER Error: Unknown field in SET", EXPFILL }},
4531         { &ei_ber_missing_field_set, { "ber.error.missing_field.set", PI_MALFORMED, PI_WARN, "BER Error: Missing field in SET", EXPFILL }},
4532         { &ei_ber_empty_choice, { "ber.error.empty_choice", PI_MALFORMED, PI_WARN, "BER Error: Empty choice was found", EXPFILL }},
4533         { &ei_ber_choice_not_found, { "ber.error.choice_not_found", PI_MALFORMED, PI_WARN, "BER Error: This choice field was not found", EXPFILL }},
4534         { &ei_ber_bits_unknown, { "ber.error.bits_unknown", PI_UNDECODED, PI_WARN, "BER Error: Bits unknown", EXPFILL }},
4535         { &ei_ber_bits_set_padded, { "ber.error.bits_set_padded", PI_UNDECODED, PI_WARN, "BER Error: Bits set in padded area", EXPFILL }},
4536         { &ei_ber_illegal_padding, { "ber.error.illegal_padding", PI_UNDECODED, PI_WARN, "Illegal padding", EXPFILL }},
4537         { &ei_ber_invalid_format_generalized_time, { "ber.error.invalid_format.generalized_time", PI_MALFORMED, PI_WARN, "BER Error: GeneralizedTime invalid format", EXPFILL }},
4538         { &ei_ber_invalid_format_utctime, { "ber.error.invalid_format.utctime", PI_MALFORMED, PI_WARN, "BER Error: malformed UTCTime encoding", EXPFILL }},
4539         { &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 }},
4540         { &ei_ber_constr_bitstr,{ "ber.error.constr_bitstr.len", PI_MALFORMED, PI_WARN, "BER Error: malformed Bitstring encoding", EXPFILL } },
4541         { &ei_ber_real_not_primitive,{ "ber.error.not_primitive.real", PI_MALFORMED, PI_WARN, "BER Error: REAL class not encoded as primitive", EXPFILL } },
4542     };
4543 
4544     /* Decode As handling */
4545     static build_valid_func ber_da_build_value[1] = {ber_value};
4546     static decode_as_value_t ber_da_values = {ber_prompt, 1, ber_da_build_value};
4547     static decode_as_t ber_da = {"ber", "ber.syntax", 1, 0, &ber_da_values, NULL, NULL,
4548                                 ber_populate_list, ber_decode_as_reset, ber_decode_as_change, NULL};
4549 
4550     module_t *ber_module;
4551     expert_module_t* expert_ber;
4552     uat_t* users_uat = uat_new("OID Tables",
4553                                sizeof(oid_user_t),
4554                                "oid",
4555                                FALSE,
4556                                &oid_users,
4557                                &num_oid_users,
4558                                UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
4559                                "ChObjectIdentifiers",
4560                                oid_copy_cb,
4561                                NULL,
4562                                oid_free_cb,
4563                                ber_update_oids,
4564                                NULL,
4565                                users_flds);
4566 
4567     proto_ber = proto_register_protocol("Basic Encoding Rules (ASN.1 X.690)", "BER", "ber");
4568 
4569     ber_handle = register_dissector("ber", dissect_ber, proto_ber);
4570 
4571     proto_register_field_array(proto_ber, hf, array_length(hf));
4572     proto_register_subtree_array(ett, array_length(ett));
4573     expert_ber = expert_register_protocol(proto_ber);
4574     expert_register_field_array(expert_ber, ei, array_length(ei));
4575 
4576     proto_set_cant_toggle(proto_ber);
4577 
4578     /* Register preferences */
4579     ber_module = prefs_register_protocol(proto_ber, NULL);
4580 
4581     prefs_register_bool_preference(ber_module, "show_internals",
4582                                    "Show internal BER encapsulation tokens",
4583                                    "Whether the dissector should also display internal"
4584                                    " ASN.1 BER details such as Identifier and Length fields", &show_internal_ber_fields);
4585     prefs_register_bool_preference(ber_module, "decode_unexpected",
4586                                    "Decode unexpected tags as BER encoded data",
4587                                    "Whether the dissector should decode unexpected tags as"
4588                                    " ASN.1 BER encoded data", &decode_unexpected);
4589     prefs_register_bool_preference(ber_module, "decode_octetstring",
4590                                    "Decode OCTET STRING as BER encoded data",
4591                                    "Whether the dissector should try decoding OCTET STRINGs as"
4592                                    " constructed ASN.1 BER encoded data", &decode_octetstring_as_ber);
4593 
4594     prefs_register_bool_preference(ber_module, "decode_primitive",
4595                                    "Decode Primitive as BER encoded data",
4596                                    "Whether the dissector should try decoding unknown primitive as"
4597                                    " constructed ASN.1 BER encoded data", &decode_primitive_as_ber);
4598 
4599     prefs_register_bool_preference(ber_module, "warn_too_many_bytes",
4600                                    "Warn if too many leading zero bits in encoded data",
4601                                    "Whether the dissector should warn if excessive leading zero (0) bits",
4602                                    &decode_warning_leading_zero_bits);
4603 
4604     prefs_register_uat_preference(ber_module, "oid_table", "Object Identifiers",
4605                                   "A table that provides names for object identifiers"
4606                                   " and the syntax of any associated values",
4607                                   users_uat);
4608 
4609     ber_oid_dissector_table = register_dissector_table("ber.oid", "BER OID", proto_ber, FT_STRING, BASE_NONE);
4610     ber_syntax_dissector_table = register_dissector_table("ber.syntax", "BER syntax", proto_ber, FT_STRING, BASE_NONE);
4611     syntax_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); /* oid to syntax */
4612 
4613     register_ber_syntax_dissector("ASN.1", proto_ber, dissect_ber_syntax);
4614 
4615     reassembly_table_register(&octet_segment_reassembly_table,
4616                           &addresses_reassembly_table_functions);
4617 
4618     register_shutdown_routine(ber_shutdown);
4619 
4620     register_decode_as(&ber_da);
4621 }
4622 
4623 void
proto_reg_handoff_ber(void)4624 proto_reg_handoff_ber(void)
4625 {
4626     guint i = 1;
4627     dissector_handle_t ber_file_handle;
4628 
4629     oid_add_from_string("asn1", "2.1");
4630     oid_add_from_string("basic-encoding", "2.1.1");
4631 
4632     ber_decode_as_foreach(ber_add_syntax_name, &i);
4633 
4634     if (i > 1)
4635         qsort(&syntax_names[1], i - 1, sizeof(value_string), cmp_value_string);
4636     syntax_names[i].value = 0;
4637     syntax_names[i].strptr = NULL;
4638 
4639     /* allow the dissection of BER/DER carried over a TCP/UDP transport
4640        by using "Decode As..." */
4641     dissector_add_for_decode_as_with_preference("tcp.port", ber_handle);
4642     dissector_add_for_decode_as_with_preference("udp.port", ber_handle);
4643 
4644     ber_update_oids();
4645 
4646     ber_file_handle = create_dissector_handle(dissect_ber_file, proto_ber);
4647     dissector_add_uint("wtap_encap", WTAP_ENCAP_BER, ber_file_handle);
4648 }
4649 
4650 /*
4651  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
4652  *
4653  * Local variables:
4654  * c-basic-offset: 4
4655  * tab-width: 8
4656  * indent-tabs-mode: nil
4657  * End:
4658  *
4659  * vi: set shiftwidth=4 tabstop=8 expandtab:
4660  * :indentSize=4:tabSize=8:noTabs=true:
4661  */
4662