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