MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-ber.c
blob03cd7811dfba8ca8a66802f82c8e25a74d716f89
1 /* packet-ber.c
2 * Helpers for ASN.1/BER dissection
3 * Ronnie Sahlberg (C) 2004
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * ITU-T Recommendation X.690 (07/2002),
28 * Information technology ASN.1 encoding rules:
29 * Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)
32 /* TODO: change #.REGISTER signature to new_dissector_t and
33 * update call_ber_oid_callback() accordingly.
35 * Since we don't pass the TAG/LENGTH from the CHOICE/SEQUENCE/SEQUENCE OF/
36 * SET OF helpers through the callbacks to the next pabket-ber helper
37 * when the tags are IMPLICIT, this causes a problem when we also have
38 * indefinite length at the same time as the tags are implicit.
40 * While the proper fix is to change the signatures for packet-ber.c helpers
41 * as well as the signatures for the callbacks to include the indefinite length
42 * indication that would be a major job.
44 * Originally we used a kludge - we set a global variable in the
45 * CHOICE/SEQUENCE [OF]/SET [OF] helpers to indicate to the next helper
46 * whether the length is indefinite or not.
47 * That had currently only been implemented for {SEQUENCE|SET} [OF] but not
48 * CHOICE.
50 * This version attacks the problem(s) in a different way. If we see
51 * indefinite length the get_ber_length traverses the tags within the
52 * compound value and then we return the true length of the compound value
53 * including the EOC. Thus the tvb length is now always correct even for
54 * indefinite length, then if we get implicit tags they can be handled as
55 * if they were definite length.
58 /*#define DEBUG_BER 1*/
60 #include "config.h"
62 #include <stdio.h>
64 #include <glib.h>
66 #include <epan/packet.h>
67 #include <epan/exceptions.h>
68 #include <epan/strutil.h>
69 #include <epan/to_str.h>
70 #include <epan/prefs.h>
71 #include <epan/reassemble.h>
72 #include <epan/oids.h>
73 #include <epan/expert.h>
74 #include <epan/uat.h>
75 #include <epan/asn1.h>
76 #include <epan/wmem/wmem.h>
78 #include "packet-ber.h"
81 * Set a limit on recursion so we don't blow away the stack. Another approach
82 * would be to remove recursion completely but then we'd exhaust CPU+memory
83 * trying to read a hellabyte of nested indefinite lengths.
85 * XXX - Max nesting in the ASN.1 plugin is 32. Should they match?
87 #define BER_MAX_NESTING 500
89 void proto_register_ber(void);
90 void proto_reg_handoff_ber(void);
92 static gint proto_ber = -1;
93 static gint hf_ber_id_class = -1;
94 static gint hf_ber_id_pc = -1;
95 static gint hf_ber_id_uni_tag = -1;
96 static gint hf_ber_id_uni_tag_ext = -1;
97 static gint hf_ber_id_tag = -1;
98 static gint hf_ber_id_tag_ext = -1;
99 static gint hf_ber_length = -1;
100 static gint hf_ber_bitstring_padding = -1;
101 static gint hf_ber_bitstring_empty = -1;
102 static gint hf_ber_unknown_OID = -1;
103 static gint hf_ber_unknown_BOOLEAN = -1;
104 static gint hf_ber_unknown_OCTETSTRING = -1;
105 static gint hf_ber_unknown_BER_OCTETSTRING = -1;
106 static gint hf_ber_unknown_BER_primitive = -1;
107 static gint hf_ber_unknown_GraphicString = -1;
108 static gint hf_ber_unknown_NumericString = -1;
109 static gint hf_ber_unknown_PrintableString = -1;
110 static gint hf_ber_unknown_TeletexString = -1;
111 static gint hf_ber_unknown_VisibleString = -1;
112 static gint hf_ber_unknown_GeneralString = -1;
113 static gint hf_ber_unknown_UniversalString = -1;
114 static gint hf_ber_unknown_BMPString = -1;
115 static gint hf_ber_unknown_IA5String = -1;
116 static gint hf_ber_unknown_UTCTime = -1;
117 static gint hf_ber_unknown_UTF8String = -1;
118 static gint hf_ber_unknown_GeneralizedTime = -1;
119 static gint hf_ber_unknown_INTEGER = -1;
120 static gint hf_ber_unknown_BITSTRING = -1;
121 static gint hf_ber_unknown_ENUMERATED = -1;
122 static gint hf_ber_error = -1;
123 static gint hf_ber_direct_reference = -1; /* OBJECT_IDENTIFIER */
124 static gint hf_ber_indirect_reference = -1; /* INTEGER */
125 static gint hf_ber_data_value_descriptor = -1; /* ObjectDescriptor */
126 static gint hf_ber_encoding = -1; /* T_encoding */
127 static gint hf_ber_single_ASN1_type = -1; /* T_single_ASN1_type */
128 static gint hf_ber_octet_aligned = -1; /* OCTET_STRING */
129 static gint hf_ber_arbitrary = -1; /* BIT_STRING */
131 static int hf_ber_fragments = -1;
132 static int hf_ber_fragment = -1;
133 static int hf_ber_fragment_overlap = -1;
134 static int hf_ber_fragment_overlap_conflicts = -1;
135 static int hf_ber_fragment_multiple_tails = -1;
136 static int hf_ber_fragment_too_long_fragment = -1;
137 static int hf_ber_fragment_error = -1;
138 static int hf_ber_fragment_count = -1;
139 static int hf_ber_reassembled_in = -1;
140 static int hf_ber_reassembled_length = -1;
142 static gint ett_ber_octet_string = -1;
143 static gint ett_ber_reassembled_octet_string = -1;
144 static gint ett_ber_primitive = -1;
145 static gint ett_ber_unknown = -1;
146 static gint ett_ber_SEQUENCE = -1;
147 static gint ett_ber_EXTERNAL = -1;
148 static gint ett_ber_T_encoding = -1;
149 static gint ett_ber_fragment = -1;
150 static gint ett_ber_fragments = -1;
152 static expert_field ei_ber_size_constraint_string = EI_INIT;
153 static expert_field ei_ber_size_constraint_value = EI_INIT;
154 static expert_field ei_ber_size_constraint_items = EI_INIT;
155 static expert_field ei_ber_sequence_field_wrong = EI_INIT;
156 static expert_field ei_ber_expected_octet_string = EI_INIT;
157 static expert_field ei_ber_expected_null = EI_INIT;
158 static expert_field ei_ber_expected_null_zero_length = EI_INIT;
159 static expert_field ei_ber_expected_sequence = EI_INIT;
160 static expert_field ei_ber_expected_set = EI_INIT;
161 static expert_field ei_ber_expected_string = EI_INIT;
162 static expert_field ei_ber_expected_object_identifier = EI_INIT;
163 static expert_field ei_ber_expected_generalized_time = EI_INIT;
164 static expert_field ei_ber_expected_utc_time = EI_INIT;
165 static expert_field ei_ber_expected_bitstring = EI_INIT;
166 static expert_field ei_ber_error_length = EI_INIT;
167 static expert_field ei_ber_wrong_tag_in_tagged_type = EI_INIT;
168 static expert_field ei_ber_universal_tag_unknown = EI_INIT;
169 static expert_field ei_ber_no_oid = EI_INIT;
170 static expert_field ei_ber_syntax_not_implemented = EI_INIT;
171 static expert_field ei_ber_oid_not_implemented = EI_INIT;
172 static expert_field ei_ber_value_too_many_bytes = EI_INIT;
173 static expert_field ei_ber_unknown_field_sequence = EI_INIT;
174 static expert_field ei_ber_unknown_field_set = EI_INIT;
175 static expert_field ei_ber_missing_field_set = EI_INIT;
176 static expert_field ei_ber_empty_choice = EI_INIT;
177 static expert_field ei_ber_choice_not_found = EI_INIT;
178 static expert_field ei_ber_bits_unknown = EI_INIT;
179 static expert_field ei_ber_bits_set_padded = EI_INIT;
180 static expert_field ei_ber_illegal_padding = EI_INIT;
181 static expert_field ei_ber_invalid_format_generalized_time = EI_INIT;
182 static expert_field ei_ber_invalid_format_utctime = EI_INIT;
184 static dissector_handle_t ber_handle;
186 static gboolean show_internal_ber_fields = FALSE;
187 static gboolean decode_octetstring_as_ber = FALSE;
188 static gboolean decode_primitive_as_ber = FALSE;
189 static gboolean decode_unexpected = FALSE;
190 static gboolean decode_warning_leading_zero_bits = FALSE;
192 static gchar *decode_as_syntax = NULL;
193 static gchar *ber_filename = NULL;
195 static dissector_table_t ber_oid_dissector_table = NULL;
196 static dissector_table_t ber_syntax_dissector_table = NULL;
198 static GHashTable *syntax_table = NULL;
200 static gint8 last_class;
201 static gboolean last_pc;
202 static gint32 last_tag;
203 static guint32 last_length;
204 static gboolean last_ind;
206 static const value_string ber_class_codes[] = {
207 { BER_CLASS_UNI, "UNIVERSAL" },
208 { BER_CLASS_APP, "APPLICATION" },
209 { BER_CLASS_CON, "CONTEXT" },
210 { BER_CLASS_PRI, "PRIVATE" },
211 { 0, NULL }
214 static const true_false_string ber_pc_codes = {
215 "Constructed Encoding",
216 "Primitive Encoding"
219 static const true_false_string ber_pc_codes_short = {
220 "constructed",
221 "primitive"
224 static const value_string ber_uni_tag_codes[] = {
225 { BER_UNI_TAG_EOC, "'end-of-content'" },
226 { BER_UNI_TAG_BOOLEAN, "BOOLEAN" },
227 { BER_UNI_TAG_INTEGER, "INTEGER" },
228 { BER_UNI_TAG_BITSTRING, "BIT STRING" },
229 { BER_UNI_TAG_OCTETSTRING, "OCTET STRING" },
230 { BER_UNI_TAG_NULL, "NULL" },
231 { BER_UNI_TAG_OID, "OBJECT IDENTIFIER" },
232 { BER_UNI_TAG_ObjectDescriptor, "ObjectDescriptor" },
233 { BER_UNI_TAG_EXTERNAL, "EXTERNAL" },
234 { BER_UNI_TAG_REAL, "REAL" },
235 { BER_UNI_TAG_ENUMERATED, "ENUMERATED" },
236 { BER_UNI_TAG_EMBEDDED_PDV, "EMBEDDED PDV" },
237 { BER_UNI_TAG_UTF8String, "UTF8String" },
238 { BER_UNI_TAG_RELATIVE_OID, "RELATIVE-OID" },
239 /* UNIVERSAL 14-15
240 * Reserved for future editions of this
241 * Recommendation | International Standard
243 { 14, "Reserved for future editions" },
244 { 15 , "Reserved for future editions" },
246 { BER_UNI_TAG_SEQUENCE, "SEQUENCE" },
247 { BER_UNI_TAG_SET, "SET" },
248 { BER_UNI_TAG_NumericString, "NumericString" },
249 { BER_UNI_TAG_PrintableString, "PrintableString" },
250 { BER_UNI_TAG_TeletexString, "TeletexString, T61String" },
251 { BER_UNI_TAG_VideotexString, "VideotexString" },
252 { BER_UNI_TAG_IA5String, "IA5String" },
253 { BER_UNI_TAG_UTCTime, "UTCTime" },
254 { BER_UNI_TAG_GeneralizedTime, "GeneralizedTime" },
255 { BER_UNI_TAG_GraphicString, "GraphicString" },
256 { BER_UNI_TAG_VisibleString, "VisibleString, ISO64String" },
257 { BER_UNI_TAG_GeneralString, "GeneralString" },
258 { BER_UNI_TAG_UniversalString, "UniversalString" },
259 { BER_UNI_TAG_CHARACTERSTRING, "CHARACTER STRING" },
260 { BER_UNI_TAG_BMPString, "BMPString" },
261 { 31, "Continued" },
262 { 0, NULL }
264 static value_string_ext ber_uni_tag_codes_ext = VALUE_STRING_EXT_INIT(ber_uni_tag_codes);
266 #if 0
267 static const true_false_string ber_real_binary_vals = {
268 "Binary encoding",
269 "Decimal encoding"
272 static const true_false_string ber_real_decimal_vals = {
273 "SpecialRealValue",
274 "Decimal encoding "
276 #endif
278 typedef struct _da_data {
279 GHFunc func;
280 gpointer user_data;
281 } da_data;
283 typedef struct _oid_user_t {
284 char *oid;
285 char *name;
286 char *syntax;
287 } oid_user_t;
289 UAT_CSTRING_CB_DEF(oid_users, oid, oid_user_t)
290 UAT_CSTRING_CB_DEF(oid_users, name, oid_user_t)
291 UAT_VS_CSTRING_DEF(oid_users, syntax, oid_user_t, 0, "")
293 static oid_user_t *oid_users;
294 static guint num_oid_users;
296 #define MAX_SYNTAX_NAMES 128
297 /* Define non_const_value_string as a hack to prevent chackAPIs.pl from complaining */
298 #define non_const_value_string value_string
299 static non_const_value_string syntax_names[MAX_SYNTAX_NAMES+1] = {
300 {0, ""},
301 {0, NULL}
304 static const fragment_items octet_string_frag_items = {
305 /* Fragment subtrees */
306 &ett_ber_fragment,
307 &ett_ber_fragments,
308 /* Fragment fields */
309 &hf_ber_fragments,
310 &hf_ber_fragment,
311 &hf_ber_fragment_overlap,
312 &hf_ber_fragment_overlap_conflicts,
313 &hf_ber_fragment_multiple_tails,
314 &hf_ber_fragment_too_long_fragment,
315 &hf_ber_fragment_error,
316 &hf_ber_fragment_count,
317 /* Reassembled in field */
318 &hf_ber_reassembled_in,
319 /* Reassembled length field */
320 &hf_ber_reassembled_length,
321 /* Reassembled data field */
322 NULL,
323 /* Tag */
324 "OCTET STRING fragments"
327 static void *
328 oid_copy_cb(void *dest, const void *orig, size_t len _U_)
330 oid_user_t *u = (oid_user_t *)dest;
331 const oid_user_t *o = (const oid_user_t *)orig;
333 u->oid = g_strdup(o->oid);
334 u->name = g_strdup(o->name);
335 u->syntax = o->syntax;
337 return dest;
340 static void
341 oid_free_cb(void *r)
343 oid_user_t *u = (oid_user_t *)r;
345 g_free(u->oid);
346 g_free(u->name);
349 static int
350 cmp_value_string(const void *v1, const void *v2)
352 const value_string *vs1 = (const value_string *)v1;
353 const value_string *vs2 = (const value_string *)v2;
355 return strcmp(vs1->strptr, vs2->strptr);
358 static uat_field_t users_flds[] = {
359 UAT_FLD_OID(oid_users, oid, "OID", "Object Identifier"),
360 UAT_FLD_CSTRING(oid_users, name, "Name", "Human readable name for the OID"),
361 UAT_FLD_VS(oid_users, syntax, "Syntax", syntax_names, "Syntax of values associated with the OID"),
362 UAT_END_FIELDS
365 void
366 dissect_ber_oid_NULL_callback(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_)
368 return;
372 void
373 register_ber_oid_dissector_handle(const char *oid, dissector_handle_t dissector, int proto _U_, const char *name)
375 dissector_add_string("ber.oid", oid, dissector);
376 oid_add_from_string(name, oid);
379 void
380 register_ber_oid_dissector(const char *oid, dissector_t dissector, int proto, const char *name)
382 dissector_handle_t dissector_handle;
384 dissector_handle = create_dissector_handle(dissector, proto);
385 dissector_add_string("ber.oid", oid, dissector_handle);
386 oid_add_from_string(name, oid);
389 void
390 register_ber_syntax_dissector(const char *syntax, int proto, dissector_t dissector)
392 dissector_handle_t dissector_handle;
394 dissector_handle = create_dissector_handle(dissector, proto);
395 dissector_add_string("ber.syntax", syntax, dissector_handle);
399 void
400 register_ber_oid_syntax(const char *oid, const char *name, const char *syntax)
403 if (syntax && *syntax)
404 g_hash_table_insert(syntax_table, (gpointer)g_strdup(oid), (gpointer)g_strdup(syntax));
406 if (name && *name)
407 register_ber_oid_name(oid, name);
410 /* Register the oid name to get translation in proto dissection */
411 void
412 register_ber_oid_name(const char *oid, const char *name)
414 oid_add_from_string(name, oid);
417 static void
418 ber_add_syntax_name(gpointer key, gpointer value _U_, gpointer user_data)
420 guint *i = (guint*)user_data;
422 if (*i < MAX_SYNTAX_NAMES) {
423 syntax_names[*i].value = *i;
424 syntax_names[*i].strptr = (const gchar*)key;
426 (*i)++;
431 static void
432 ber_decode_as_dt(const gchar *table_name _U_, ftenum_t selector_type _U_, gpointer key, gpointer value, gpointer user_data)
434 da_data *decode_as_data;
436 decode_as_data = (da_data *)user_data;
438 decode_as_data->func(key, value, decode_as_data->user_data);
441 void
442 ber_decode_as_foreach(GHFunc func, gpointer user_data)
444 da_data decode_as_data;
446 decode_as_data.func = func;
447 decode_as_data.user_data = user_data;
449 dissector_table_foreach("ber.syntax", ber_decode_as_dt, &decode_as_data);
453 void
454 ber_decode_as(const gchar *syntax)
457 if (decode_as_syntax) {
458 g_free(decode_as_syntax);
459 decode_as_syntax = NULL;
462 if (syntax)
463 decode_as_syntax = g_strdup(syntax);
466 /* Get oid syntax from hash table to get translation in proto dissection(packet-per.c) */
467 static const gchar *
468 get_ber_oid_syntax(const char *oid)
470 return (const char *)g_hash_table_lookup(syntax_table, oid);
473 void
474 ber_set_filename(gchar *filename)
476 gchar *ptr;
478 if (ber_filename) {
479 g_free(ber_filename);
480 ber_filename = NULL;
483 if (filename) {
485 ber_filename = g_strdup(filename);
487 if ((ptr = strrchr(ber_filename, '.')) != NULL) {
489 ber_decode_as(get_ber_oid_syntax(ptr));
496 static void
497 ber_update_oids(void)
499 guint i;
501 for (i = 0; i < num_oid_users; i++)
502 register_ber_oid_syntax(oid_users[i].oid, oid_users[i].name, oid_users[i].syntax);
505 static void
506 ber_check_length (guint32 length, gint32 min_len, gint32 max_len, asn1_ctx_t *actx, proto_item *item, gboolean bit)
508 if ((min_len != -1) && (length < (guint32)min_len)) {
509 expert_add_info_format(
510 actx->pinfo, item, &ei_ber_size_constraint_string,
511 "Size constraint: %sstring too short: %d (%d .. %d)",
512 bit ? "bit " : "", length, min_len, max_len);
513 } else if ((max_len != -1) && (length > (guint32)max_len)) {
514 expert_add_info_format(
515 actx->pinfo, item, &ei_ber_size_constraint_string,
516 "Size constraint: %sstring too long: %d (%d .. %d)",
517 bit ? "bit " : "", length, min_len, max_len);
521 static void
522 ber_check_value64 (gint64 value, gint64 min_len, gint64 max_len, asn1_ctx_t *actx, proto_item *item)
524 if ((min_len != -1) && (value < min_len)) {
525 expert_add_info_format(
526 actx->pinfo, item, &ei_ber_size_constraint_value,
527 "Size constraint: value too small: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "d .. %" G_GINT64_MODIFIER "d)",
528 value, min_len, max_len);
529 } else if ((max_len != -1) && (value > max_len)) {
530 expert_add_info_format(
531 actx->pinfo, item, &ei_ber_size_constraint_value,
532 "Size constraint: value too big: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "d .. %" G_GINT64_MODIFIER "d)",
533 value, min_len, max_len);
537 static void
538 ber_check_value (guint32 value, gint32 min_len, gint32 max_len, asn1_ctx_t *actx, proto_item *item)
540 if ((min_len != -1) && (value < (guint32)min_len)) {
541 expert_add_info_format(
542 actx->pinfo, item, &ei_ber_size_constraint_value,
543 "Size constraint: value too small: %d (%d .. %d)",
544 value, min_len, max_len);
545 } else if ((max_len != -1) && (value > (guint32)max_len)) {
546 expert_add_info_format(
547 actx->pinfo, item, &ei_ber_size_constraint_value,
548 "Size constraint: value too big: %d (%d .. %d)",
549 value, min_len, max_len);
553 static void
554 ber_check_items (int cnt, gint32 min_len, gint32 max_len, asn1_ctx_t *actx, proto_item *item)
556 if ((min_len != -1) && (cnt < min_len)) {
557 expert_add_info_format(
558 actx->pinfo, item, &ei_ber_size_constraint_items,
559 "Size constraint: too few items: %d (%d .. %d)",
560 cnt, min_len, max_len);
561 } else if ((max_len != -1) && (cnt > max_len)) {
562 expert_add_info_format(
563 actx->pinfo, item, &ei_ber_size_constraint_items,
564 "Size constraint: too many items: %d (%d .. %d)",
565 cnt, min_len, max_len);
570 dissect_ber_tagged_type(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gint8 tag_cls, gint32 tag_tag, gboolean tag_impl, ber_type_fn type)
572 gint8 tmp_cls;
573 gint32 tmp_tag;
574 guint32 tmp_len;
575 tvbuff_t *next_tvb = tvb;
576 proto_item *cause;
578 #ifdef DEBUG_BER
580 const char *name;
581 header_field_info *hfinfo;
582 if (hf_id >= 0) {
583 hfinfo = proto_registrar_get_nth(hf_id);
584 name = hfinfo->name;
585 } else {
586 name = "unnamed";
588 if (tvb_length_remaining(tvb, offset) > 3) {
589 printf("dissect_ber_tagged_type(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name, implicit_tag, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
590 } else {
591 printf("dissect_ber_tagged_type(%s) entered\n", name);
594 #endif
596 if (implicit_tag) {
597 offset = type(tag_impl, tvb, offset, actx, tree, hf_id);
598 return offset;
601 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &tmp_cls, NULL, &tmp_tag);
602 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &tmp_len, NULL);
604 if ((tmp_cls != tag_cls) || (tmp_tag != tag_tag)) {
605 cause = proto_tree_add_string_format_value(
606 tree, hf_ber_error, tvb, offset, tmp_len, "wrong_tag",
607 "Wrong tag in tagged type - expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
608 val_to_str_const(tag_cls, ber_class_codes, "Unknown"),
609 tag_cls,
610 tag_tag,
611 val_to_str_ext_const(tag_tag, &ber_uni_tag_codes_ext, "Unknown"),
612 val_to_str_const(tmp_cls, ber_class_codes, "Unknown"),
613 tmp_cls,
614 tmp_tag);
615 expert_add_info(actx->pinfo, cause, &ei_ber_wrong_tag_in_tagged_type);
618 if (tag_impl) {
619 gint length_remaining;
621 length_remaining = tvb_length_remaining(tvb, offset);
622 if (tmp_len > (guint32)length_remaining)
623 tmp_len = length_remaining;
624 next_tvb = tvb_new_subset(tvb, offset, tmp_len, tmp_len);
625 type(tag_impl, next_tvb, 0, actx, tree, hf_id);
626 offset += tmp_len;
627 } else {
628 offset = type(tag_impl, tvb, offset, actx, tree, hf_id);
631 return offset;
635 * Add a "length bogus" error.
637 static proto_item *
638 ber_add_bad_length_error(packet_info *pinfo, proto_tree *tree,
639 const char *name, tvbuff_t *tvb, const gint start,
640 gint length)
642 proto_item *ti;
644 ti = proto_tree_add_string_format(
645 tree, hf_ber_error, tvb, start, length, "illegal_length",
646 "%s: length of item (%d) is not valid",
647 name, length);
648 expert_add_info_format(
649 pinfo, ti, &ei_ber_error_length,
650 "Length of item (%d) is not valid", length);
651 return ti;
655 * Like proto_tree_add_item(), but checks whether the length of the item
656 * being added is appropriate for the type of the item being added, so
657 * if it's not, we report an error rather than a dissector bug.
659 * This is for use when a field that's nominally an OCTET STRING but
660 * where we want the string further interpreted, e.g. as a number or
661 * a network address or a UN*X-style time stamp.
663 * XXX - this duplicates the length checking in proto_tree_add_item()
664 * and the routines it calls; that should really be done in one
665 * place. We *do* want to report a dissector bug in proto_tree_add_item()
666 * if the dissector explicitly says, for example, "this IPv4 address is
667 * 7 bytes long", but we don't want to report a dissector bug if the
668 * *packet* says "this IPv4 address is 7 bytes long", we want to report
669 * a malformed packet.
671 static proto_item *
672 ber_proto_tree_add_item(packet_info *pinfo, proto_tree *tree,
673 const int hfindex, tvbuff_t *tvb, const gint start,
674 gint length, const guint encoding)
676 header_field_info *hfinfo;
678 hfinfo = proto_registrar_get_nth((guint)hfindex);
679 if (hfinfo != NULL) {
680 switch (hfinfo->type) {
682 case FT_BOOLEAN:
683 case FT_UINT8:
684 case FT_UINT16:
685 case FT_UINT24:
686 case FT_UINT32:
687 case FT_INT8:
688 case FT_INT16:
689 case FT_INT24:
690 case FT_INT32:
691 if ((length != 1) && (length != 2) && (length != 3) &&
692 (length != 4))
693 return ber_add_bad_length_error(pinfo, tree,
694 hfinfo->name, tvb, start, length);
695 break;
697 case FT_IPv4:
698 if (length != FT_IPv4_LEN)
699 return ber_add_bad_length_error(pinfo, tree,
700 hfinfo->name, tvb, start, length);
701 break;
703 case FT_IPXNET:
704 if (length != FT_IPXNET_LEN)
705 return ber_add_bad_length_error(pinfo, tree,
706 hfinfo->name, tvb, start, length);
707 break;
709 case FT_IPv6:
710 if ((length < 0) || (length > FT_IPv6_LEN))
711 return ber_add_bad_length_error(pinfo, tree,
712 hfinfo->name, tvb, start, length);
713 break;
715 case FT_ETHER:
716 if (length != FT_ETHER_LEN)
717 return ber_add_bad_length_error(pinfo, tree,
718 hfinfo->name, tvb, start, length);
719 break;
721 case FT_GUID:
722 if (length != FT_GUID_LEN)
723 return ber_add_bad_length_error(pinfo, tree,
724 hfinfo->name, tvb, start, length);
725 break;
727 case FT_FLOAT:
728 if (length != 4)
729 return ber_add_bad_length_error(pinfo, tree,
730 hfinfo->name, tvb, start, length);
731 break;
733 case FT_DOUBLE:
734 if (length != 8)
735 return ber_add_bad_length_error(pinfo, tree,
736 hfinfo->name, tvb, start, length);
737 break;
739 case FT_ABSOLUTE_TIME:
740 case FT_RELATIVE_TIME:
741 if ((length != 4) && (length != 8))
742 return ber_add_bad_length_error(pinfo, tree,
743 hfinfo->name, tvb, start, length);
744 break;
746 default:
747 break;
750 return proto_tree_add_item(tree, hfindex, tvb, start, length, encoding);
753 static int
754 try_dissect_unknown_ber(packet_info *pinfo, tvbuff_t *tvb, volatile int offset, proto_tree *tree, gint nest_level)
756 int start_offset;
757 gint8 ber_class;
758 gboolean pc, ind;
759 gint32 tag;
760 guint32 len;
761 int hdr_len;
762 proto_item *item = NULL;
763 proto_tree *next_tree = NULL;
764 guint8 c;
765 guint32 i;
766 gboolean is_printable;
767 volatile gboolean is_decoded_as;
768 proto_item *pi, *cause;
769 asn1_ctx_t asn1_ctx;
771 if (nest_level > BER_MAX_NESTING) {
772 /* Assume that we have a malformed packet. */
773 THROW(ReportedBoundsError);
776 start_offset = offset;
777 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
779 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
780 offset = get_ber_length(tvb, offset, &len, &ind);
782 if (len > (guint32)tvb_length_remaining(tvb, offset)) {
783 /* hmm maybe something bad happened or the frame is short;
784 since these are not vital outputs just return instead of
785 throwing an exception.
788 if (show_internal_ber_fields) {
789 offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, &ber_class, &pc, &tag);
790 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
792 cause = proto_tree_add_string_format_value(
793 tree, hf_ber_error, tvb, offset, len, "illegal_length",
794 "length:%u longer than tvb_length_remaining:%d",
795 len,
796 tvb_length_remaining(tvb, offset));
797 expert_add_info(pinfo, cause, &ei_ber_error_length);
798 return tvb_length(tvb);
800 /* we don't care about the class only on the constructor flag */
801 switch (pc) {
803 case FALSE: /* this is not constructed */
805 switch (ber_class) { /* we do care about the class */
806 case BER_CLASS_UNI: /* it a Universal tag - we can decode it */
807 switch (tag) {
808 case BER_UNI_TAG_EOC:
809 /* XXX: shouldn't really get here */
810 break;
811 case BER_UNI_TAG_INTEGER:
812 offset = dissect_ber_integer(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_INTEGER, NULL);
813 break;
814 case BER_UNI_TAG_BITSTRING:
815 offset = dissect_ber_bitstring(FALSE, &asn1_ctx, tree, tvb, start_offset, NULL, hf_ber_unknown_BITSTRING, -1, NULL);
816 break;
817 case BER_UNI_TAG_ENUMERATED:
818 offset = dissect_ber_integer(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_ENUMERATED, NULL);
819 break;
820 case BER_UNI_TAG_GraphicString:
821 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_GraphicString, NULL);
822 break;
823 case BER_UNI_TAG_OCTETSTRING:
824 is_decoded_as = FALSE;
825 if (decode_octetstring_as_ber && (len >= 2)) {
826 volatile int ber_offset = 0;
827 guint32 ber_len = 0;
828 TRY {
829 ber_offset = get_ber_identifier(tvb, offset, NULL, &pc, NULL);
830 ber_offset = get_ber_length(tvb, ber_offset, &ber_len, NULL);
831 } CATCH_ALL {
833 ENDTRY;
834 if (pc && (ber_len > 0) && (ber_len + (ber_offset - offset) == len)) {
835 /* Decoded a constructed ASN.1 tag with a length indicating this
836 * could be BER encoded data. Try dissecting as unknown BER.
838 is_decoded_as = TRUE;
839 if (show_internal_ber_fields) {
840 offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, NULL, NULL, NULL);
841 offset = dissect_ber_length(pinfo, tree, tvb, offset, NULL, NULL);
843 item = ber_proto_tree_add_item(pinfo, tree, hf_ber_unknown_BER_OCTETSTRING, tvb, offset, len, ENC_NA);
844 next_tree = proto_item_add_subtree(item, ett_ber_octet_string);
845 offset = try_dissect_unknown_ber(pinfo, tvb, offset, next_tree, nest_level+1);
848 if (!is_decoded_as) {
849 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_OCTETSTRING, NULL);
851 break;
852 case BER_UNI_TAG_OID:
853 offset = dissect_ber_object_identifier_str(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_OID, NULL);
854 break;
855 case BER_UNI_TAG_RELATIVE_OID:
856 offset = dissect_ber_relative_oid_str(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_OID, NULL);
857 break;
858 case BER_UNI_TAG_NumericString:
859 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_NumericString, NULL);
860 break;
861 case BER_UNI_TAG_PrintableString:
862 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_PrintableString, NULL);
863 break;
864 case BER_UNI_TAG_TeletexString:
865 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_TeletexString, NULL);
866 break;
867 case BER_UNI_TAG_VisibleString:
868 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_VisibleString, NULL);
869 break;
870 case BER_UNI_TAG_GeneralString:
871 offset = dissect_ber_GeneralString(&asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_GeneralString, NULL, 0);
872 break;
873 case BER_UNI_TAG_BMPString:
874 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_BMPString, NULL);
875 break;
876 case BER_UNI_TAG_UniversalString:
877 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_UniversalString, NULL);
878 break;
879 case BER_UNI_TAG_IA5String:
880 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_IA5String, NULL);
881 break;
882 case BER_UNI_TAG_UTCTime:
883 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_UTCTime, NULL);
884 break;
885 case BER_UNI_TAG_NULL:
886 proto_tree_add_text(tree, tvb, offset, len, "NULL tag");
887 break;
888 case BER_UNI_TAG_UTF8String:
889 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_UTF8String, NULL);
890 break;
891 case BER_UNI_TAG_GeneralizedTime:
892 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_GeneralizedTime, NULL);
893 break;
894 case BER_UNI_TAG_BOOLEAN:
895 offset = dissect_ber_boolean(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_BOOLEAN, NULL);
896 break;
897 default:
898 offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, &ber_class, &pc, &tag);
899 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
900 cause = proto_tree_add_string_format_value(
901 tree, hf_ber_error, tvb, offset, len, "unknown_universal_tag",
902 "can not handle universal tag:%d",
903 tag);
904 expert_add_info(pinfo, cause, &ei_ber_universal_tag_unknown);
905 offset += len;
907 break;
908 case BER_CLASS_APP:
909 case BER_CLASS_CON:
910 case BER_CLASS_PRI:
911 default:
912 /* we dissect again if show_internal_ber_fields is set */
913 if (show_internal_ber_fields) {
914 offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, &ber_class, &pc, &tag);
915 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
918 /* we can't dissect this directly as it is specific */
919 pi = proto_tree_add_none_format(tree, hf_ber_unknown_BER_primitive, tvb, offset, len,
920 "[%s %d] ", val_to_str_const(ber_class, ber_class_codes, "Unknown"), tag);
922 is_decoded_as = FALSE;
923 if (decode_primitive_as_ber && (len >= 2)) {
924 volatile int ber_offset = 0;
925 guint32 ber_len = 0;
926 TRY {
927 ber_offset = get_ber_identifier(tvb, offset, NULL, &pc, NULL);
928 ber_offset = get_ber_length(tvb, ber_offset, &ber_len, NULL);
929 } CATCH_ALL {
931 ENDTRY;
932 if (pc && (ber_len > 0) && (ber_len + (ber_offset - offset) == len)) {
933 /* Decoded a constructed ASN.1 tag with a length indicating this
934 * could be BER encoded data. Try dissecting as unknown BER.
936 is_decoded_as = TRUE;
937 proto_item_append_text (pi, "[BER encoded]");
938 next_tree = proto_item_add_subtree(pi, ett_ber_primitive);
939 offset = try_dissect_unknown_ber(pinfo, tvb, offset, next_tree, nest_level+1);
943 if (!is_decoded_as && len) {
944 /* we may want to do better and show the bytes */
945 is_printable = TRUE;
946 for (i=0; i<len; i++) {
947 c = tvb_get_guint8(tvb, offset+i);
949 if (is_printable && !g_ascii_isprint(c))
950 is_printable = FALSE;
952 proto_item_append_text(pi, "%02x", c);
955 if (is_printable) { /* give a nicer representation if it looks like a string */
956 proto_item_append_text(pi, " (");
957 for (i=0; i<len; i++) {
958 proto_item_append_text(pi, "%c", tvb_get_guint8(tvb, offset+i));
960 proto_item_append_text(pi, ")");
962 offset += len;
965 break;
967 break;
969 case TRUE: /* this is constructed */
971 /* we dissect again if show_internal_ber_fields is set */
972 if (show_internal_ber_fields) {
973 offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, &ber_class, &pc, &tag);
974 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
977 hdr_len = offset-start_offset;
979 switch (ber_class) {
980 case BER_CLASS_UNI:
981 item = proto_tree_add_text(tree, tvb, offset, len, "%s", val_to_str_ext_const(tag, &ber_uni_tag_codes_ext, "Unknown"));
982 if (item) {
983 next_tree = proto_item_add_subtree(item, ett_ber_SEQUENCE);
985 while (offset < (int)(start_offset + len + hdr_len))
986 offset = try_dissect_unknown_ber(pinfo, tvb, offset, next_tree, nest_level+1);
987 break;
988 case BER_CLASS_APP:
989 case BER_CLASS_CON:
990 case BER_CLASS_PRI:
991 default:
992 item = proto_tree_add_text(tree, tvb, offset, len, "[%s %d]", val_to_str_const(ber_class, ber_class_codes, "Unknown"), tag);
993 if (item) {
994 next_tree = proto_item_add_subtree(item, ett_ber_SEQUENCE);
996 while (offset < (int)(start_offset + len + hdr_len))
997 offset = try_dissect_unknown_ber(pinfo, tvb, offset, next_tree, nest_level+1);
998 break;
1001 break;
1005 return offset;
1009 dissect_unknown_ber(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree)
1011 return try_dissect_unknown_ber(pinfo, tvb, offset, tree, 1);
1015 call_ber_oid_callback(const char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data)
1017 tvbuff_t *next_tvb;
1018 const char *syntax = NULL;
1020 if (!tvb) {
1021 return offset;
1024 next_tvb = tvb_new_subset_remaining(tvb, offset);
1025 if (oid == NULL ||
1026 ((((syntax = get_ber_oid_syntax(oid)) == NULL) ||
1027 /* First see if a syntax has been registered for this oid (user defined) */
1028 !dissector_try_string(ber_syntax_dissector_table, syntax, next_tvb, pinfo, tree, data)) &&
1029 /* Then try registered oid's */
1030 (!dissector_try_string(ber_oid_dissector_table, oid, next_tvb, pinfo, tree, data)))) {
1031 proto_item *item = NULL;
1032 proto_tree *next_tree = NULL;
1033 gint length_remaining;
1035 length_remaining = tvb_length_remaining(tvb, offset);
1037 if (oid == NULL) {
1038 item = proto_tree_add_expert(tree, pinfo, &ei_ber_no_oid, next_tvb, 0, length_remaining);
1039 } else if (tvb_get_ntohs (tvb, offset) != 0x0500) { /* Not NULL tag */
1040 if (syntax) {
1041 item = proto_tree_add_expert_format(
1042 tree, pinfo, &ei_ber_syntax_not_implemented, next_tvb, 0, length_remaining,
1043 "BER: Dissector for syntax:%s not implemented."
1044 " Contact Wireshark developers if you want this supported",
1045 syntax);
1046 } else {
1047 item = proto_tree_add_expert(tree, pinfo, &ei_ber_oid_not_implemented, next_tvb, 0, length_remaining);
1049 } else {
1050 next_tree = tree;
1052 if (decode_unexpected) {
1053 int ber_offset;
1054 gint32 ber_len;
1056 if (item) {
1057 next_tree = proto_item_add_subtree(item, ett_ber_unknown);
1059 ber_offset = get_ber_identifier(next_tvb, 0, NULL, NULL, NULL);
1060 ber_offset = get_ber_length(next_tvb, ber_offset, &ber_len, NULL);
1061 if ((ber_len + ber_offset) == length_remaining) {
1062 /* Decoded an ASN.1 tag with a length indicating this
1063 * could be BER encoded data. Try dissecting as unknown BER.
1065 dissect_unknown_ber(pinfo, next_tvb, 0, next_tree);
1066 } else {
1067 proto_tree_add_text(next_tree, next_tvb, 0, length_remaining,
1068 "Unknown Data (%d byte%s)", length_remaining,
1069 plurality(length_remaining, "", "s"));
1075 /*XXX until we change the #.REGISTER signature for _PDU()s
1076 * into new_dissector_t we have to do this kludge with
1077 * manually step past the content in the ANY type.
1079 offset += tvb_length_remaining(tvb, offset);
1081 return offset;
1084 static int
1085 call_ber_syntax_callback(const char *syntax, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1087 tvbuff_t *next_tvb;
1089 next_tvb = tvb_new_subset_remaining(tvb, offset);
1090 if (syntax == NULL ||
1091 !dissector_try_string(ber_syntax_dissector_table, syntax, next_tvb, pinfo, tree, NULL)) {
1092 proto_item *item = NULL;
1093 proto_tree *next_tree = NULL;
1095 if (syntax == NULL) {
1096 item = proto_tree_add_expert_format(
1097 tree, pinfo, &ei_ber_no_oid, next_tvb, 0, tvb_length_remaining(tvb, offset),
1098 "BER: No syntax supplied to call_ber_syntax_callback");
1099 } else {
1100 item = proto_tree_add_expert_format(
1101 tree, pinfo, &ei_ber_syntax_not_implemented, next_tvb, 0, tvb_length_remaining(tvb, offset),
1102 "BER: Dissector for syntax:%s not implemented."
1103 " Contact Wireshark developers if you want this supported",
1104 syntax);
1106 if (item) {
1107 next_tree = proto_item_add_subtree(item, ett_ber_unknown);
1109 dissect_unknown_ber(pinfo, next_tvb, 0, next_tree);
1112 /*XXX until we change the #.REGISTER signature for _PDU()s
1113 * into new_dissector_t we have to do this kludge with
1114 * manually step past the content in the ANY type.
1116 offset+=tvb_length_remaining(tvb, offset);
1118 return offset;
1122 /* 8.1 General rules for encoding */
1124 /* 8.1.2 Identifier octets */
1126 get_ber_identifier(tvbuff_t *tvb, int offset, gint8 *ber_class, gboolean *pc, gint32 *tag) {
1127 guint8 id, t;
1128 gint8 tmp_class;
1129 gboolean tmp_pc;
1130 gint32 tmp_tag;
1132 id = tvb_get_guint8(tvb, offset);
1133 offset += 1;
1134 #ifdef DEBUG_BER
1135 printf ("BER ID=%02x", id);
1136 #endif
1137 /* 8.1.2.2 */
1138 tmp_class = (id >> 6) & 0x03;
1139 tmp_pc = (id >> 5) & 0x01;
1140 tmp_tag = id & 0x1F;
1141 /* 8.1.2.4 */
1142 if (tmp_tag == 0x1F) {
1143 tmp_tag = 0;
1144 while (tvb_length_remaining(tvb, offset) > 0) {
1145 t = tvb_get_guint8(tvb, offset);
1146 #ifdef DEBUG_BER
1147 printf (" %02x", t);
1148 #endif
1149 offset += 1;
1150 tmp_tag <<= 7;
1151 tmp_tag |= t & 0x7F;
1152 if (!(t & 0x80))
1153 break;
1157 #ifdef DEBUG_BER
1158 printf ("\n");
1159 #endif
1160 if (ber_class)
1161 *ber_class = tmp_class;
1162 if (pc)
1163 *pc = tmp_pc;
1164 if (tag)
1165 *tag = tmp_tag;
1167 last_class = tmp_class;
1168 last_pc = tmp_pc;
1169 last_tag = tmp_tag;
1171 return offset;
1174 static void
1175 get_last_ber_identifier(gint8 *ber_class, gboolean *pc, gint32 *tag)
1177 if (ber_class)
1178 *ber_class = last_class;
1179 if (pc)
1180 *pc = last_pc;
1181 if (tag)
1182 *tag = last_tag;
1187 dissect_ber_identifier(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gint8 *ber_class, gboolean *pc, gint32 *tag)
1189 int old_offset = offset;
1190 gint8 tmp_class;
1191 gboolean tmp_pc;
1192 gint32 tmp_tag;
1194 offset = get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
1196 if (show_internal_ber_fields) {
1197 proto_tree_add_uint(tree, hf_ber_id_class, tvb, old_offset, 1, tmp_class << 6);
1198 proto_tree_add_boolean(tree, hf_ber_id_pc, tvb, old_offset, 1, (tmp_pc) ? 0x20 : 0x00);
1199 if (tmp_tag > 0x1F) {
1200 if (tmp_class == BER_CLASS_UNI) {
1201 proto_tree_add_uint(tree, hf_ber_id_uni_tag_ext, tvb, old_offset + 1, offset - (old_offset + 1), tmp_tag);
1202 } else {
1203 proto_tree_add_uint(tree, hf_ber_id_tag_ext, tvb, old_offset + 1, offset - (old_offset + 1), tmp_tag);
1205 } else {
1206 if (tmp_class == BER_CLASS_UNI) {
1207 proto_tree_add_uint(tree, hf_ber_id_uni_tag, tvb, old_offset, 1, tmp_tag);
1208 } else {
1209 proto_tree_add_uint(tree, hf_ber_id_tag, tvb, old_offset, 1, tmp_tag);
1214 if (ber_class)
1215 *ber_class = tmp_class;
1216 if (pc)
1217 *pc = tmp_pc;
1218 if (tag)
1219 *tag = tmp_tag;
1221 return offset;
1224 /** Try to get the length octets of the BER TLV.
1225 * Only (TAGs and) LENGTHs that fit inside 32 bit integers are supported.
1227 * @return TRUE if we have the entire length, FALSE if we're in the middle of
1228 * an indefinite length and haven't reached EOC.
1230 /* 8.1.3 Length octets */
1232 static int
1233 try_get_ber_length(tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind, gint nest_level) {
1234 guint8 oct, len;
1235 guint32 indef_len;
1236 guint32 tmp_length;
1237 gboolean tmp_ind;
1238 int tmp_offset, s_offset;
1239 gint8 tclass;
1240 gboolean tpc;
1241 gint32 ttag;
1243 tmp_length = 0;
1244 tmp_ind = FALSE;
1246 if (nest_level > BER_MAX_NESTING) {
1247 /* Assume that we have a malformed packet. */
1248 THROW(ReportedBoundsError);
1251 oct = tvb_get_guint8(tvb, offset);
1252 offset += 1;
1254 if (!(oct & 0x80)) {
1255 /* 8.1.3.4 */
1256 tmp_length = oct;
1257 } else {
1258 len = oct & 0x7F;
1259 if (len) {
1260 /* 8.1.3.5 */
1261 while (len--) {
1262 oct = tvb_get_guint8(tvb, offset);
1263 offset++;
1264 tmp_length = (tmp_length<<8) + oct;
1266 } else {
1267 /* 8.1.3.6 */
1269 tmp_offset = offset;
1270 /* ok in here we can traverse the BER to find the length, this will fix most indefinite length issues */
1271 /* Assumption here is that indefinite length is always used on constructed types*/
1272 /* check for EOC */
1273 while (tvb_get_guint8(tvb, offset) || tvb_get_guint8(tvb, offset+1)) {
1274 /* not an EOC at offset */
1275 s_offset = offset;
1276 offset= get_ber_identifier(tvb, offset, &tclass, &tpc, &ttag);
1277 offset= try_get_ber_length(tvb, offset, &indef_len, NULL, nest_level+1);
1278 tmp_length += indef_len+(offset-s_offset); /* length + tag and length */
1279 offset += indef_len;
1280 /* Make sure we've moved forward in the packet */
1281 if (offset <= s_offset)
1282 THROW(ReportedBoundsError);
1284 tmp_length += 2;
1285 tmp_ind = TRUE;
1286 offset = tmp_offset;
1290 if (length)
1291 *length = tmp_length;
1292 if (ind)
1293 *ind = tmp_ind;
1295 #ifdef DEBUG_BER
1296 printf("get BER length %d, offset %d (remaining %d)\n", tmp_length, offset, tvb_length_remaining(tvb, offset));
1297 #endif
1299 return offset;
1303 get_ber_length(tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind)
1305 return try_get_ber_length(tvb, offset, length, ind, 1);
1308 static void
1309 get_last_ber_length(guint32 *length, gboolean *ind)
1311 if (length)
1312 *length = last_length;
1313 if (ind)
1314 *ind = last_ind;
1317 /* this function dissects the length octets of the BER TLV.
1318 * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
1321 dissect_ber_length(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind)
1323 int old_offset = offset;
1324 guint32 tmp_length;
1325 gboolean tmp_ind;
1327 offset = get_ber_length(tvb, offset, &tmp_length, &tmp_ind);
1329 if (show_internal_ber_fields) {
1330 if (tmp_ind) {
1331 proto_tree_add_text(tree, tvb, old_offset, 1, "Length: Indefinite length %d", tmp_length);
1332 } else {
1333 proto_tree_add_uint(tree, hf_ber_length, tvb, old_offset, offset - old_offset, tmp_length);
1336 if (length)
1337 *length = tmp_length;
1338 if (ind)
1339 *ind = tmp_ind;
1341 #ifdef DEBUG_BER
1342 printf("dissect BER length %d, offset %d (remaining %d)\n", tmp_length, offset, tvb_length_remaining(tvb, offset));
1343 #endif
1345 last_length = tmp_length;
1346 last_ind = tmp_ind;
1348 return offset;
1351 static reassembly_table octet_segment_reassembly_table;
1353 static void ber_defragment_init(void) {
1354 reassembly_table_init(&octet_segment_reassembly_table,
1355 &addresses_reassembly_table_functions);
1358 static int
1359 reassemble_octet_string(asn1_ctx_t *actx, proto_tree *tree, gint hf_id, tvbuff_t *tvb, int offset, guint32 con_len, gboolean ind, tvbuff_t **out_tvb)
1361 fragment_head *fd_head = NULL;
1362 tvbuff_t *next_tvb = NULL;
1363 tvbuff_t *reassembled_tvb = NULL;
1364 guint16 dst_ref = 0;
1365 int start_offset = offset;
1366 gboolean fragment = TRUE;
1367 gboolean firstFragment = TRUE;
1369 /* so we need to consume octet strings for the given length */
1371 if (out_tvb)
1372 *out_tvb = NULL;
1374 if (con_len == 0) /* Zero encodings (8.7.3) */
1375 return offset;
1377 /* not sure we need this */
1378 actx->pinfo->fragmented = TRUE;
1380 while(!fd_head) {
1382 offset = dissect_ber_octet_string(FALSE, actx, NULL, tvb, offset, hf_id, &next_tvb);
1384 if (next_tvb == NULL) {
1385 /* Assume that we have a malformed packet. */
1386 THROW(ReportedBoundsError);
1389 if (ind) {
1390 /* this was indefinite length - so check for EOC */
1392 if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
1393 fragment = FALSE;
1394 /* skip past EOC */
1395 offset +=2;
1397 } else {
1399 if ((guint32)(offset - start_offset) >= con_len)
1400 fragment = FALSE;
1403 if (!fragment && firstFragment) {
1404 /* there is only one fragment (I'm sure there's a reason it was constructed) */
1405 /* anyway, we can get out of here */
1406 gboolean pc;
1407 get_ber_identifier(tvb, start_offset, NULL, &pc, NULL);
1408 if (!pc && tree) {
1409 /* Only display here if not constructed */
1410 dissect_ber_octet_string(FALSE, actx, tree, tvb, start_offset, hf_id, NULL);
1412 reassembled_tvb = next_tvb;
1413 break;
1417 if (tvb_length(next_tvb) < 1) {
1418 /* Don't cause an assertion in the reassembly code. */
1419 THROW(ReportedBoundsError);
1421 fd_head = fragment_add_seq_next(&octet_segment_reassembly_table,
1422 next_tvb, 0, actx->pinfo, dst_ref, NULL,
1423 tvb_length(next_tvb),
1424 fragment);
1426 firstFragment = FALSE;
1429 if (fd_head) {
1430 if (fd_head->next) {
1431 /* not sure I really want to do this here - should be nearer the application where we can give it a better name*/
1432 proto_tree *next_tree;
1433 proto_item *frag_tree_item;
1435 reassembled_tvb = tvb_new_chain(next_tvb, fd_head->tvb_data);
1437 actx->created_item = proto_tree_add_item(tree, hf_id, reassembled_tvb, 0, -1, ENC_BIG_ENDIAN);
1438 next_tree = proto_item_add_subtree (actx->created_item, ett_ber_reassembled_octet_string);
1440 add_new_data_source(actx->pinfo, reassembled_tvb, "Reassembled OCTET STRING");
1441 show_fragment_seq_tree(fd_head, &octet_string_frag_items, next_tree, actx->pinfo, reassembled_tvb, &frag_tree_item);
1445 if (out_tvb)
1446 *out_tvb = reassembled_tvb;
1448 /* again - not sure we need this */
1449 actx->pinfo->fragmented = FALSE;
1451 return offset;
1455 /* 8.7 Encoding of an octetstring value */
1457 dissect_ber_constrained_octet_string(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, tvbuff_t **out_tvb) {
1458 gint8 ber_class;
1459 gboolean pc, ind;
1460 gint32 tag;
1461 guint32 len;
1462 int hoffset;
1463 int end_offset;
1464 proto_item *it, *cause;
1465 guint32 i;
1466 guint32 len_remain;
1468 #ifdef DEBUG_BER
1470 const char *name;
1471 header_field_info *hfinfo;
1472 if (hf_id >= 0) {
1473 hfinfo = proto_registrar_get_nth(hf_id);
1474 name = hfinfo->name;
1475 } else {
1476 name = "unnamed";
1478 if (tvb_length_remaining(tvb, offset) > 3) {
1479 printf("OCTET STRING dissect_ber_octet string(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name, implicit_tag, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
1480 } else {
1481 printf("OCTET STRING dissect_ber_octet_string(%s) entered\n", name);
1484 #endif
1486 if (out_tvb)
1487 *out_tvb = NULL;
1489 if (!implicit_tag) {
1490 hoffset = offset;
1491 /* read header and len for the octet string */
1492 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
1493 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
1494 end_offset = offset+len;
1496 /* sanity check: we only handle Constructed Universal Sequences */
1497 if ((ber_class != BER_CLASS_APP) && (ber_class != BER_CLASS_PRI)) {
1498 if ( (ber_class != BER_CLASS_UNI)
1499 || ((tag < BER_UNI_TAG_NumericString) && (tag != BER_UNI_TAG_OCTETSTRING) && (tag != BER_UNI_TAG_UTF8String)) ) {
1500 tvb_ensure_bytes_exist(tvb, hoffset, 2);
1501 cause = proto_tree_add_string_format_value(
1502 tree, hf_ber_error, tvb, offset, len, "octetstring_expected",
1503 "OctetString expected but class:%s(%d) %s tag:%d was unexpected",
1504 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
1505 ber_class,
1506 pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
1507 tag);
1508 expert_add_info(actx->pinfo, cause, &ei_ber_expected_octet_string);
1509 if (decode_unexpected) {
1510 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
1511 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1513 return end_offset;
1516 } else {
1517 /* implicit tag so get from last tag/length */
1519 get_last_ber_identifier(&ber_class, &pc, &tag);
1520 get_last_ber_length(&len, &ind);
1522 end_offset = offset+len;
1524 /* caller may have created new buffer for indefinite length data Verify via length */
1525 len_remain = (guint32)tvb_length_remaining(tvb, offset);
1526 if (ind && (len_remain == (len - 2))) {
1527 /* new buffer received so adjust length and indefinite flag */
1528 len -= 2;
1529 end_offset -= 2;
1530 ind = FALSE;
1531 } else if (len_remain < len) {
1533 * error - short frame, or this item runs past the
1534 * end of the item containing it
1536 cause = proto_tree_add_string_format_value(
1537 tree, hf_ber_error, tvb, offset, len, "illegal_length",
1538 "length:%u longer than tvb_length_remaining:%d",
1539 len,
1540 len_remain);
1541 expert_add_info(actx->pinfo, cause, &ei_ber_error_length);
1542 return end_offset;
1547 actx->created_item = NULL;
1549 if (pc) {
1550 /* constructed */
1551 end_offset = reassemble_octet_string(actx, tree, hf_id, tvb, offset, len, ind, out_tvb);
1552 } else {
1553 /* primitive */
1554 gint length_remaining;
1556 length_remaining = tvb_length_remaining(tvb, offset);
1557 #if 0
1558 if (length_remaining < 1) {
1559 return end_offset;
1561 #endif
1563 if (len <= (guint32)length_remaining) {
1564 length_remaining = len;
1566 if (hf_id >= 0) {
1567 it = ber_proto_tree_add_item(actx->pinfo, tree, hf_id, tvb, offset, length_remaining, ENC_BIG_ENDIAN);
1568 actx->created_item = it;
1569 ber_check_length(length_remaining, min_len, max_len, actx, it, FALSE);
1570 } else {
1571 proto_item *pi;
1573 pi = proto_tree_add_text(tree, tvb, offset, len, "Unknown OctetString: Length: 0x%02x, Value: 0x", len);
1574 if (pi) {
1575 for (i=0; i<len; i++) {
1576 proto_item_append_text(pi, "%02x", tvb_get_guint8(tvb, offset));
1577 offset++;
1582 if (out_tvb) {
1583 if (len > (guint32)length_remaining)
1584 len = length_remaining;
1585 *out_tvb = tvb_new_subset(tvb, offset, len, len);
1588 return end_offset;
1592 dissect_ber_octet_string(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb) {
1593 return dissect_ber_constrained_octet_string(implicit_tag, actx, tree, tvb, offset, NO_BOUND, NO_BOUND, hf_id, out_tvb);
1597 dissect_ber_octet_string_wcb(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, ber_callback func)
1599 tvbuff_t *out_tvb = NULL;
1601 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_id, (func) ? &out_tvb : NULL);
1602 if (func && out_tvb && (tvb_length(out_tvb) > 0)) {
1603 if (hf_id >= 0)
1604 tree = proto_item_add_subtree(actx->created_item, ett_ber_octet_string);
1605 /* TODO Should hf_id2 be pased as last parameter???*/
1606 func(FALSE, out_tvb, 0, actx, tree, -1);
1608 return offset;
1612 dissect_ber_old_octet_string_wcb(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, ber_old_callback func)
1614 tvbuff_t *out_tvb = NULL;
1616 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_id, (func) ? &out_tvb : NULL);
1617 if (func && out_tvb && (tvb_length(out_tvb) > 0)) {
1618 if (hf_id >= 0)
1619 tree = proto_item_add_subtree(actx->created_item, ett_ber_octet_string);
1620 /* TODO Should hf_id2 be pased as last parameter???*/
1621 func(tree, out_tvb, 0, actx);
1623 return offset;
1625 /* 8.8 Encoding of a null value */
1627 dissect_ber_null(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id) {
1628 gint8 ber_class;
1629 gboolean pc;
1630 gint32 tag;
1631 guint32 len;
1632 int offset_old;
1633 proto_item* cause;
1635 if (!implicit_tag) {
1636 offset_old = offset;
1637 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
1638 if (pc ||
1639 (!implicit_tag && ((ber_class != BER_CLASS_UNI) || (tag != BER_UNI_TAG_NULL)))) {
1640 cause = proto_tree_add_string_format_value(
1641 tree, hf_ber_error, tvb, offset_old, offset - offset_old, "null_expected",
1642 "NULL expected but class:%s(%d) %s tag:%d was unexpected",
1643 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
1644 ber_class,
1645 pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
1646 tag);
1647 expert_add_info(actx->pinfo, cause, &ei_ber_expected_null);
1650 offset_old = offset;
1651 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
1652 if (len) {
1653 proto_tree_add_string_format_value(
1654 tree, hf_ber_error, tvb, offset_old, offset - offset_old, "illegal_length",
1655 "NULL expect zero length but Length=%d",
1656 len);
1657 cause = proto_tree_add_string_format_value(
1658 tree, hf_ber_error, tvb, offset, len, "unexpected_data",
1659 "unexpected data in NULL type");
1660 expert_add_info(actx->pinfo, cause, &ei_ber_expected_null_zero_length);
1661 offset += len;
1664 if (hf_id >= 0)
1665 proto_tree_add_item(tree, hf_id, tvb, offset, 0, ENC_BIG_ENDIAN);
1666 return offset;
1670 dissect_ber_integer64(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gint64 *value)
1672 gint8 ber_class;
1673 gboolean pc;
1674 gint32 tag;
1675 guint32 len;
1676 gint64 val;
1677 guint32 i;
1678 gboolean used_too_many_bytes = FALSE;
1679 guint8 first;
1680 #ifdef DEBUG_BER
1682 const char *name;
1683 header_field_info *hfinfo;
1684 if (hf_id >= 0) {
1685 hfinfo = proto_registrar_get_nth(hf_id);
1686 name = hfinfo->name;
1687 } else {
1688 name = "unnamed";
1690 if (tvb_length_remaining(tvb, offset) > 3) {
1691 printf("INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name, implicit_tag, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
1692 } else {
1693 printf("INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d \n", name, implicit_tag);
1696 #endif
1699 if (value) {
1700 *value = 0;
1703 if (!implicit_tag) {
1704 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
1705 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
1706 } else {
1707 gint32 remaining = tvb_length_remaining(tvb, offset);
1708 len = remaining>0 ? remaining : 0;
1711 first = tvb_get_guint8(tvb, offset);
1712 /* we can't handle integers > 64 bits */
1713 /* take into account the use case of a 64bits unsigned integer: you will have a 9th byte set to 0 */
1714 if ((len > 9) || ((len == 9) && (first != 0))) {
1715 header_field_info *hfinfo;
1716 proto_item *pi = NULL;
1718 if (hf_id >= 0) {
1719 hfinfo = proto_registrar_get_nth(hf_id);
1720 pi = proto_tree_add_text(tree, tvb, offset, len, "%s : 0x", hfinfo->name);
1722 if (pi) {
1723 for (i=0; i<len; i++) {
1724 proto_item_append_text(pi, "%02x", tvb_get_guint8(tvb, offset));
1725 offset++;
1727 } else {
1728 offset += len;
1730 return offset;
1733 val=0;
1734 if (len > 0) {
1735 /* extend sign bit for signed fields */
1736 enum ftenum type = FT_INT32; /* Default to signed, is this correct? */
1737 if (hf_id >= 0) {
1738 type = proto_registrar_get_ftype(hf_id);
1740 if (first & 0x80 && IS_FT_INT(type)) {
1741 val = -1;
1743 if ((len > 1) && decode_warning_leading_zero_bits) {
1744 guint8 second = tvb_get_guint8(tvb, offset+1);
1745 if (((first == 0x00) && ((second & 0x80) == 0)) ||
1746 ((first == 0xff) && ((second & 0x80) != 0))) {
1747 used_too_many_bytes = TRUE;
1750 for (i=0; i<len; i++) {
1751 val = (val<<8) | tvb_get_guint8(tvb, offset);
1752 offset++;
1756 actx->created_item = NULL;
1758 if (hf_id >= 0) {
1759 /* */
1760 if ((len < 1) || (len > 9) || ((len == 9) && (first != 0))) {
1761 proto_item *pi = proto_tree_add_string_format_value(
1762 tree, hf_ber_error, tvb, offset-len, len, "invalid length",
1763 "Can't handle integer length: %u",
1764 len);
1765 expert_add_info_format(actx->pinfo, pi, &ei_ber_error_length,
1766 "BER Error: Illegal integer length: %u", len);
1767 } else {
1768 header_field_info* hfi;
1770 hfi = proto_registrar_get_nth(hf_id);
1771 switch (hfi->type) {
1772 case FT_UINT8:
1773 case FT_UINT16:
1774 case FT_UINT24:
1775 case FT_UINT32:
1776 actx->created_item = proto_tree_add_uint(tree, hf_id, tvb, offset-len, len, (guint32)val);
1777 break;
1778 case FT_INT8:
1779 case FT_INT16:
1780 case FT_INT24:
1781 case FT_INT32:
1782 actx->created_item = proto_tree_add_int(tree, hf_id, tvb, offset-len, len, (gint32)val);
1783 break;
1784 case FT_INT64:
1785 actx->created_item = proto_tree_add_int64(tree, hf_id, tvb, offset-len, len, val);
1786 break;
1787 case FT_UINT64:
1788 actx->created_item = proto_tree_add_uint64(tree, hf_id, tvb, offset-len, len, (guint64)val);
1789 break;
1790 default:
1791 DISSECTOR_ASSERT_NOT_REACHED();
1794 if (used_too_many_bytes) {
1795 expert_add_info_format(
1796 actx->pinfo, actx->created_item, &ei_ber_value_too_many_bytes,
1797 "Value is encoded with too many bytes(9 leading zero or one bits), hf_abbr: %s",
1798 hfi->abbrev);
1803 if (value) {
1804 *value = val;
1807 return offset;
1811 dissect_ber_constrained_integer64(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint64 min_len, gint64 max_len, gint hf_id, gint64 *value)
1813 gint64 val;
1815 offset = dissect_ber_integer64(implicit_tag, actx, tree, tvb, offset, hf_id, &val);
1816 if (value) {
1817 *value = val;
1820 ber_check_value64 (val, min_len, max_len, actx, actx->created_item);
1822 return offset;
1826 dissect_ber_integer(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, guint32 *value)
1828 gint64 val;
1830 offset = dissect_ber_integer64(implicit_tag, actx, tree, tvb, offset, hf_id, &val);
1831 if (value) {
1832 *value = (guint32)val;
1835 return offset;
1839 dissect_ber_constrained_integer(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, guint32 *value)
1841 gint64 val;
1843 offset = dissect_ber_integer64(implicit_tag, actx, tree, tvb, offset, hf_id, &val);
1844 if (value) {
1845 *value = (guint32)val;
1848 ber_check_value ((guint32)val, min_len, max_len, actx, actx->created_item);
1850 return offset;
1854 dissect_ber_boolean(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gboolean *value)
1856 gint8 ber_class;
1857 gboolean pc;
1858 gint32 tag;
1859 guint32 len;
1860 guint8 val;
1861 header_field_info *hfi;
1863 if (!implicit_tag) {
1864 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
1865 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
1866 /*if (ber_class != BER_CLASS_UNI)*/
1867 } else {
1868 /* nothing to do here, yet */
1871 val = tvb_get_guint8(tvb, offset);
1872 offset += 1;
1874 actx->created_item = NULL;
1876 if (hf_id >= 0) {
1877 hfi = proto_registrar_get_nth(hf_id);
1878 if (hfi->type == FT_BOOLEAN)
1879 actx->created_item = proto_tree_add_boolean(tree, hf_id, tvb, offset-1, 1, val);
1880 else
1881 actx->created_item = proto_tree_add_uint(tree, hf_id, tvb, offset-1, 1, val ? 1 : 0);
1884 if (value) {
1885 *value = (val ? TRUE : FALSE);
1888 return offset;
1892 /* 8.5 Encoding of a real value */
1893 /* NOT Tested*/
1895 dissect_ber_real(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id _U_, double *value)
1897 gint8 ber_class;
1898 gboolean pc;
1899 gint32 tag;
1900 guint32 val_length = 0, end_offset;
1901 double val = 0;
1903 if (!implicit_tag) {
1904 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
1905 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &val_length, NULL);
1906 } else {
1907 /* 8.5.1 The encoding of a real value shall be primitive. */
1908 DISSECTOR_ASSERT_NOT_REACHED();
1910 /* 8.5.2 If the real value is the value zero,
1911 * there shall be no contents octets in the encoding.
1913 if (val_length == 0) {
1914 if (value)
1915 *value = 0;
1916 return offset;
1918 end_offset = offset + val_length;
1920 val = asn1_get_real(tvb_get_ptr(tvb, offset, val_length), val_length);
1921 actx->created_item = proto_tree_add_double(tree, hf_id, tvb, offset, val_length, val);
1923 if (value)
1924 *value = val;
1926 return end_offset;
1929 /* this function dissects a BER sequence
1932 dissect_ber_sequence(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
1933 gint8 classx;
1934 gboolean pcx, ind = 0, ind_field, imp_tag = FALSE;
1935 gint32 tagx;
1936 guint32 lenx;
1937 proto_tree *tree = parent_tree;
1938 proto_item *item = NULL;
1939 proto_item *cause;
1940 int end_offset = 0;
1941 int hoffset;
1942 gint length_remaining;
1943 tvbuff_t *next_tvb;
1945 #ifdef DEBUG_BER
1947 const char *name;
1948 header_field_info *hfinfo;
1949 if (hf_id >= 0) {
1950 hfinfo = proto_registrar_get_nth(hf_id);
1951 name = hfinfo->name;
1952 } else {
1953 name = "unnamed";
1955 if (tvb_length_remaining(tvb, offset) > 3) {
1956 printf("SEQUENCE dissect_ber_sequence(%s) entered offset:%d len:%d %02x:%02x:%02x\n", name, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
1957 } else {
1958 printf("SEQUENCE dissect_ber_sequence(%s) entered\n", name);
1961 #endif
1962 hoffset = offset;
1963 if (!implicit_tag) {
1964 offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
1965 offset = get_ber_length(tvb, offset, &lenx, NULL);
1966 } else {
1967 /* was implicit tag so just use the length of the tvb */
1968 lenx = tvb_length_remaining(tvb, offset);
1969 end_offset = offset+lenx;
1971 /* create subtree */
1972 if (hf_id >= 0) {
1973 if (parent_tree) {
1974 item = proto_tree_add_item(parent_tree, hf_id, tvb, hoffset, lenx + offset - hoffset, ENC_BIG_ENDIAN);
1975 tree = proto_item_add_subtree(item, ett_id);
1978 offset = hoffset;
1980 if (!implicit_tag) {
1981 /* first we must read the sequence header */
1982 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
1983 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
1984 if (ind) {
1985 /* Fixed the length is correctly returned from dissect ber_length
1986 end_offset = tvb_length(tvb);*/
1987 end_offset = offset + lenx -2;
1988 } else {
1989 end_offset = offset + lenx;
1992 /* sanity check: we only handle Constructed Universal Sequences */
1993 if ((classx != BER_CLASS_APP) && (classx != BER_CLASS_PRI)) {
1994 if (!pcx
1995 || (!implicit_tag && ((classx != BER_CLASS_UNI) || (tagx != BER_UNI_TAG_SEQUENCE)))) {
1996 tvb_ensure_bytes_exist(tvb, hoffset, 2);
1997 cause = proto_tree_add_string_format_value(
1998 tree, hf_ber_error, tvb, offset, lenx, "sequence_expected",
1999 "Sequence expected but class:%s(%d) %s tag:%d was unexpected",
2000 val_to_str_const(classx, ber_class_codes, "Unknown"),
2001 classx,
2002 pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
2003 tagx);
2004 expert_add_info(actx->pinfo, cause, &ei_ber_expected_sequence);
2005 if (decode_unexpected) {
2006 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2007 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2009 return end_offset;
2013 if(offset == end_offset){
2014 proto_item_append_text(item, " [0 length]");
2016 /* loop over all entries until we reach the end of the sequence */
2017 while (offset < end_offset) {
2018 gint8 ber_class;
2019 gboolean pc;
2020 gint32 tag;
2021 guint32 len;
2022 int eoffset, count;
2024 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2025 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2026 if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
2027 /* If the first bytes is 00 00 of a indefenert length field it's a zero length field*/
2028 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
2029 dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
2030 proto_item_append_text(item, " 0 items");
2031 return end_offset;
2033 if (show_internal_ber_fields) {
2034 proto_tree_add_text(tree, tvb, s_offset, offset+2, "ERROR WRONG SEQ EOC");
2036 return end_offset;
2039 /* } */
2040 hoffset = offset;
2041 /* read header and len for next field */
2042 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
2043 offset = get_ber_length(tvb, offset, &len, &ind_field);
2044 eoffset = offset + len;
2045 /* Make sure we move forward */
2046 if (eoffset <= hoffset)
2047 THROW(ReportedBoundsError);
2049 /*if (ind_field && (len == 2)) {
2050 / disgusting indefinite length zero length field, what are these people doing /
2051 offset = eoffset;
2052 continue;
2056 ber_sequence_try_again:
2057 /* have we run out of known entries in the sequence ?*/
2058 if (!seq->func) {
2059 /* it was not, move to the next one and try again */
2060 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2061 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
2062 cause = proto_tree_add_string_format_value(
2063 tree, hf_ber_error, tvb, offset, len, "unknown_field",
2064 "This field lies beyond the end of the known sequence definition.");
2065 expert_add_info(actx->pinfo, cause, &ei_ber_unknown_field_sequence);
2066 if (decode_unexpected) {
2067 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2068 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2070 offset = eoffset;
2071 continue;
2074 /* Verify that this one is the one we want.
2075 * Skip check completely if ber_class == ANY
2076 * of if NOCHKTAG is set
2078 /* XXX Bug in asn2eth,
2079 * for scope [7] Scope OPTIONAL,
2080 * it generates
2081 * { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_scope },
2082 * and there should not be a NOTCHKTAG here
2084 if ( ((seq->ber_class == BER_CLASS_CON) || (seq->ber_class == BER_CLASS_APP) || (seq->ber_class == BER_CLASS_PRI))
2085 && (!(seq->flags & BER_FLAGS_NOOWNTAG)) ) {
2086 if ( (seq->ber_class != BER_CLASS_ANY)
2087 && (seq->tag != -1)
2088 && ( (seq->ber_class != ber_class)
2089 || (seq->tag != tag) ) ) {
2090 /* it was not, move to the next one and try again */
2091 if (seq->flags & BER_FLAGS_OPTIONAL) {
2092 /* well this one was optional so just skip to the next one and try again. */
2093 seq++;
2094 goto ber_sequence_try_again;
2096 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2097 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
2098 if (seq->ber_class == BER_CLASS_UNI) {
2099 cause = proto_tree_add_string_format_value(
2100 tree, hf_ber_error, tvb, offset, len, "wrong_field",
2101 "Wrong field in SEQUENCE expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
2102 val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2103 seq->ber_class,
2104 seq->tag,
2105 val_to_str_ext_const(seq->tag, &ber_uni_tag_codes_ext, "Unknown"),
2106 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2107 ber_class,
2108 tag);
2109 expert_add_info(actx->pinfo, cause, &ei_ber_sequence_field_wrong);
2110 } else {
2111 cause = proto_tree_add_string_format_value(
2112 tree, hf_ber_error, tvb, offset, len, "wrong_field",
2113 "Wrong field in SEQUENCE expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2114 val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2115 seq->ber_class,
2116 seq->tag,
2117 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2118 ber_class,
2119 tag);
2120 expert_add_info(actx->pinfo, cause, &ei_ber_sequence_field_wrong);
2122 if (decode_unexpected) {
2123 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2124 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2126 seq++;
2127 offset = eoffset;
2128 continue;
2130 } else if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
2131 if ( (seq->ber_class != BER_CLASS_ANY)
2132 && (seq->tag != -1)
2133 && ( (seq->ber_class != ber_class)
2134 || (seq->tag != tag) ) ) {
2135 /* it was not, move to the next one and try again */
2136 if (seq->flags & BER_FLAGS_OPTIONAL) {
2137 /* well this one was optional so just skip to the next one and try again. */
2138 seq++;
2139 goto ber_sequence_try_again;
2142 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2143 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
2144 if ( seq->ber_class == BER_CLASS_UNI) {
2145 cause = proto_tree_add_string_format_value(
2146 tree, hf_ber_error, tvb, offset, len, "wrong_field",
2147 "Wrong field in sequence expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d",
2148 val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2149 seq->ber_class,
2150 seq->tag,
2151 val_to_str_ext_const(seq->tag, &ber_uni_tag_codes_ext, "Unknown"),
2152 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2153 ber_class, tag);
2154 expert_add_info(actx->pinfo, cause, &ei_ber_sequence_field_wrong);
2155 } else {
2156 cause = proto_tree_add_string_format_value(
2157 tree, hf_ber_error, tvb, offset, len, "wrong_field",
2158 "Wrong field in sequence expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2159 val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2160 seq->ber_class,
2161 seq->tag,
2162 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2163 ber_class,
2164 tag);
2165 expert_add_info(actx->pinfo, cause, &ei_ber_sequence_field_wrong);
2167 if (decode_unexpected) {
2168 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2169 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2171 seq++;
2172 offset = eoffset;
2173 continue;
2177 if (!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
2178 /* dissect header and len for field */
2179 if (ind_field && (len == 2)) {
2180 /* This is a Zero length field */
2181 next_tvb = tvb_new_subset(tvb, offset, len, len);
2182 hoffset = eoffset;
2183 } else {
2184 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2185 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
2186 length_remaining = tvb_length_remaining(tvb, hoffset);
2187 if (length_remaining > (eoffset - hoffset - (2 * ind_field)))
2188 length_remaining = eoffset - hoffset - (2 * ind_field);
2189 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, length_remaining);
2191 } else {
2192 length_remaining = tvb_length_remaining(tvb, hoffset);
2193 if (length_remaining > (eoffset - hoffset))
2194 length_remaining = eoffset - hoffset;
2195 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, length_remaining);
2198 #if 0
2199 /* call the dissector for this field */
2200 if ((eoffset-hoffset) > length_remaining) {
2201 /* If the field is indefinite (i.e. we don't know the
2202 * length) of if the tvb is short, then just
2203 * give it all of the tvb and hope for the best.
2205 next_tvb = tvb_new_subset_remaining(tvb, hoffset);
2206 } else {
2209 #endif
2211 #ifdef DEBUG_BER
2213 const char *name;
2214 header_field_info *hfinfo;
2215 if (hf_id >= 0) {
2216 hfinfo = proto_registrar_get_nth(hf_id);
2217 name = hfinfo->name;
2218 } else {
2219 name = "unnamed";
2221 if (tvb_length_remaining(next_tvb, 0) > 3) {
2222 printf("SEQUENCE dissect_ber_sequence(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x\n", name, offset, tvb_length_remaining(next_tvb, 0), tvb_get_guint8(next_tvb, 0), tvb_get_guint8(next_tvb, 1), tvb_get_guint8(next_tvb, 2));
2223 } else {
2224 printf("SEQUENCE dissect_ber_sequence(%s) calling subdissector\n", name);
2227 #endif
2228 if (next_tvb == NULL) {
2229 /* Assume that we have a malformed packet. */
2230 THROW(ReportedBoundsError);
2232 imp_tag = FALSE;
2233 if (seq->flags & BER_FLAGS_IMPLTAG) {
2234 imp_tag = TRUE;
2237 count = seq->func(imp_tag, next_tvb, 0, actx, tree, *seq->p_id);
2239 #ifdef DEBUG_BER
2241 const char *name;
2242 header_field_info *hfinfo;
2243 if (hf_id >= 0) {
2244 hfinfo = proto_registrar_get_nth(hf_id);
2245 name = hfinfo->name;
2246 } else {
2247 name = "unnamed";
2249 printf("SEQUENCE dissect_ber_sequence(%s) subdissector ate %d bytes\n", name, count);
2251 #endif
2252 /* if it was optional and no bytes were eaten and it was */
2253 /* supposed to (len <> 0), just try again. */
2254 if ((len != 0) && (count == 0) && (seq->flags & BER_FLAGS_OPTIONAL)) {
2255 seq++;
2256 goto ber_sequence_try_again;
2257 /* move the offset to the beginning of the next sequenced item */
2259 offset = eoffset;
2260 if (!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
2261 /* if we stripped the tag and length we should also strip the EOC is ind_len
2262 * Unless it's a zero length field (len = 2)
2264 if ((ind_field == 1) && (len > 2))
2266 /* skip over EOC */
2267 if (show_internal_ber_fields) {
2268 proto_tree_add_text(tree, tvb, offset, count, "SEQ FIELD EOC");
2272 seq++;
2275 /* if we didnt end up at exactly offset, then we ate too many bytes */
2276 if (offset != end_offset) {
2277 tvb_ensure_bytes_exist(tvb, offset-2, 2);
2278 cause = proto_tree_add_string_format_value(
2279 tree, hf_ber_error, tvb, offset-2, 2, "illegal_length",
2280 "Sequence ate %d too many bytes",
2281 offset - end_offset);
2282 expert_add_info_format(actx->pinfo, cause, &ei_ber_error_length,
2283 "BER Error: too many bytes in Sequence");
2285 if (ind) {
2286 /* need to eat this EOC
2287 end_offset = tvb_length(tvb);*/
2288 end_offset += 2;
2289 if (show_internal_ber_fields) {
2290 proto_tree_add_text(tree, tvb, end_offset-2, 2 , "SEQ EOC");
2293 return end_offset;
2296 dissect_ber_old_sequence(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_old_sequence_t *seq, gint hf_id, gint ett_id) {
2297 gint8 classx;
2298 gboolean pcx, ind = 0, ind_field;
2299 gint32 tagx;
2300 guint32 lenx;
2301 proto_tree *tree = parent_tree;
2302 proto_item *item = NULL;
2303 proto_item *cause;
2304 int end_offset = 0;
2305 int hoffset;
2306 gint length_remaining;
2307 tvbuff_t *next_tvb;
2309 #ifdef DEBUG_BER
2311 const char *name;
2312 header_field_info *hfinfo;
2313 if (hf_id >= 0) {
2314 hfinfo = proto_registrar_get_nth(hf_id);
2315 name = hfinfo->name;
2316 } else {
2317 name = "unnamed";
2319 if (tvb_length_remaining(tvb, offset) > 3) {
2320 printf("SEQUENCE dissect_ber_old_sequence(%s) entered offset:%d len:%d %02x:%02x:%02x\n", name, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
2321 } else {
2322 printf("SEQUENCE dissect_ber_old_sequence(%s) entered\n", name);
2325 #endif
2326 hoffset = offset;
2327 if (!implicit_tag) {
2328 offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
2329 offset = get_ber_length(tvb, offset, &lenx, NULL);
2330 } else {
2331 /* was implicit tag so just use the length of the tvb */
2332 lenx = tvb_length_remaining(tvb, offset);
2333 end_offset = offset+lenx;
2335 /* create subtree */
2336 if (hf_id >= 0) {
2337 if (parent_tree) {
2338 item = proto_tree_add_item(parent_tree, hf_id, tvb, hoffset, lenx + offset - hoffset, ENC_BIG_ENDIAN);
2339 tree = proto_item_add_subtree(item, ett_id);
2342 offset = hoffset;
2344 if (!implicit_tag) {
2345 /* first we must read the sequence header */
2346 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
2347 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
2348 if (ind) {
2349 /* Fixed the length is correctly returned from dissect ber_length
2350 end_offset = tvb_length(tvb);*/
2351 end_offset = offset + lenx -2;
2352 } else {
2353 end_offset = offset + lenx;
2356 /* sanity check: we only handle Constructed Universal Sequences */
2357 if ((classx != BER_CLASS_APP) && (classx != BER_CLASS_PRI)) {
2358 if (!pcx
2359 || (!implicit_tag && ((classx != BER_CLASS_UNI) || (tagx != BER_UNI_TAG_SEQUENCE)))) {
2360 tvb_ensure_bytes_exist(tvb, hoffset, 2);
2361 cause = proto_tree_add_string_format_value(
2362 tree, hf_ber_error, tvb, offset, lenx, "sequence_expected",
2363 "Sequence expected but class:%s(%d) %s tag:%d was unexpected",
2364 val_to_str_const(classx, ber_class_codes, "Unknown"),
2365 classx,
2366 pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
2367 tagx);
2368 expert_add_info(
2369 actx->pinfo, cause, &ei_ber_expected_sequence);
2370 if (decode_unexpected) {
2371 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2372 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2374 return end_offset;
2378 /* loop over all entries until we reach the end of the sequence */
2379 while (offset < end_offset) {
2380 gint8 ber_class;
2381 gboolean pc;
2382 gint32 tag;
2383 guint32 len;
2384 int eoffset, count;
2386 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2387 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2388 if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
2389 /* If the first bytes are 00 00 in an indefinite length field, it's a zero length field */
2390 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
2391 dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
2392 proto_item_append_text(item, " 0 items");
2393 return end_offset;
2395 if (show_internal_ber_fields) {
2396 proto_tree_add_text(tree, tvb, s_offset, offset+2, "ERROR WRONG SEQ EOC");
2398 return end_offset;
2401 /* } */
2402 hoffset = offset;
2403 /* read header and len for next field */
2404 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
2405 offset = get_ber_length(tvb, offset, &len, &ind_field);
2406 eoffset = offset + len;
2407 /* Make sure we move forward */
2408 if (eoffset <= hoffset)
2409 THROW(ReportedBoundsError);
2411 /*if (ind_field && (len == 2)) {
2412 / disgusting indefinite length zero length field, what are these people doing /
2413 offset = eoffset;
2414 continue;
2418 ber_old_sequence_try_again:
2419 /* have we run out of known entries in the sequence ?*/
2420 if (!seq->func) {
2421 /* it was not, move to the next one and try again */
2422 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2423 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
2424 cause = proto_tree_add_string_format_value(
2425 tree, hf_ber_error, tvb, offset, len, "illegal_length",
2426 "This field lies beyond the end of the known sequence definition.");
2427 expert_add_info(actx->pinfo, cause, &ei_ber_unknown_field_sequence);
2428 if (decode_unexpected) {
2429 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2430 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2432 offset = eoffset;
2433 continue;
2436 /* Verify that this one is the one we want.
2437 * Skip check completely if ber_class == ANY
2438 * of if NOCHKTAG is set
2440 /* XXX Bug in asn2eth,
2441 * for scope [7] Scope OPTIONAL,
2442 * it generates
2443 * { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_scope },
2444 * and there should not be a NOTCHKTAG here
2446 if ( ((seq->ber_class == BER_CLASS_CON) || (seq->ber_class == BER_CLASS_APP) || (seq->ber_class == BER_CLASS_PRI))
2447 && (!(seq->flags & BER_FLAGS_NOOWNTAG)) ) {
2448 if ( (seq->ber_class != BER_CLASS_ANY)
2449 && (seq->tag != -1)
2450 && ( (seq->ber_class != ber_class)
2451 || (seq->tag != tag) ) ) {
2452 /* it was not, move to the next one and try again */
2453 if (seq->flags & BER_FLAGS_OPTIONAL) {
2454 /* well this one was optional so just skip to the next one and try again. */
2455 seq++;
2456 goto ber_old_sequence_try_again;
2458 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2459 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
2460 if ( seq->ber_class == BER_CLASS_UNI) {
2461 cause = proto_tree_add_string_format_value(
2462 tree, hf_ber_error, tvb, offset, len, "wrong_field",
2463 "Wrong field in SEQUENCE expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
2464 val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2465 seq->ber_class,
2466 seq->tag,
2467 val_to_str_ext_const(seq->tag, &ber_uni_tag_codes_ext, "Unknown"),
2468 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2469 ber_class,
2470 tag);
2471 expert_add_info(actx->pinfo, cause, &ei_ber_sequence_field_wrong);
2472 } else {
2473 cause = proto_tree_add_string_format_value(
2474 tree, hf_ber_error, tvb, offset, len, "wrong_field"
2475 "Wrong field in SEQUENCE expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2476 val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2477 seq->ber_class,
2478 seq->tag,
2479 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2480 ber_class,
2481 tag);
2482 expert_add_info(actx->pinfo, cause, &ei_ber_sequence_field_wrong);
2484 if (decode_unexpected) {
2485 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2486 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2488 seq++;
2489 offset = eoffset;
2490 continue;
2492 } else if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
2493 if ( (seq->ber_class != BER_CLASS_ANY)
2494 && (seq->tag != -1)
2495 && ( (seq->ber_class != ber_class)
2496 || (seq->tag != tag) ) ) {
2497 /* it was not, move to the next one and try again */
2498 if (seq->flags & BER_FLAGS_OPTIONAL) {
2499 /* well this one was optional so just skip to the next one and try again. */
2500 seq++;
2501 goto ber_old_sequence_try_again;
2504 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2505 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
2506 if ( seq->ber_class == BER_CLASS_UNI) {
2507 cause = proto_tree_add_string_format_value(
2508 tree, hf_ber_error, tvb, offset, len, "wrong_field",
2509 "Wrong field in sequence expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d",
2510 val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2511 seq->ber_class,
2512 seq->tag,
2513 val_to_str_ext_const(seq->tag, &ber_uni_tag_codes_ext, "Unknown"),
2514 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2515 ber_class,
2516 tag);
2517 expert_add_info(actx->pinfo, cause, &ei_ber_sequence_field_wrong);
2518 } else {
2519 cause = proto_tree_add_string_format_value(
2520 tree, hf_ber_error, tvb, offset, len, "wrong_field",
2521 "Wrong field in sequence expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
2522 val_to_str_const(seq->ber_class, ber_class_codes, "Unknown"),
2523 seq->ber_class,
2524 seq->tag,
2525 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2526 ber_class,
2527 tag);
2528 expert_add_info(actx->pinfo, cause, &ei_ber_sequence_field_wrong);
2530 if (decode_unexpected) {
2531 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2532 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2534 seq++;
2535 offset = eoffset;
2536 continue;
2540 if (!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
2541 /* dissect header and len for field */
2542 if (ind_field && (len == 2)) {
2543 /* This is a Zero length field */
2544 next_tvb = tvb_new_subset(tvb, offset, len, len);
2545 hoffset = eoffset;
2546 } else {
2547 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2548 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
2549 length_remaining = tvb_length_remaining(tvb, hoffset);
2550 if (length_remaining > (eoffset - hoffset - (2 * ind_field)))
2551 length_remaining = eoffset - hoffset - (2 * ind_field);
2552 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset - hoffset - (2 * ind_field));
2555 else {
2556 length_remaining = tvb_length_remaining(tvb, hoffset);
2557 if (length_remaining > (eoffset - hoffset))
2558 length_remaining = eoffset - hoffset;
2559 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset - hoffset);
2562 #if 0
2563 /* call the dissector for this field */
2564 if ((eoffset-hoffset) > length_remaining) {
2565 /* If the field is indefinite (i.e. we don't know the
2566 * length) of if the tvb is short, then just
2567 * give it all of the tvb and hope for the best.
2569 next_tvb = tvb_new_subset_remaining(tvb, hoffset);
2570 } else {
2573 #endif
2575 #ifdef DEBUG_BER
2577 const char *name;
2578 header_field_info *hfinfo;
2579 if (hf_id >= 0) {
2580 hfinfo = proto_registrar_get_nth(hf_id);
2581 name = hfinfo->name;
2582 } else {
2583 name = "unnamed";
2585 if (tvb_length_remaining(next_tvb, 0) > 3) {
2586 printf("SEQUENCE dissect_ber_old_sequence(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x\n", name, offset, tvb_length_remaining(next_tvb, 0), tvb_get_guint8(next_tvb, 0), tvb_get_guint8(next_tvb, 1), tvb_get_guint8(next_tvb, 2));
2587 } else {
2588 printf("SEQUENCE dissect_ber_old_sequence(%s) calling subdissector\n", name);
2591 #endif
2592 if (next_tvb == NULL) {
2593 /* Assume that we have a malformed packet. */
2594 THROW(ReportedBoundsError);
2596 count = seq->func(tree, next_tvb, 0, actx);
2598 #ifdef DEBUG_BER
2600 const char *name;
2601 header_field_info *hfinfo;
2602 if (hf_id >= 0) {
2603 hfinfo = proto_registrar_get_nth(hf_id);
2604 name = hfinfo->name;
2605 } else {
2606 name = "unnamed";
2608 printf("SEQUENCE dissect_ber_old_sequence(%s) subdissector ate %d bytes\n", name, count);
2610 #endif
2611 /* if it was optional and no bytes were eaten and it was */
2612 /* supposed to (len<>0), just try again. */
2613 if ((len != 0) && (count == 0) && (seq->flags & BER_FLAGS_OPTIONAL)) {
2614 seq++;
2615 goto ber_old_sequence_try_again;
2616 /* move the offset to the beginning of the next sequenced item */
2618 offset = eoffset;
2619 seq++;
2620 if (!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
2621 /* if we stripped the tag and length we should also strip the EOC is ind_len
2622 * Unless it's a zero length field (len = 2)
2624 if ((ind_field == 1) && (len > 2))
2626 /* skip over EOC */
2627 if (show_internal_ber_fields) {
2628 proto_tree_add_text(tree, tvb, offset, count, "SEQ FIELD EOC");
2634 /* if we didnt end up at exactly offset, then we ate too many bytes */
2635 if (offset != end_offset) {
2636 tvb_ensure_bytes_exist(tvb, offset-2, 2);
2637 cause = proto_tree_add_string_format_value(
2638 tree, hf_ber_error, tvb, offset-2, 2, "illegal_length",
2639 "Sequence ate %d too many bytes",
2640 offset - end_offset);
2641 expert_add_info_format(actx->pinfo, cause, &ei_ber_error_length,
2642 "BER Error: too many bytes in Sequence");
2644 if (ind) {
2645 /* need to eat this EOC
2646 end_offset = tvb_length(tvb);*/
2647 end_offset += 2;
2648 if (show_internal_ber_fields) {
2649 proto_tree_add_text(tree, tvb, end_offset-2, 2 , "SEQ EOC");
2652 return end_offset;
2655 /* This function dissects a BER set
2658 dissect_ber_set(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *set, gint hf_id, gint ett_id) {
2659 gint8 classx;
2660 gboolean pcx, ind = 0, ind_field, imp_tag = FALSE;
2661 gint32 tagx;
2662 guint32 lenx;
2663 proto_tree *tree = parent_tree;
2664 proto_item *item = NULL;
2665 proto_item *cause;
2666 int end_offset, s_offset;
2667 int hoffset;
2668 gint length_remaining;
2669 tvbuff_t *next_tvb;
2670 guint32 mandatory_fields = 0;
2671 guint8 set_idx;
2672 gboolean first_pass;
2673 const ber_sequence_t *cset = NULL;
2675 #define MAX_SET_ELEMENTS 32
2677 s_offset = offset;
2679 #ifdef DEBUG_BER
2681 const char *name;
2682 header_field_info *hfinfo;
2683 if (hf_id >= 0) {
2684 hfinfo = proto_registrar_get_nth(hf_id);
2685 name = hfinfo->name;
2686 } else {
2687 name = "unnamed";
2689 if (tvb_length_remaining(tvb, offset) > 3) {
2690 printf("SET dissect_ber_set(%s) entered offset:%d len:%d %02x:%02x:%02x\n", name, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
2691 } else {
2692 printf("SET dissect_ber_set(%s) entered\n", name);
2695 #endif
2697 if (!implicit_tag) {
2698 hoffset = offset;
2699 /* first we must read the sequence header */
2700 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
2701 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
2702 if (ind) {
2703 /* Fixed the length is correctly returned from dissect ber_length
2704 end_offset = tvb_length(tvb);*/
2705 end_offset = offset + lenx -2;
2706 } else {
2707 end_offset = offset + lenx;
2710 /* sanity check: we only handle Constructed Universal Sets */
2711 if ((classx != BER_CLASS_APP) && (classx != BER_CLASS_PRI)) {
2712 if (!pcx
2713 || (!implicit_tag && ((classx != BER_CLASS_UNI)
2714 || (tagx != BER_UNI_TAG_SET)))) {
2715 tvb_ensure_bytes_exist(tvb, hoffset, 2);
2716 cause = proto_tree_add_string_format_value(
2717 tree, hf_ber_error, tvb, offset, lenx, "set_expected",
2718 "SET expected but class:%s(%d) %s tag:%d was found",
2719 val_to_str_const(classx, ber_class_codes, "Unknown"),
2720 classx,
2721 pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
2722 tagx);
2723 expert_add_info(actx->pinfo, cause, &ei_ber_expected_set);
2724 if (decode_unexpected) {
2725 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2726 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2728 return end_offset;
2731 } else {
2732 /* was implicit tag so just use the length of the tvb */
2733 lenx = tvb_length_remaining(tvb, offset);
2734 end_offset = offset+lenx;
2737 /* create subtree */
2738 if (hf_id >= 0) {
2739 if (parent_tree) {
2740 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, lenx, ENC_BIG_ENDIAN);
2741 tree = proto_item_add_subtree(item, ett_id);
2745 /* record the mandatory elements of the set so we can check we found everything at the end
2746 we can only record 32 elements for now ... */
2747 for (set_idx = 0; (cset = &set[set_idx])->func && (set_idx < MAX_SET_ELEMENTS); set_idx++) {
2749 if (!(cset->flags & BER_FLAGS_OPTIONAL))
2750 mandatory_fields |= 1 << set_idx;
2754 /* loop over all entries until we reach the end of the set */
2755 while (offset < end_offset) {
2756 gint8 ber_class;
2757 gboolean pc;
2758 gint32 tag;
2759 guint32 len;
2760 int eoffset, count;
2762 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2763 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2765 if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
2766 if (show_internal_ber_fields) {
2767 proto_tree_add_text(tree, tvb, s_offset, offset+2, "SEQ EOC");
2769 return end_offset;
2771 /* } */
2772 hoffset = offset;
2773 /* read header and len for next field */
2774 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
2775 offset = get_ber_length(tvb, offset, &len, &ind_field);
2776 eoffset = offset + len;
2778 /* Look through the Set to see if this class/id exists and
2779 * hasn't been seen before
2780 * Skip check completely if ber_class == ANY
2781 * of if NOCHKTAG is set
2785 for (first_pass = TRUE, cset = set, set_idx = 0; cset->func || first_pass; cset++, set_idx++) {
2787 /* we reset for a second pass when we will look for choices */
2788 if (!cset->func) {
2789 first_pass = FALSE;
2791 cset = set; /* reset to the beginning */
2792 set_idx = 0;
2795 if ((first_pass && ((cset->ber_class == ber_class) && (cset->tag == tag))) ||
2796 (!first_pass && ((cset->ber_class == BER_CLASS_ANY) && (cset->tag == -1))) ) /* choices */
2798 if (!(cset->flags & BER_FLAGS_NOOWNTAG) ) {
2799 /* dissect header and len for field */
2800 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2801 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
2802 length_remaining = tvb_length_remaining(tvb, hoffset);
2803 if (length_remaining > (eoffset - hoffset - (2 * ind_field)))
2804 length_remaining = eoffset - hoffset - (2 * ind_field);
2805 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset - hoffset - (2 * ind_field));
2806 } else {
2807 length_remaining = tvb_length_remaining(tvb, hoffset);
2808 if (length_remaining > (eoffset - hoffset))
2809 length_remaining = eoffset - hoffset;
2810 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset - hoffset);
2814 #if 0
2815 /* call the dissector for this field */
2816 if ((eoffset-hoffset)>length_remaining) {
2817 /* If the field is indefinite (i.e. we don't know the
2818 * length) of if the tvb is short, then just
2819 * give it all of the tvb and hope for the best.
2821 next_tvb = tvb_new_subset_remaining(tvb, hoffset);
2822 } else {
2825 #endif
2827 #ifdef DEBUG_BER
2829 const char *name;
2830 header_field_info *hfinfo;
2831 if (hf_id >= 0) {
2832 hfinfo = proto_registrar_get_nth(hf_id);
2833 name = hfinfo->name;
2834 } else {
2835 name = "unnamed";
2837 if (tvb_length_remaining(next_tvb, 0) > 3) {
2838 printf("SET dissect_ber_set(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x\n", name, offset, tvb_length_remaining(next_tvb, 0), tvb_get_guint8(next_tvb, 0), tvb_get_guint8(next_tvb, 1), tvb_get_guint8(next_tvb, 2));
2839 } else {
2840 printf("SET dissect_ber_set(%s) calling subdissector\n", name);
2843 #endif
2844 if (next_tvb == NULL) {
2845 /* Assume that we have a malformed packet. */
2846 THROW(ReportedBoundsError);
2848 imp_tag = FALSE;
2849 if ((cset->flags & BER_FLAGS_IMPLTAG))
2850 imp_tag = TRUE;
2851 count = cset->func(imp_tag, next_tvb, 0, actx, tree, *cset->p_id);
2853 /* if we consumed some bytes,
2854 or we knew the length was zero (during the first pass only) */
2855 if (count || (first_pass && ((len == 0) || ((ind_field == 1) && (len == 2))))) {
2856 /* we found it! */
2857 if (set_idx < MAX_SET_ELEMENTS)
2858 mandatory_fields &= ~(1 << set_idx);
2860 offset = eoffset;
2862 if (!(cset->flags & BER_FLAGS_NOOWNTAG) ) {
2863 /* if we stripped the tag and length we should also strip the EOC is ind_len */
2864 if (ind_field == 1) {
2865 /* skip over EOC */
2866 if (show_internal_ber_fields) {
2867 proto_tree_add_text(tree, tvb, offset, count, "SET FIELD EOC");
2871 break;
2876 if (!cset->func) {
2877 /* we didn't find a match */
2878 cause = proto_tree_add_string_format_value(
2879 tree, hf_ber_error, tvb, offset, len, "unknown_field",
2880 "Unknown field in SET class:%s(%d) tag:%d",
2881 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
2882 ber_class,
2883 tag);
2884 expert_add_info(actx->pinfo, cause, &ei_ber_unknown_field_set);
2885 if (decode_unexpected) {
2886 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2887 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2889 offset = eoffset;
2893 if (mandatory_fields) {
2895 /* OK - we didn't find some of the elements we expected */
2897 for (set_idx = 0; (cset = &set[set_idx])->func && (set_idx < MAX_SET_ELEMENTS); set_idx++) {
2898 if (mandatory_fields & (1 << set_idx)) {
2899 /* here is something we should have seen - but didn't! */
2900 cause = proto_tree_add_string_format_value(
2901 tree, hf_ber_error, tvb, offset, lenx, "missing_field",
2902 "Missing field in SET class:%s(%d) tag:%d expected",
2903 val_to_str_const(cset->ber_class, ber_class_codes, "Unknown"),
2904 cset->ber_class,
2905 cset->tag);
2906 expert_add_info(actx->pinfo, cause, &ei_ber_missing_field_set);
2913 /* if we didnt end up at exactly offset, then we ate too many bytes */
2914 if (offset != end_offset) {
2915 tvb_ensure_bytes_exist(tvb, offset-2, 2);
2916 cause = proto_tree_add_string_format_value(
2917 tree, hf_ber_error, tvb, offset-2, 2, "illegal_length",
2918 "SET ate %d too many bytes",
2919 offset - end_offset);
2920 expert_add_info_format(actx->pinfo, cause, &ei_ber_error_length,
2921 "BER Error: too many bytes in SET");
2924 if (ind) {
2925 /* need to eat this EOC
2926 end_offset = tvb_length(tvb);*/
2927 end_offset += 2;
2928 if (show_internal_ber_fields) {
2929 proto_tree_add_text(tree, tvb, end_offset-2, 2 , "SET EOC");
2933 return end_offset;
2938 dissect_ber_old_set(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_old_sequence_t *set, gint hf_id, gint ett_id) {
2939 gint8 classx;
2940 gboolean pcx, ind = 0, ind_field;
2941 gint32 tagx;
2942 guint32 lenx;
2943 proto_tree *tree = parent_tree;
2944 proto_item *item = NULL;
2945 proto_item *cause;
2946 int end_offset, s_offset;
2947 int hoffset;
2948 gint length_remaining;
2949 tvbuff_t *next_tvb;
2950 guint32 mandatory_fields = 0;
2951 guint8 set_idx;
2952 gboolean first_pass;
2953 const ber_old_sequence_t *cset = NULL;
2955 s_offset = offset;
2957 #define MAX_SET_ELEMENTS 32
2959 #ifdef DEBUG_BER
2961 const char *name;
2962 header_field_info *hfinfo;
2963 if (hf_id >= 0) {
2964 hfinfo = proto_registrar_get_nth(hf_id);
2965 name = hfinfo->name;
2966 } else {
2967 name = "unnamed";
2969 if (tvb_length_remaining(tvb, offset) > 3) {
2970 printf("SET dissect_old_ber_set(%s) entered offset:%d len:%d %02x:%02x:%02x\n", name, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
2971 } else {
2972 printf("SET dissect_old_ber_set(%s) entered\n", name);
2975 #endif
2977 if (!implicit_tag) {
2978 hoffset = offset;
2979 /* first we must read the sequence header */
2980 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
2981 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
2982 if (ind) {
2983 /* Fixed the length is correctly returned from dissect ber_length
2984 end_offset = tvb_length(tvb);*/
2985 end_offset = offset + lenx -2;
2986 } else {
2987 end_offset = offset + lenx;
2990 /* sanity check: we only handle Constructed Universal Sets */
2991 if ((classx != BER_CLASS_APP) && (classx != BER_CLASS_PRI)) {
2992 if (!pcx
2993 || (!implicit_tag && ((classx != BER_CLASS_UNI)
2994 || (tagx != BER_UNI_TAG_SET)))) {
2995 tvb_ensure_bytes_exist(tvb, hoffset, 2);
2996 cause = proto_tree_add_string_format_value(
2997 tree, hf_ber_error, tvb, offset, lenx, "set_expected",
2998 "SET expected but class:%s(%d) %s tag:%d was found",
2999 val_to_str_const(classx, ber_class_codes, "Unknown"),
3000 classx,
3001 pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
3002 tagx);
3003 expert_add_info(actx->pinfo, cause, &ei_ber_expected_set);
3004 if (decode_unexpected) {
3005 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3006 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3008 return end_offset;
3011 } else {
3012 /* was implicit tag so just use the length of the tvb */
3013 lenx = tvb_length_remaining(tvb, offset);
3014 end_offset = offset+lenx;
3017 /* create subtree */
3018 if (hf_id >= 0) {
3019 if (parent_tree) {
3020 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, lenx, ENC_BIG_ENDIAN);
3021 tree = proto_item_add_subtree(item, ett_id);
3025 /* record the mandatory elements of the set so we can check we found everything at the end
3026 we can only record 32 elements for now ... */
3027 for (set_idx = 0; (cset = &set[set_idx])->func && (set_idx < MAX_SET_ELEMENTS); set_idx++) {
3029 if (!(cset->flags & BER_FLAGS_OPTIONAL))
3030 mandatory_fields |= 1 << set_idx;
3034 /* loop over all entries until we reach the end of the set */
3035 while (offset < end_offset) {
3036 gint8 ber_class;
3037 gboolean pc;
3038 gint32 tag;
3039 guint32 len;
3040 int eoffset, count;
3042 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
3043 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
3045 if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
3046 if (show_internal_ber_fields) {
3047 proto_tree_add_text(tree, tvb, s_offset, offset+2, "SEQ EOC");
3049 return end_offset;
3051 /* } */
3052 hoffset = offset;
3053 /* read header and len for next field */
3054 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
3055 offset = get_ber_length(tvb, offset, &len, &ind_field);
3056 eoffset = offset + len;
3058 /* Look through the Set to see if this class/id exists and
3059 * hasn't been seen before
3060 * Skip check completely if class == ANY
3061 * of if NOCHKTAG is set
3065 for (first_pass=TRUE, cset=set, set_idx=0; cset->func || first_pass; cset++, set_idx++) {
3067 /* we reset for a second pass when we will look for choices */
3068 if (!cset->func) {
3069 first_pass = FALSE;
3071 cset = set; /* reset to the beginning */
3072 set_idx = 0;
3075 if ((first_pass && ((cset->ber_class == ber_class) && (cset->tag == tag))) ||
3076 (!first_pass && ((cset->ber_class == BER_CLASS_ANY) && (cset->tag == -1))) ) /* choices */
3078 if (!(cset->flags & BER_FLAGS_NOOWNTAG) ) {
3079 /* dissect header and len for field */
3080 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
3081 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3082 length_remaining = tvb_length_remaining(tvb, hoffset);
3083 if (length_remaining > (eoffset - hoffset - (2 * ind_field)))
3084 length_remaining = eoffset - hoffset - (2 * ind_field);
3085 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset - hoffset - (2 * ind_field));
3086 } else {
3087 length_remaining = tvb_length_remaining(tvb, hoffset);
3088 if (length_remaining > (eoffset - hoffset))
3089 length_remaining = eoffset - hoffset;
3090 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset - hoffset);
3093 #if 0
3094 /* call the dissector for this field */
3095 if ((eoffset-hoffset)>length_remaining) {
3096 /* If the field is indefinite (i.e. we don't know the
3097 * length) of if the tvb is short, then just
3098 * give it all of the tvb and hope for the best.
3100 next_tvb = tvb_new_subset_remaining(tvb, hoffset);
3101 } else {
3104 #endif
3106 #ifdef DEBUG_BER
3108 const char *name;
3109 header_field_info *hfinfo;
3110 if (hf_id >= 0) {
3111 hfinfo = proto_registrar_get_nth(hf_id);
3112 name = hfinfo->name;
3113 } else {
3114 name = "unnamed";
3116 if (tvb_length_remaining(next_tvb, 0) > 3) {
3117 printf("SET dissect_old_ber_set(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x\n", name, offset, tvb_length_remaining(next_tvb, 0), tvb_get_guint8(next_tvb, 0), tvb_get_guint8(next_tvb, 1), tvb_get_guint8(next_tvb, 2));
3118 } else {
3119 printf("SET dissect_old_ber_set(%s) calling subdissector\n", name);
3122 #endif
3123 if (next_tvb == NULL) {
3124 /* Assume that we have a malformed packet. */
3125 THROW(ReportedBoundsError);
3127 count = cset->func(tree, next_tvb, 0, actx);
3129 /* if we consumed some bytes,
3130 or we knew the length was zero (during the first pass only) */
3131 if (count || (first_pass && ((len == 0) || ((ind_field == 1) && (len == 2))))) {
3132 /* we found it! */
3133 if (set_idx < MAX_SET_ELEMENTS)
3134 mandatory_fields &= ~(1 << set_idx);
3136 offset = eoffset;
3138 if (!(cset->flags & BER_FLAGS_NOOWNTAG) ) {
3139 /* if we stripped the tag and length we should also strip the EOC is ind_len */
3140 if (ind_field == 1) {
3141 /* skip over EOC */
3142 if (show_internal_ber_fields) {
3143 proto_tree_add_text(tree, tvb, offset, count, "SET FIELD EOC");
3147 break;
3152 if (!cset->func) {
3153 /* we didn't find a match */
3154 cause = proto_tree_add_string_format_value(
3155 tree, hf_ber_error, tvb, offset, len, "unknown_field",
3156 "Unknown field in SET class:%s(%d) tag:%d",
3157 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3158 ber_class,
3159 tag);
3160 expert_add_info(actx->pinfo, cause, &ei_ber_unknown_field_set);
3161 if (decode_unexpected) {
3162 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3163 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3165 offset = eoffset;
3169 if (mandatory_fields) {
3171 /* OK - we didn't find some of the elements we expected */
3173 for (set_idx = 0; (cset = &set[set_idx])->func && (set_idx < MAX_SET_ELEMENTS); set_idx++) {
3174 if (mandatory_fields & (1 << set_idx)) {
3175 /* here is something we should have seen - but didn't! */
3176 cause = proto_tree_add_string_format_value(
3177 tree, hf_ber_error, tvb, offset, lenx, "missing_field",
3178 "Missing field in SET class:%s(%d) tag:%d expected",
3179 val_to_str_const(cset->ber_class, ber_class_codes, "Unknown"),
3180 cset->ber_class,
3181 cset->tag);
3182 expert_add_info(actx->pinfo, cause, &ei_ber_missing_field_set);
3187 /* if we didnt end up at exactly offset, then we ate too many bytes */
3188 if (offset != end_offset) {
3189 tvb_ensure_bytes_exist(tvb, offset-2, 2);
3190 cause = proto_tree_add_string_format_value(
3191 tree, hf_ber_error, tvb, offset-2, 2, "illegal_length",
3192 "SET ate %d too many bytes",
3193 offset - end_offset);
3194 expert_add_info_format(actx->pinfo, cause, &ei_ber_error_length,
3195 "BER Error: too many bytes in SET");
3198 if (ind) {
3199 /* need to eat this EOC
3200 end_offset = tvb_length(tvb);*/
3201 end_offset += 2;
3202 if (show_internal_ber_fields) {
3203 proto_tree_add_text(tree, tvb, end_offset-2, 2 , "SET EOC");
3207 return end_offset;
3210 /* this function dissects a BER choice
3211 * If we did not find a matching choice, just return offset unchanged
3212 * in case it was a CHOICE { } OPTIONAL
3214 #ifdef DEBUG_BER
3215 #define DEBUG_BER_CHOICE
3216 #endif
3219 dissect_ber_choice(asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_choice_t *choice, gint hf_id, gint ett_id, gint *branch_taken)
3221 gint8 ber_class;
3222 gboolean pc, ind, imp_tag = FALSE;
3223 gint32 tag;
3224 guint32 len;
3225 proto_tree *tree = parent_tree;
3226 proto_item *item = NULL;
3227 int end_offset, start_offset, count;
3228 int hoffset = offset;
3229 gint length, length_remaining;
3230 tvbuff_t *next_tvb;
3231 gboolean first_pass;
3232 header_field_info *hfinfo;
3233 const ber_choice_t *ch;
3235 #ifdef DEBUG_BER_CHOICE
3237 const char *name;
3238 if (hf_id >= 0) {
3239 hfinfo = proto_registrar_get_nth(hf_id);
3240 name = hfinfo->name;
3241 } else {
3242 name = "unnamed";
3244 if (tvb_length_remaining(tvb, offset) > 3) {
3245 printf("CHOICE dissect_ber_choice(%s) entered offset:%d len:%d %02x:%02x:%02x\n", name, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
3246 } else {
3247 printf("CHOICE dissect_ber_choice(%s) entered len:%d\n", name, tvb_length_remaining(tvb, offset));
3250 #endif
3252 start_offset = offset;
3254 if (branch_taken) {
3255 *branch_taken = -1;
3258 if (tvb_length_remaining(tvb, offset) == 0) {
3259 item = proto_tree_add_string_format_value(
3260 parent_tree, hf_ber_error, tvb, offset, 0, "empty_choice",
3261 "Empty choice was found");
3262 expert_add_info(actx->pinfo, item, &ei_ber_empty_choice);
3263 return offset;
3266 /* read header and len for choice field */
3267 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
3268 offset = get_ber_length(tvb, offset, &len, &ind);
3269 end_offset = offset + len ;
3271 /* Some sanity checks.
3272 * The hf field passed to us MUST be an integer type
3274 if (hf_id >= 0) {
3275 hfinfo = proto_registrar_get_nth(hf_id);
3276 switch (hfinfo->type) {
3277 case FT_UINT8:
3278 case FT_UINT16:
3279 case FT_UINT24:
3280 case FT_UINT32:
3281 break;
3282 default:
3283 proto_tree_add_text(
3284 tree, tvb, offset, len,
3285 "dissect_ber_choice(): Was passed a HF field that was not integer type : %s",
3286 hfinfo->abbrev);
3287 g_warning("dissect_ber_choice(): frame:%u offset:%d Was passed a HF field that was not integer type : %s",
3288 actx->pinfo->fd->num, offset, hfinfo->abbrev);
3289 return end_offset;
3293 /* loop over all entries until we find the right choice or
3294 run out of entries */
3295 ch = choice;
3296 first_pass = TRUE;
3297 while (ch->func || first_pass) {
3298 if (branch_taken) {
3299 (*branch_taken)++;
3301 /* we reset for a second pass when we will look for choices */
3302 if (!ch->func) {
3303 first_pass = FALSE;
3304 ch = choice; /* reset to the beginning */
3305 if (branch_taken) {
3306 *branch_taken = -1;
3310 choice_try_again:
3311 #ifdef DEBUG_BER_CHOICE
3312 printf("CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d:(expected)%d flags:%d\n", ch, ber_class, ch->ber_class, tag, ch->tag, ch->flags);
3313 #endif
3314 if ( (first_pass
3315 && (((ch->ber_class == ber_class) && (ch->tag == tag))
3316 || ((ch->ber_class == ber_class) && (ch->tag == -1) && (ch->flags & BER_FLAGS_NOOWNTAG))))
3317 || (!first_pass && (((ch->ber_class == BER_CLASS_ANY) && (ch->tag == -1)))) /* we failed on the first pass so now try any choices */
3319 if (!(ch->flags & BER_FLAGS_NOOWNTAG)) {
3320 /* dissect header and len for field */
3321 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, start_offset, NULL, NULL, NULL);
3322 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3323 start_offset = hoffset;
3324 if (ind) {
3325 length = len - 2;
3326 } else {
3327 length = len;
3329 } else {
3330 length = end_offset- hoffset;
3332 /* create subtree */
3333 if (hf_id >= 0) {
3334 if (parent_tree) {
3335 item = proto_tree_add_uint(parent_tree, hf_id, tvb, hoffset, end_offset - hoffset, ch->value);
3336 tree = proto_item_add_subtree(item, ett_id);
3340 length_remaining = tvb_length_remaining(tvb, hoffset);
3341 if (length_remaining>length)
3342 length_remaining = length;
3344 #ifdef REMOVED
3345 /* This is bogus and makes the OID_1.0.9506.1.1.cap file
3346 * in Steven J Schaeffer's email of 2005-09-12 fail to dissect
3347 * properly. Maybe we should get rid of 'first_pass'
3348 * completely.
3349 * It was added as a qad workaround for some problem CMIP
3350 * traces anyway.
3351 * God, this file is a mess and it is my fault. /ronnie
3353 if (first_pass)
3354 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, length);
3355 else
3356 next_tvb = tvb; /* we didn't make selection on this class/tag so pass it on */
3357 #endif
3358 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, length);
3361 #ifdef DEBUG_BER_CHOICE
3363 const char *name;
3364 if (hf_id >= 0) {
3365 hfinfo = proto_registrar_get_nth(hf_id);
3366 name = hfinfo->name;
3367 } else {
3368 name = "unnamed";
3370 if (tvb_length_remaining(next_tvb, 0) > 3) {
3371 printf("CHOICE dissect_ber_choice(%s) calling subdissector start_offset:%d offset:%d len:%d %02x:%02x:%02x\n", name, start_offset, offset, tvb_length_remaining(next_tvb, 0), tvb_get_guint8(next_tvb, 0), tvb_get_guint8(next_tvb, 1), tvb_get_guint8(next_tvb, 2));
3372 } else {
3373 printf("CHOICE dissect_ber_choice(%s) calling subdissector len:%d\n", name, tvb_length(next_tvb));
3376 #endif
3377 if (next_tvb == NULL) {
3378 /* Assume that we have a malformed packet. */
3379 THROW(ReportedBoundsError);
3381 imp_tag = FALSE;
3382 if ((ch->flags & BER_FLAGS_IMPLTAG))
3383 imp_tag = TRUE;
3384 count = ch->func(imp_tag, next_tvb, 0, actx, tree, *ch->p_id);
3385 #ifdef DEBUG_BER_CHOICE
3387 const char *name;
3388 if (hf_id >= 0) {
3389 hfinfo = proto_registrar_get_nth(hf_id);
3390 name = hfinfo->name;
3391 } else {
3392 name = "unnamed";
3394 printf("CHOICE dissect_ber_choice(%s) subdissector ate %d bytes\n", name, count);
3396 #endif
3397 if ((count == 0) && (((ch->ber_class == ber_class) && (ch->tag == -1) && (ch->flags & BER_FLAGS_NOOWNTAG)) || !first_pass)) {
3398 /* wrong one, break and try again */
3399 ch++;
3400 #ifdef DEBUG_BER_CHOICE
3402 const char *name;
3403 if (hf_id >= 0) {
3404 hfinfo = proto_registrar_get_nth(hf_id);
3405 name = hfinfo->name;
3406 } else {
3407 name = "unnamed";
3409 printf("CHOICE dissect_ber_choice(%s) trying again\n", name);
3411 #endif
3412 goto choice_try_again;
3414 if (!(ch->flags & BER_FLAGS_NOOWNTAG)) {
3415 if (ind) {
3416 /* we are traversing a indfinite length choice where we did not pass the tag length */
3417 /* we need to eat the EOC */
3418 if (show_internal_ber_fields) {
3419 proto_tree_add_text(tree, tvb, start_offset, count+2, "CHOICE EOC");
3423 return end_offset;
3425 ch++;
3427 if (branch_taken) {
3428 /* none of the branches were taken so set the param
3429 back to -1 */
3430 *branch_taken = -1;
3433 #ifdef REMOVED
3434 /*XXX here we should have another flag to the CHOICE to distinguish
3435 * between the case when we know it is a mandatory or if the CHOICE is optional == no arm matched */
3437 /* oops no more entries and we still havent found
3438 * our guy :-(
3440 item = proto_tree_add_string_format_value(
3441 tree, hf_ber_error, tvb, offset, len, "missing_choice_field",
3442 "This choice field was not found.");
3443 expert_add_info(actx->pinfo, item, &ei_ber_choice_not_found);
3444 return end_offset;
3445 #endif
3447 return start_offset;
3451 dissect_ber_old_choice(asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_old_choice_t *choice, gint hf_id, gint ett_id, gint *branch_taken)
3453 gint8 ber_class;
3454 gboolean pc, ind;
3455 gint32 tag;
3456 guint32 len;
3457 proto_tree *tree = parent_tree;
3458 proto_item *item = NULL;
3459 int end_offset, start_offset, count;
3460 int hoffset = offset;
3461 gint length, length_remaining;
3462 tvbuff_t *next_tvb;
3463 gboolean first_pass;
3464 header_field_info *hfinfo;
3465 const ber_old_choice_t *ch;
3467 #ifdef DEBUG_BER_CHOICE
3469 const char *name;
3470 if (hf_id >= 0) {
3471 hfinfo = proto_registrar_get_nth(hf_id);
3472 name = hfinfo->name;
3473 } else {
3474 name = "unnamed";
3476 if (tvb_length_remaining(tvb, offset) > 3) {
3477 printf("CHOICE dissect_ber_old_choice(%s) entered offset:%d len:%d %02x:%02x:%02x\n", name, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
3478 } else {
3479 printf("CHOICE dissect_ber_old_choice(%s) entered len:%d\n", name, tvb_length_remaining(tvb, offset));
3482 #endif
3483 start_offset = offset;
3485 if (tvb_length_remaining(tvb, offset) == 0) {
3486 item = proto_tree_add_string_format_value(
3487 parent_tree, hf_ber_error, tvb, offset, 0, "empty_choice",
3488 "Empty choice was found");
3489 expert_add_info(actx->pinfo, item, &ei_ber_empty_choice);
3490 return offset;
3493 /* read header and len for choice field */
3494 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
3495 offset = get_ber_length(tvb, offset, &len, &ind);
3496 end_offset = offset + len ;
3498 /* Some sanity checks.
3499 * The hf field passed to us MUST be an integer type
3501 if (hf_id >= 0) {
3502 hfinfo = proto_registrar_get_nth(hf_id);
3503 switch (hfinfo->type) {
3504 case FT_UINT8:
3505 case FT_UINT16:
3506 case FT_UINT24:
3507 case FT_UINT32:
3508 break;
3509 default:
3510 proto_tree_add_text(
3511 tree, tvb, offset, len,
3512 "dissect_ber_old_choice(): Was passed a HF field that was not integer type : %s",
3513 hfinfo->abbrev);
3514 g_warning("dissect_ber_old_choice(): frame:%u offset:%d Was passed a HF field that was not integer type : %s",
3515 actx->pinfo->fd->num, offset, hfinfo->abbrev);
3516 return end_offset;
3522 /* loop over all entries until we find the right choice or
3523 run out of entries */
3524 ch = choice;
3525 if (branch_taken) {
3526 *branch_taken = -1;
3528 first_pass = TRUE;
3529 while (ch->func || first_pass) {
3530 if (branch_taken) {
3531 (*branch_taken)++;
3533 /* we reset for a second pass when we will look for choices */
3534 if (!ch->func) {
3535 first_pass = FALSE;
3536 ch = choice; /* reset to the beginning */
3537 if (branch_taken) {
3538 *branch_taken = -1;
3542 choice_try_again:
3543 #ifdef DEBUG_BER_CHOICE
3544 printf("CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d:(expected)%d flags:%d\n", ch, ber_class, ch->ber_class, tag, ch->tag, ch->flags);
3545 #endif
3546 if ( (first_pass
3547 && (((ch->ber_class == ber_class) && (ch->tag == tag))
3548 || ((ch->ber_class == ber_class) && (ch->tag == -1) && (ch->flags & BER_FLAGS_NOOWNTAG))))
3549 || (!first_pass && (((ch->ber_class == BER_CLASS_ANY) && (ch->tag == -1)))) /* we failed on the first pass so now try any choices */
3551 if (!(ch->flags & BER_FLAGS_NOOWNTAG)) {
3552 /* dissect header and len for field */
3553 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, start_offset, NULL, NULL, NULL);
3554 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3555 start_offset = hoffset;
3556 if (ind) {
3557 length = len - 2;
3558 } else {
3559 length = len;
3561 } else {
3562 length = end_offset- hoffset;
3564 /* create subtree */
3565 if (hf_id >= 0) {
3566 if (parent_tree) {
3567 item = proto_tree_add_uint(parent_tree, hf_id, tvb, hoffset, end_offset - hoffset, ch->value);
3568 tree = proto_item_add_subtree(item, ett_id);
3572 length_remaining = tvb_length_remaining(tvb, hoffset);
3573 if (length_remaining>length)
3574 length_remaining = length;
3576 #ifdef REMOVED
3577 /* This is bogus and makes the OID_1.0.9506.1.1.cap file
3578 * in Steven J Schaeffer's email of 2005-09-12 fail to dissect
3579 * properly. Maybe we should get rid of 'first_pass'
3580 * completely.
3581 * It was added as a qad workaround for some problem CMIP
3582 * traces anyway.
3583 * God, this file is a mess and it is my fault. /ronnie
3585 if (first_pass)
3586 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, length);
3587 else
3588 next_tvb = tvb; /* we didn't make selection on this class/tag so pass it on */
3589 #endif
3590 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, length_remaining);
3593 #ifdef DEBUG_BER_CHOICE
3595 const char *name;
3596 if (hf_id >= 0) {
3597 hfinfo = proto_registrar_get_nth(hf_id);
3598 name = hfinfo->name;
3599 } else {
3600 name = "unnamed";
3602 if (tvb_length_remaining(next_tvb, 0) > 3) {
3603 printf("CHOICE dissect_ber_old_choice(%s) calling subdissector start_offset:%d offset:%d len:%d %02x:%02x:%02x\n", name, start_offset, offset, tvb_length_remaining(next_tvb, 0), tvb_get_guint8(next_tvb, 0), tvb_get_guint8(next_tvb, 1), tvb_get_guint8(next_tvb, 2));
3604 } else {
3605 printf("CHOICE dissect_ber_old_choice(%s) calling subdissector len:%d\n", name, tvb_length(next_tvb));
3608 #endif
3609 if (next_tvb == NULL) {
3610 /* Assume that we have a malformed packet. */
3611 THROW(ReportedBoundsError);
3613 count = ch->func(tree, next_tvb, 0, actx);
3614 #ifdef DEBUG_BER_CHOICE
3616 const char *name;
3617 if (hf_id >= 0) {
3618 hfinfo = proto_registrar_get_nth(hf_id);
3619 name = hfinfo->name;
3620 } else {
3621 name = "unnamed";
3623 printf("CHOICE dissect_ber_old_choice(%s) subdissector ate %d bytes\n", name, count);
3625 #endif
3626 if ((count == 0) && (((ch->ber_class == ber_class) && (ch->tag == -1) && (ch->flags & BER_FLAGS_NOOWNTAG)) || !first_pass)) {
3627 /* wrong one, break and try again */
3628 ch++;
3629 #ifdef DEBUG_BER_CHOICE
3631 const char *name;
3632 if (hf_id >= 0) {
3633 hfinfo = proto_registrar_get_nth(hf_id);
3634 name = hfinfo->name;
3635 } else {
3636 name = "unnamed";
3638 printf("CHOICE dissect_ber_old_choice(%s) trying again\n", name);
3640 #endif
3641 goto choice_try_again;
3643 if (!(ch->flags & BER_FLAGS_NOOWNTAG)) {
3644 if (ind) {
3645 /* we are traversing a indfinite length choice where we did not pass the tag length */
3646 /* we need to eat the EOC */
3647 if (show_internal_ber_fields) {
3648 proto_tree_add_text(tree, tvb, start_offset, count+2, "CHOICE EOC");
3652 return end_offset;
3654 ch++;
3656 if (branch_taken) {
3657 /* none of the branches were taken so set the param
3658 back to -1 */
3659 *branch_taken=-1;
3662 #ifdef REMOVED
3663 /*XXX here we should have another flag to the CHOICE to distinguish
3664 * between the case when we know it is a mandatory or if the CHOICE is optional == no arm matched */
3666 /* oops no more entries and we still havent found
3667 * our guy :-(
3669 cause = proto_tree_add_string_format_value(
3670 tree, hf_ber_error, tvb, offset, len, "missing_choice_field",
3671 "This choice field was not found.");
3672 expert_add_info(actx->pinfo, item, &ei_ber_choice_not_found);
3673 return end_offset;
3674 #endif
3676 return start_offset;
3679 #if 0
3680 /* this function dissects a BER GeneralString
3683 dissect_ber_GeneralString(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, int name_len)
3685 gint8 ber_class;
3686 gboolean pc;
3687 gint32 tag;
3688 guint32 len;
3689 int end_offset;
3690 int hoffset;
3691 char str_arr[256];
3692 guint32 max_len;
3693 char *str;
3694 proto_item *cause;
3696 str = str_arr;
3697 max_len = 255;
3698 if (name_string) {
3699 str = name_string;
3700 max_len = name_len;
3703 hoffset = offset;
3704 /* first we must read the GeneralString header */
3705 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
3706 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
3707 end_offset = offset + len;
3709 /* sanity check: we only handle Universal GeneralString*/
3710 if ( (ber_class != BER_CLASS_UNI)
3711 || (tag != BER_UNI_TAG_GENSTR) ) {
3712 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3713 cause = proto_tree_add_string_format_value(
3714 tree, hf_ber_error, tvb, offset, len, "generalstring_expected",
3715 "GeneralString expected but class:%s(%d) %s tag:%d was unexpected",
3716 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3717 ber_class, pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
3718 tag);
3719 expert_add_info(actx->pinfo, cause, &ei_ber_expected_general_string,
3720 "BER Error: GeneralString expected");
3721 if (decode_unexpected) {
3722 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3723 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3725 return end_offset;
3728 if (len >= (max_len - 1)) {
3729 len = max_len - 1;
3732 tvb_memcpy(tvb, str, offset, len);
3733 str[len]=0;
3735 if (hf_id >= 0) {
3736 proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
3739 return end_offset;
3741 #endif
3744 dissect_ber_constrained_restricted_string(gboolean implicit_tag, gint32 type, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, tvbuff_t **out_tvb) {
3745 gint8 ber_class;
3746 gboolean pc;
3747 gint32 tag;
3748 guint32 len;
3749 int eoffset;
3750 int hoffset = offset;
3751 proto_item *cause;
3753 #ifdef DEBUG_BER
3755 const char *name;
3756 header_field_info *hfinfo;
3757 if (hf_id >= 0) {
3758 hfinfo = proto_registrar_get_nth(hf_id);
3759 name = hfinfo->name;
3760 } else {
3761 name = "unnamed";
3763 if (tvb_length_remaining(tvb, offset) > 3) {
3764 printf("RESTRICTED STRING dissect_ber_octet string(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name, implicit_tag, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
3765 } else {
3766 printf("RESTRICTED STRING dissect_ber_octet_string(%s) entered\n", name);
3769 #endif
3771 if (!implicit_tag) {
3772 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
3773 offset = get_ber_length(tvb, offset, &len, NULL);
3774 eoffset = offset + len;
3776 /* sanity check */
3777 if ( (ber_class != BER_CLASS_UNI)
3778 || (tag != type) ) {
3779 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3780 cause = proto_tree_add_string_format_value(
3781 tree, hf_ber_error, tvb, offset, len, "string_expected",
3782 "String with tag=%d expected but class:%s(%d) %s tag:%d was unexpected",
3783 type,
3784 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3785 ber_class, pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
3786 tag);
3787 expert_add_info(actx->pinfo, cause, &ei_ber_expected_string);
3788 if (decode_unexpected) {
3789 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3790 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3792 return eoffset;
3796 /* 8.21.3 */
3797 return dissect_ber_constrained_octet_string(implicit_tag, actx, tree, tvb, hoffset, min_len, max_len, hf_id, out_tvb);
3800 int dissect_ber_restricted_string(gboolean implicit_tag, gint32 type, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb)
3802 return dissect_ber_constrained_restricted_string(implicit_tag, type, actx, tree, tvb, offset, NO_BOUND, NO_BOUND, hf_id, out_tvb);
3806 dissect_ber_GeneralString(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, guint name_len)
3808 tvbuff_t *out_tvb = NULL;
3809 gint tvb_len;
3811 offset = dissect_ber_restricted_string(FALSE, BER_UNI_TAG_GeneralString, actx, tree, tvb, offset, hf_id, (name_string) ? &out_tvb : NULL);
3813 if (name_string) {
3815 * XXX - do we want to just get what's left in the tvbuff
3816 * if the full length isn't available in the tvbuff, or
3817 * do we want to throw an exception?
3819 if (out_tvb) {
3820 tvb_len = tvb_length(out_tvb);
3821 if ((guint)tvb_len >= name_len) {
3822 tvb_memcpy(out_tvb, (guint8*)name_string, 0, name_len-1);
3823 name_string[name_len-1] = '\0';
3824 } else {
3825 tvb_memcpy(out_tvb, (guint8*)name_string, 0, tvb_len);
3826 name_string[tvb_len] = '\0';
3831 return offset;
3834 /* 8.19 Encoding of a relative or absolute object identifier value.
3836 static int
3837 dissect_ber_any_oid(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **value_tvb, gboolean is_absolute)
3839 gint8 ber_class;
3840 gboolean pc;
3841 gint32 tag;
3842 guint32 len;
3843 int eoffset;
3844 int hoffset;
3845 const char *str;
3846 proto_item *cause;
3847 const gchar *name;
3848 header_field_info *hfi;
3850 #ifdef DEBUG_BER
3852 header_field_info *hfinfo;
3853 if (hf_id >= 0) {
3854 hfinfo = proto_registrar_get_nth(hf_id);
3855 name = hfinfo->name;
3856 } else {
3857 name = "unnamed";
3859 if (tvb_length_remaining(tvb, offset) > 3) {
3860 printf("OBJECT IDENTIFIER dissect_ber_any_oid(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name, implicit_tag, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
3861 } else {
3862 printf("OBJECT IDENTIFIER dissect_ber_any_oid(%s) entered\n", name);
3865 #endif
3867 if (!implicit_tag) {
3868 hoffset = offset;
3869 /* sanity check */
3870 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
3871 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
3872 eoffset = offset + len;
3873 if ( (ber_class != BER_CLASS_UNI)
3874 || (is_absolute && tag != BER_UNI_TAG_OID)
3875 || (!is_absolute && tag != BER_UNI_TAG_RELATIVE_OID) ) {
3876 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3877 cause = proto_tree_add_string_format_value(
3878 tree, hf_ber_error, tvb, offset, len, "oid_expected",
3879 "Object Identifier expected but class:%s(%d) %s tag:%d was unexpected",
3880 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
3881 ber_class,
3882 pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
3883 tag);
3884 expert_add_info(actx->pinfo, cause, &ei_ber_expected_object_identifier);
3885 if (decode_unexpected) {
3886 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3887 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3889 return eoffset;
3891 } else {
3892 len = tvb_length_remaining(tvb, offset);
3893 eoffset = offset+len;
3896 actx->created_item = NULL;
3897 hfi = proto_registrar_get_nth(hf_id);
3898 if ((is_absolute && hfi->type == FT_OID) || (!is_absolute && hfi->type == FT_REL_OID)) {
3899 actx->created_item = proto_tree_add_item(tree, hf_id, tvb, offset, len, ENC_BIG_ENDIAN);
3900 } else if (IS_FT_STRING(hfi->type)) {
3901 str = oid_encoded2string(tvb_get_ptr(tvb, offset, len), len);
3902 actx->created_item = proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
3903 if (actx->created_item) {
3904 /* see if we know the name of this oid */
3905 name = oid_resolved_from_encoded(tvb_get_ptr(tvb, offset, len), len);
3906 if (name) {
3907 proto_item_append_text(actx->created_item, " (%s)", name);
3910 } else {
3911 DISSECTOR_ASSERT_NOT_REACHED();
3914 if (value_tvb)
3915 *value_tvb = tvb_new_subset(tvb, offset, len, len);
3917 return eoffset;
3920 static int
3921 dissect_ber_any_oid_str(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, const char **value_stringx, gboolean is_absolute)
3923 tvbuff_t *value_tvb = NULL;
3924 guint length;
3926 offset = dissect_ber_any_oid(implicit_tag, actx, tree, tvb, offset, hf_id, (value_stringx) ? &value_tvb : NULL, is_absolute);
3928 if (value_stringx) {
3929 if (value_tvb && (length = tvb_length(value_tvb))) {
3930 *value_stringx = oid_encoded2string(tvb_get_ptr(value_tvb, 0, length), length);
3931 } else {
3932 *value_stringx = "";
3936 return offset;
3939 /* 8.19 Encoding of a relative object identifier value.
3942 dissect_ber_relative_oid(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **value_tvb)
3944 return dissect_ber_any_oid(implicit_tag, actx, tree, tvb, offset, hf_id, value_tvb, FALSE);
3948 dissect_ber_relative_oid_str(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, const char **value_stringx)
3950 return dissect_ber_any_oid_str(implicit_tag, actx, tree, tvb, offset, hf_id, value_stringx, FALSE);
3953 /* 8.19 Encoding of an object identifier value.
3956 dissect_ber_object_identifier(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **value_tvb)
3958 return dissect_ber_any_oid(implicit_tag, actx, tree, tvb, offset, hf_id, value_tvb, TRUE);
3962 dissect_ber_object_identifier_str(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, const char **value_stringx)
3964 return dissect_ber_any_oid_str(implicit_tag, actx, tree, tvb, offset, hf_id, value_stringx, TRUE);
3967 #ifdef DEBUG_BER
3968 #define DEBUG_BER_SQ_OF
3969 #endif
3971 static int
3972 dissect_ber_sq_of(gboolean implicit_tag, gint32 type, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
3973 gint8 classx;
3974 gboolean pcx, ind = FALSE, ind_field;
3975 gint32 tagx;
3976 guint32 lenx;
3978 proto_tree *tree = parent_tree;
3979 proto_item *item = NULL;
3980 proto_item *causex;
3981 int cnt, hoffsetx, end_offset;
3982 header_field_info *hfi;
3983 gint length_remaining;
3984 tvbuff_t *next_tvb;
3986 #ifdef DEBUG_BER_SQ_OF
3988 const char *name;
3989 header_field_info *hfinfo;
3990 if (hf_id >= 0) {
3991 hfinfo = proto_registrar_get_nth(hf_id);
3992 name = hfinfo->name;
3993 } else {
3994 name = "unnamed";
3996 if (tvb_length_remaining(tvb,offset) > 3) {
3997 printf("SQ OF dissect_ber_sq_of(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name, implicit_tag, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
3998 } else {
3999 printf("SQ OF dissect_ber_sq_of(%s) entered\n", name);
4002 #endif
4004 if (!implicit_tag) {
4005 hoffsetx = offset;
4006 /* first we must read the sequence header */
4007 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
4008 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
4009 if (ind) {
4010 /* if the length is indefinite we don't really know (yet) where the
4011 * object ends so assume it spans the rest of the tvb for now.
4013 end_offset = offset + lenx;
4014 } else {
4015 end_offset = offset + lenx;
4018 /* sanity check: we only handle Constructed Universal Sequences */
4019 if ((classx != BER_CLASS_APP) && (classx != BER_CLASS_PRI)) {
4020 if (!pcx
4021 || (!implicit_tag && ((classx != BER_CLASS_UNI)
4022 || (tagx != type)))) {
4023 tvb_ensure_bytes_exist(tvb, hoffsetx, 2);
4024 causex = proto_tree_add_string_format_value(
4025 tree, hf_ber_error, tvb, offset, lenx,
4026 (type == BER_UNI_TAG_SEQUENCE) ? "set_of_expected" : "sequence_of_expected",
4027 "%s Of expected but class:%s(%d) %s tag:%d was unexpected",
4028 (type == BER_UNI_TAG_SEQUENCE) ? "Set" : "Sequence",
4029 val_to_str_const(classx, ber_class_codes, "Unknown"),
4030 classx, pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
4031 tagx);
4032 if (type == BER_UNI_TAG_SEQUENCE) {
4033 expert_add_info_format(
4034 actx->pinfo, causex, &ei_ber_expected_set,
4035 "BER Error: Set Of expected");
4036 } else {
4037 expert_add_info_format(
4038 actx->pinfo, causex, &ei_ber_expected_sequence,
4039 "BER Error: Sequence Of expected");
4041 if (decode_unexpected) {
4042 proto_tree *unknown_tree = proto_item_add_subtree(causex, ett_ber_unknown);
4043 dissect_unknown_ber(actx->pinfo, tvb, hoffsetx, unknown_tree);
4045 return end_offset;
4048 } else {
4049 /* the tvb length should be correct now nope we could be coming from an implicit choice or sequence, thus we
4050 read the items we match and return the length*/
4051 lenx = tvb_length_remaining(tvb, offset);
4052 end_offset = offset + lenx;
4055 /* count number of items */
4056 cnt = 0;
4057 hoffsetx = offset;
4058 /* only count the number of items IFF we have the full blob,
4059 * else this will just generate a [short frame] before we even start
4060 * dissecting a single item.
4062 /* XXX Do we really need to count them at all ? ronnie */
4063 if (tvb_length_remaining(tvb, offset) == tvb_reported_length_remaining(tvb, offset)) {
4064 while (offset < end_offset) {
4065 guint32 len;
4066 gint s_offset;
4068 s_offset = offset;
4070 /*if (ind) { this sequence of was of indefinite length, if this is implicit indefinite impossible maybe
4071 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
4072 if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
4073 break;
4075 /* } */
4077 /* read header and len for next field */
4078 offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
4079 offset = get_ber_length(tvb, offset, &len, &ind);
4080 /* best place to get real length of implicit sequence of or set of is here... */
4081 /* adjust end_offset if we find somthing that doesnt match */
4082 offset += len;
4083 cnt++;
4084 if (offset <= s_offset)
4085 THROW(ReportedBoundsError);
4088 offset = hoffsetx;
4090 /* create subtree */
4091 if (hf_id >= 0) {
4092 hfi = proto_registrar_get_nth(hf_id);
4093 if (parent_tree) {
4094 if (hfi->type == FT_NONE) {
4095 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, lenx, ENC_BIG_ENDIAN);
4096 proto_item_append_text(item, ":");
4097 } else {
4098 item = proto_tree_add_uint(parent_tree, hf_id, tvb, offset, lenx, cnt);
4099 proto_item_append_text(item, (cnt == 1) ? " item" : " items");
4101 tree = proto_item_add_subtree(item, ett_id);
4102 ber_check_items (cnt, min_len, max_len, actx, item);
4106 /* loop over all entries until we reach the end of the sequence */
4107 while (offset < end_offset) {
4108 gint8 ber_class;
4109 gboolean pc;
4110 gint32 tag;
4111 guint32 len;
4112 int eoffset;
4113 int hoffset;
4114 proto_item *cause;
4115 gboolean imp_tag;
4117 hoffset = offset;
4118 /*if (ind) { this sequence was of indefinite length, if this is implicit indefinite impossible maybe
4119 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
4120 if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
4121 if (show_internal_ber_fields) {
4122 proto_tree_add_text(tree, tvb, hoffset, end_offset-hoffset, "SEQ OF EOC");
4124 return offset+2;
4126 /*}*/
4127 /* read header and len for next field */
4128 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
4129 offset = get_ber_length(tvb, offset, &len, &ind_field);
4130 eoffset = offset + len;
4131 /* Make sure we move forward */
4132 if (eoffset <= hoffset)
4133 THROW(ReportedBoundsError);
4135 if ((ber_class == BER_CLASS_UNI) && (tag == BER_UNI_TAG_EOC)) {
4136 /* This is a zero length sequence of*/
4137 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
4138 dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
4139 return eoffset;
4141 /* verify that this one is the one we want */
4142 /* ahup if we are implicit then we return to the upper layer how much we have used */
4143 if (seq->ber_class != BER_CLASS_ANY) {
4144 if ((seq->ber_class != ber_class)
4145 || (seq->tag != tag) ) {
4146 if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
4147 cause = proto_tree_add_string_format_value(
4148 tree, hf_ber_error, tvb, offset, len, "wrong_field",
4149 "Wrong field in SQ OF(tag %u expected %u)",
4150 tag,
4151 seq->tag);
4152 expert_add_info_format(
4153 actx->pinfo, cause, &ei_ber_sequence_field_wrong,
4154 "BER Error: Wrong field in Sequence Of");
4155 if (decode_unexpected) {
4156 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
4157 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
4159 offset = eoffset;
4160 continue;
4161 /* wrong.... */
4166 if (!(seq->flags & BER_FLAGS_NOOWNTAG) && !(seq->flags & BER_FLAGS_IMPLTAG)) {
4167 /* dissect header and len for field */
4168 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
4169 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
4171 if ((seq->flags == BER_FLAGS_IMPLTAG) && (seq->ber_class == BER_CLASS_CON)) {
4172 /* Constructed sequence of with a tag */
4173 /* dissect header and len for field */
4174 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
4175 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
4176 /* Function has IMPLICIT TAG */
4179 length_remaining = tvb_length_remaining(tvb, hoffset);
4180 if (length_remaining>eoffset-hoffset)
4181 length_remaining = eoffset-hoffset;
4182 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, length_remaining);
4184 imp_tag = FALSE;
4185 if (seq->flags == BER_FLAGS_IMPLTAG)
4186 imp_tag = TRUE;
4187 /* call the dissector for this field */
4188 seq->func(imp_tag, next_tvb, 0, actx, tree, *seq->p_id);
4189 /* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
4190 doesnt match the next item, thus this implicit sequence is over, return the number of bytes
4191 we have eaten to allow the possible upper sequence continue... */
4192 cnt++; /* rubbish*/
4193 offset = eoffset;
4196 /* if we didnt end up at exactly offset, then we ate too many bytes */
4197 if (offset != end_offset) {
4198 tvb_ensure_bytes_exist(tvb, offset-2, 2);
4199 causex = proto_tree_add_string_format_value(
4200 tree, hf_ber_error, tvb, offset-2, 2, "illegal_length",
4201 "%s Of ate %d too many bytes",
4202 (type == BER_UNI_TAG_SEQUENCE) ? "Set" : "Sequence",
4203 offset - end_offset);
4204 expert_add_info_format(actx->pinfo, causex, &ei_ber_error_length,
4205 "BER Error:too many byte in %s",
4206 (type == BER_UNI_TAG_SEQUENCE) ? "Set" : "Sequence");
4209 return end_offset;
4212 static int
4213 dissect_ber_old_sq_of(gboolean implicit_tag, gint32 type, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_old_sequence_t *seq, gint hf_id, gint ett_id) {
4214 gint8 classx;
4215 gboolean pcx, ind = FALSE, ind_field;
4216 gint32 tagx;
4217 guint32 lenx;
4219 proto_tree *tree = parent_tree;
4220 proto_item *item = NULL;
4221 proto_item *causex;
4222 int cnt, hoffsetx, end_offset;
4223 header_field_info *hfi;
4224 /*gint length_remaining;*/
4226 #ifdef DEBUG_BER_SQ_OF
4228 const char *name;
4229 header_field_info *hfinfo;
4230 if (hf_id >= 0) {
4231 hfinfo = proto_registrar_get_nth(hf_id);
4232 name = hfinfo->name;
4233 } else {
4234 name = "unnamed";
4236 if (tvb_length_remaining(tvb, offset) > 3) {
4237 printf("SQ OF dissect_ber_old_sq_of(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name, implicit_tag, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2));
4238 } else {
4239 printf("SQ OF dissect_ber_old_sq_of(%s) entered\n", name);
4242 #endif
4244 if (!implicit_tag) {
4245 hoffsetx = offset;
4246 /* first we must read the sequence header */
4247 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
4248 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
4249 if (ind) {
4250 /* if the length is indefinite we don't really know (yet) where the
4251 * object ends so assume it spans the rest of the tvb for now.
4253 end_offset = offset + lenx;
4254 } else {
4255 end_offset = offset + lenx;
4258 /* sanity check: we only handle Constructed Universal Sequences */
4259 if ((classx != BER_CLASS_APP) && (classx != BER_CLASS_PRI)) {
4260 if (!pcx
4261 || (!implicit_tag && ((classx != BER_CLASS_UNI)
4262 || (tagx != type)))) {
4263 tvb_ensure_bytes_exist(tvb, hoffsetx, 2);
4264 causex = proto_tree_add_string_format_value(
4265 tree, hf_ber_error, tvb, offset, lenx,
4266 (type == BER_UNI_TAG_SEQUENCE) ? "set_of_expected" : "sequence_of_expected",
4267 "%s Of expected but class:%s(%d) %s tag:%d was unexpected",
4268 (type == BER_UNI_TAG_SEQUENCE) ? "Set" : "Sequence",
4269 val_to_str_const(classx, ber_class_codes, "Unknown"),
4270 classx,
4271 pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
4272 tagx);
4273 if (type == BER_UNI_TAG_SEQUENCE) {
4274 expert_add_info_format(
4275 actx->pinfo, causex, &ei_ber_expected_set,
4276 "BER Error: Set Of expected");
4277 } else {
4278 expert_add_info_format(
4279 actx->pinfo, causex, &ei_ber_expected_sequence,
4280 "BER Error: Sequence Of expected");
4282 if (decode_unexpected) {
4283 proto_tree *unknown_tree = proto_item_add_subtree(causex, ett_ber_unknown);
4284 dissect_unknown_ber(actx->pinfo, tvb, hoffsetx, unknown_tree);
4286 return end_offset;
4289 } else {
4290 /* the tvb length should be correct now nope we could be coming from an implicit choice or sequence, thus we
4291 read the items we match and return the length*/
4292 lenx = tvb_length_remaining(tvb, offset);
4293 end_offset = offset + lenx;
4296 /* count number of items */
4297 cnt = 0;
4298 hoffsetx = offset;
4299 /* only count the number of items IFF we have the full blob,
4300 * else this will just generate a [short frame] before we even start
4301 * dissecting a single item.
4303 /* XXX Do we really need to count them at all ? ronnie */
4304 if (tvb_length_remaining(tvb, offset) == tvb_reported_length_remaining(tvb, offset)) {
4305 while (offset < end_offset) {
4306 guint32 len;
4307 gint s_offset;
4309 s_offset = offset;
4311 if (ind) { /* this sequence of was of indefinite length, so check for EOC */
4312 if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
4313 break;
4317 /* read header and len for next field */
4318 offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
4319 offset = get_ber_length(tvb, offset, &len, &ind);
4320 /* best place to get real length of implicit sequence of or set of is here... */
4321 /* adjust end_offset if we find somthing that doesn't match */
4322 offset += len;
4323 cnt++;
4324 if (offset <= s_offset)
4325 THROW(ReportedBoundsError);
4328 offset = hoffsetx;
4330 /* create subtree */
4331 if (hf_id >= 0) {
4332 hfi = proto_registrar_get_nth(hf_id);
4333 if (parent_tree) {
4334 if (hfi->type == FT_NONE) {
4335 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, lenx, ENC_BIG_ENDIAN);
4336 proto_item_append_text(item, ":");
4337 } else {
4338 item = proto_tree_add_uint(parent_tree, hf_id, tvb, offset, lenx, cnt);
4339 proto_item_append_text(item, (cnt == 1) ? " item" : " items");
4341 tree = proto_item_add_subtree(item, ett_id);
4345 /* loop over all entries until we reach the end of the sequence */
4346 while (offset < end_offset) {
4347 gint8 ber_class;
4348 gboolean pc;
4349 gint32 tag;
4350 guint32 len;
4351 int eoffset;
4352 int hoffset;
4353 proto_item *cause;
4355 hoffset = offset;
4356 if (ind) { /*this 'sequence of' was of indefinite length, so check for EOC */
4357 if ((tvb_get_guint8(tvb, offset) == 0) && (tvb_get_guint8(tvb, offset+1) == 0)) {
4358 if (show_internal_ber_fields) {
4359 proto_tree_add_text(tree, tvb, hoffset, end_offset-hoffset, "SEQ OF EOC");
4361 return offset+2;
4364 /* read header and len for next field */
4365 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
4366 offset = get_ber_length(tvb, offset, &len, &ind_field);
4367 eoffset = offset + len;
4368 /* Make sure we move forward */
4369 if (eoffset <= hoffset)
4370 THROW(ReportedBoundsError);
4372 if ((ber_class == BER_CLASS_UNI) && (tag == BER_UNI_TAG_EOC)) {
4373 /* This is a zero length sequence of*/
4374 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
4375 dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
4376 return eoffset;
4378 /* verify that this one is the one we want */
4379 /* ahup if we are implicit then we return to the upper layer how much we have used */
4380 if (seq->ber_class != BER_CLASS_ANY) {
4381 if ((seq->ber_class != ber_class)
4382 || (seq->tag != tag) ) {
4383 if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
4384 cause = proto_tree_add_string_format_value(
4385 tree, hf_ber_error, tvb, offset, len, "wrong_field",
4386 "Wrong field in SQ OF");
4387 expert_add_info_format(
4388 actx->pinfo, cause, &ei_ber_sequence_field_wrong,
4389 "BER Error: Wrong field in Sequence Of");
4390 if (decode_unexpected) {
4391 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
4392 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
4394 offset = eoffset;
4395 continue;
4396 /* wrong.... */
4401 if (!(seq->flags & BER_FLAGS_NOOWNTAG) && !(seq->flags & BER_FLAGS_IMPLTAG)) {
4402 /* dissect header and len for field */
4403 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
4404 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
4406 if ((seq->flags == BER_FLAGS_IMPLTAG) && (seq->ber_class == BER_CLASS_CON)) {
4407 /* Constructed sequence of with a tag */
4408 /* dissect header and len for field */
4409 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
4410 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
4413 /*length_remaining = tvb_length_remaining(tvb, hoffset);
4414 if (length_remaining > (eoffset - hoffset))
4415 length_remaining = eoffset - hoffset;*/
4418 /* call the dissector for this field */
4419 seq->func(tree, tvb, hoffset, actx);
4420 /* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
4421 doesnt match the next item, thus this implicit sequence is over, return the number of bytes
4422 we have eaten to allow the possible upper sequence continue... */
4423 cnt++; /* rubbish*/
4424 offset = eoffset;
4427 /* if we didn't end up at exactly offset, then we ate too many bytes */
4428 if (offset != end_offset) {
4429 tvb_ensure_bytes_exist(tvb, offset-2, 2);
4430 causex =proto_tree_add_string_format_value(
4431 tree, hf_ber_error, tvb, offset-2, 2, "illegal_length",
4432 "%s Of ate %d too many bytes",
4433 (type == BER_UNI_TAG_SEQUENCE) ? "Set" : "Sequence",
4434 offset-end_offset);
4435 expert_add_info_format(actx->pinfo, causex, &ei_ber_error_length,
4436 "BER Error:too many byte in %s",
4437 (type == BER_UNI_TAG_SEQUENCE) ? "Set" : "Sequence");
4440 return end_offset;
4444 dissect_ber_constrained_sequence_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
4445 return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SEQUENCE, actx, parent_tree, tvb, offset, min_len, max_len, seq, hf_id, ett_id);
4449 dissect_ber_sequence_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
4450 return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SEQUENCE, actx, parent_tree, tvb, offset, NO_BOUND, NO_BOUND, seq, hf_id, ett_id);
4454 dissect_ber_constrained_set_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
4455 return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SET, actx, parent_tree, tvb, offset, min_len, max_len, seq, hf_id, ett_id);
4459 dissect_ber_set_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
4460 return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SET, actx, parent_tree, tvb, offset, NO_BOUND, NO_BOUND, seq, hf_id, ett_id);
4464 dissect_ber_old_sequence_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_old_sequence_t *seq, gint hf_id, gint ett_id) {
4465 return dissect_ber_old_sq_of(implicit_tag, BER_UNI_TAG_SEQUENCE, actx, parent_tree, tvb, offset, seq, hf_id, ett_id);
4469 dissect_ber_old_set_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_old_sequence_t *seq, gint hf_id, gint ett_id) {
4470 return dissect_ber_old_sq_of(implicit_tag, BER_UNI_TAG_SET, actx, parent_tree, tvb, offset, seq, hf_id, ett_id);
4474 dissect_ber_GeneralizedTime(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
4476 char str[35];
4477 int tmp_int;
4478 const guint8 *tmpstr;
4479 char *strptr;
4480 char first_delim[2];
4481 int first_digits;
4482 char second_delim[2];
4483 int second_digits;
4484 int ret;
4485 gint8 ber_class;
4486 gboolean pc;
4487 gint32 tag;
4488 guint32 len;
4489 int end_offset;
4490 int hoffset;
4491 proto_item *cause;
4493 if (!implicit_tag) {
4494 hoffset = offset;
4495 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
4496 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
4497 end_offset = offset+len;
4499 /* sanity check. we only handle universal/generalized time */
4500 if ( (ber_class != BER_CLASS_UNI)
4501 || (tag != BER_UNI_TAG_GeneralizedTime)) {
4502 tvb_ensure_bytes_exist(tvb, hoffset, 2);
4503 cause = proto_tree_add_string_format_value(
4504 tree, hf_ber_error, tvb, offset, len, "generalized_time_expected",
4505 "GeneralizedTime expected but class:%s(%d) %s tag:%d was unexpected",
4506 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
4507 ber_class,
4508 pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
4509 tag);
4510 expert_add_info(actx->pinfo, cause, &ei_ber_expected_generalized_time);
4511 if (decode_unexpected) {
4512 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
4513 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
4515 return end_offset;
4517 } else {
4518 len = tvb_length_remaining(tvb, offset);
4519 end_offset = offset+len;
4522 if ((len < 14) || (len > 23)) {
4523 cause = proto_tree_add_string_format_value(
4524 tree, hf_ber_error, tvb, offset, len, "illegal_length",
4525 "GeneralizedTime invalid length: %u",
4526 len);
4527 expert_add_info_format(actx->pinfo, cause, &ei_ber_error_length,
4528 "BER Error: GeneralizedTime invalid length");
4529 if (decode_unexpected) {
4530 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
4531 dissect_unknown_ber(actx->pinfo, tvb, offset, unknown_tree);
4533 return end_offset;
4536 tmpstr = tvb_get_string(wmem_packet_scope(), tvb, offset, len);
4537 strptr = str;
4538 /* those fields are allways present */
4539 strptr += g_snprintf(str, 20, "%.4s-%.2s-%.2s %.2s:%.2s:%.2s",
4540 tmpstr, tmpstr+4, tmpstr+6, tmpstr+8,
4541 tmpstr+10, tmpstr+12);
4543 first_delim[0] = 0;
4544 second_delim[0] = 0;
4545 ret = sscanf( tmpstr, "%14d%1[.,+-Z]%4d%1[+-Z]%4d", &tmp_int, first_delim, &first_digits, second_delim, &second_digits);
4546 /* tmp_int does not contain valid value bacause of overflow but we use it just for format checking */
4547 if (ret < 1) {
4548 cause = proto_tree_add_string_format_value(
4549 tree, hf_ber_error, tvb, offset, len, "invalid_generalized_time",
4550 "GeneralizedTime invalid format: %s",
4551 tmpstr);
4552 expert_add_info(actx->pinfo, cause, &ei_ber_invalid_format_generalized_time);
4553 if (decode_unexpected) {
4554 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
4555 dissect_unknown_ber(actx->pinfo, tvb, offset, unknown_tree);
4557 return end_offset;
4560 switch (first_delim[0]) {
4561 case '.':
4562 case ',':
4563 strptr += g_snprintf(strptr, 5, "%c%.3d", first_delim[0], first_digits);
4564 switch (second_delim[0]) {
4565 case '+':
4566 case '-':
4567 g_snprintf(strptr, 12, " (UTC%c%.4d)", second_delim[0], second_digits);
4568 break;
4569 case 'Z':
4570 g_snprintf(strptr, 7, " (UTC)");
4571 break;
4572 case 0:
4573 break;
4574 default:
4575 /* handle the malformed field */
4576 break;
4578 break;
4579 case '+':
4580 case '-':
4581 g_snprintf(strptr, 12, " (UTC%c%.4d)", first_delim[0], first_digits);
4582 break;
4583 case 'Z':
4584 g_snprintf(strptr, 7, " (UTC)");
4585 break;
4586 case 0:
4587 break;
4588 default:
4589 /* handle the malformed field */
4590 break;
4593 if (hf_id >= 0) {
4594 proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
4597 offset+=len;
4598 return offset;
4603 dissect_ber_UTCTime(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
4605 char outstr[33];
4606 char *outstrptr = outstr;
4607 const guint8 *instr;
4608 gint8 ber_class;
4609 gboolean pc;
4610 gint32 tag;
4611 guint32 len, i, n;
4612 int hoffset;
4613 proto_item *cause;
4614 proto_tree *error_tree;
4615 const gchar *error_str = NULL;
4617 if (!implicit_tag) {
4618 hoffset = offset;
4619 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
4620 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
4622 /* sanity check: we only handle UTCTime */
4623 if ( (ber_class != BER_CLASS_UNI) || (tag != BER_UNI_TAG_UTCTime) ) {
4624 tvb_ensure_bytes_exist(tvb, hoffset, 2);
4625 cause = proto_tree_add_string_format_value(
4626 tree, hf_ber_error, tvb, offset, len, "utctime_expected",
4627 "UTCTime expected but class:%s(%d) %s tag:%d was unexpected",
4628 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
4629 ber_class,
4630 pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
4631 tag);
4632 expert_add_info(actx->pinfo, cause, &ei_ber_expected_utc_time);
4633 if (decode_unexpected) {
4634 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
4635 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
4637 return offset+len;
4639 } else {
4640 len = tvb_length_remaining(tvb, offset);
4643 if ((len < 10) || (len > 19)) {
4644 error_str = wmem_strdup_printf(wmem_packet_scope(), "BER Error: UTCTime invalid length: %u", len);
4645 instr = tvb_get_string(wmem_packet_scope(), tvb, offset, len > 19 ? 19 : len);
4646 goto malformed;
4649 instr = tvb_get_string(wmem_packet_scope(), tvb, offset, len);
4651 /* YYMMDDhhmm */
4652 for (i=0; i<10; i++) {
4653 if ((instr[i] < '0') || (instr[i] > '9')) {
4654 error_str = "BER Error: malformed UTCTime encoding, "
4655 "first 10 octets have to contain YYMMDDhhmm in digits";
4656 goto malformed;
4659 g_snprintf(outstrptr, 15, "%.2s-%.2s-%.2s %.2s:%.2s", instr, instr+2, instr+4, instr+6, instr+8);
4660 outstrptr+= 14;
4662 /* (ss)? */
4663 if (len >= 12) {
4664 if ((instr[i] >= '0') && (instr[i] <= '9')) {
4665 i++;
4666 if ((instr[i] >= '0') && (instr[i] <= '9')) {
4667 i++;
4668 g_snprintf(outstrptr, 4, ":%.2s", instr+10);
4669 outstrptr+=3;
4670 } else {
4671 error_str = "BER Error: malformed UTCTime encoding, "
4672 "if 11th octet is a digit for seconds, "
4673 "the 12th octet has to be a digit, too";
4674 goto malformed;
4679 /* Z|([+-]hhmm) */
4680 switch (instr[i]) {
4681 case 'Z':
4682 if (len != (i+1)) {
4683 error_str = "BER Error: malformed UTCTime encoding, "
4684 "there must be no further octets after \'Z\'";
4685 goto malformed;
4687 g_snprintf(outstrptr, 7, " (UTC)");
4688 i++;
4689 break;
4690 case '-':
4691 case '+':
4692 if (len != (i+5)) {
4693 error_str = "BER Error: malformed UTCTime encoding, "
4694 "4 digits must follow on \'+\' resp. \'-\'";
4695 goto malformed;
4697 for (n=i+1; n<i+5; n++) {
4698 if ((instr[n] < '0') || (instr[n] > '9')) {
4699 error_str = "BER Error: malformed UTCTime encoding, "
4700 "4 digits must follow on \'+\' resp. \'-\'";
4701 goto malformed;
4704 g_snprintf(outstrptr, 12, " (UTC%c%.4s)", instr[i], instr+i+1);
4705 i+=5;
4706 break;
4707 default:
4708 error_str = wmem_strdup_printf(wmem_packet_scope(),
4709 "BER Error: malformed UTCTime encoding, "
4710 "unexpected character in %dth octet, "
4711 "must be \'Z\', \'+\' or \'-\'", i+1);
4712 goto malformed;
4713 break;
4716 if (len != i) {
4717 error_str = wmem_strdup_printf(wmem_packet_scope(),
4718 "BER Error: malformed UTCTime encoding, %d unexpected character%s after %dth octet",
4719 len - i,
4720 (len == (i - 1) ? "s" : ""),
4722 goto malformed;
4725 if (hf_id >= 0) {
4726 proto_tree_add_string(tree, hf_id, tvb, offset, len, outstr);
4729 return offset+len;
4730 malformed:
4731 if (hf_id >= 0) {
4732 cause = proto_tree_add_string(tree, hf_id, tvb, offset, len, instr);
4733 error_tree = proto_item_add_subtree(cause, ett_ber_unknown);
4734 } else {
4735 error_tree = tree;
4738 cause = proto_tree_add_string_format(
4739 error_tree, hf_ber_error, tvb, offset, len, "invalid_utctime",
4740 "%s",
4741 error_str);
4742 expert_add_info(actx->pinfo, cause, &ei_ber_invalid_format_utctime);
4744 return offset+len;
4748 /* 8.6 Encoding of a bitstring value */
4750 dissect_ber_constrained_bitstring(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, const asn_namedbit *named_bits, gint hf_id, gint ett_id, tvbuff_t **out_tvb)
4752 gint8 ber_class;
4753 gboolean pc, ind;
4754 gint32 tag;
4755 guint32 len, byteno;
4756 guint8 pad = 0, b0, b1, val, *bitstring;
4757 int end_offset;
4758 int hoffset;
4759 proto_item *item = NULL;
4760 proto_item *cause;
4761 proto_tree *tree = NULL;
4762 const char *sep;
4763 gboolean term;
4764 const asn_namedbit *nb;
4766 if (!implicit_tag) {
4767 hoffset = offset;
4768 /* read header and len for the octet string */
4769 offset = dissect_ber_identifier(actx->pinfo, parent_tree, tvb, offset, &ber_class, &pc, &tag);
4770 offset = dissect_ber_length(actx->pinfo, parent_tree, tvb, offset, &len, &ind);
4771 end_offset = offset + len;
4773 /* sanity check: we only handle Universal BitStrings */
4775 /* for an IMPLICIT APPLICATION tag asn2eth seems to call this
4776 function with implicit_tag = FALSE. BER_FLAGS_NOOWNTAG was
4777 set so the APPLICATION tag was still present.
4778 So here we relax it for APPLICATION tags. CONTEXT tags may
4779 still cause a problem. */
4781 if (!implicit_tag && (ber_class != BER_CLASS_APP)) {
4782 if ( (ber_class != BER_CLASS_UNI)
4783 || (tag != BER_UNI_TAG_BITSTRING) ) {
4784 tvb_ensure_bytes_exist(tvb, hoffset, 2);
4785 cause = proto_tree_add_string_format_value(
4786 parent_tree, hf_ber_error, tvb, offset, len, "bitstring_expected",
4787 "BitString expected but class:%s(%d) %s tag:%d was unexpected",
4788 val_to_str_const(ber_class, ber_class_codes, "Unknown"),
4789 ber_class, pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string,
4790 tag);
4791 expert_add_info(actx->pinfo, cause, &ei_ber_expected_bitstring);
4792 if (decode_unexpected) {
4793 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
4794 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
4796 return end_offset;
4799 } else {
4800 pc=0;
4801 len = tvb_length_remaining(tvb, offset);
4802 end_offset = offset+len;
4805 actx->created_item = NULL;
4807 if (pc) {
4808 /* constructed */
4809 /* TO DO */
4810 } else {
4811 /* primitive */
4812 pad = tvb_get_guint8(tvb, offset);
4813 if ((pad == 0) && (len == 1)) {
4814 /* empty */
4815 proto_tree_add_item(parent_tree, hf_ber_bitstring_empty, tvb, offset, 1, ENC_BIG_ENDIAN);
4816 } else {
4817 /* padding */
4818 proto_item *pad_item = proto_tree_add_item(parent_tree, hf_ber_bitstring_padding, tvb, offset, 1, ENC_BIG_ENDIAN);
4819 if (pad > 7) {
4820 expert_add_info_format(
4821 actx->pinfo, pad_item, &ei_ber_illegal_padding,
4822 "Illegal padding (0 .. 7): %d", pad);
4825 offset++;
4826 len--;
4827 if (hf_id >= 0) {
4828 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, ENC_BIG_ENDIAN);
4829 actx->created_item = item;
4830 if (ett_id != -1) {
4831 tree = proto_item_add_subtree(item, ett_id);
4834 if (out_tvb) {
4835 if (len <= (guint32)tvb_length_remaining(tvb, offset)) {
4836 *out_tvb = tvb_new_subset(tvb, offset, len, len);
4837 } else {
4838 *out_tvb = tvb_new_subset_remaining(tvb, offset);
4843 if (named_bits) {
4844 sep = " (";
4845 term = FALSE;
4846 nb = named_bits;
4847 bitstring = tvb_get_string(wmem_packet_scope(), tvb, offset, len);
4849 while (nb->p_id) {
4850 if ((len > 0) && (nb->bit < (8*len-pad))) {
4851 val = tvb_get_guint8(tvb, offset + nb->bit/8);
4852 bitstring[(nb->bit/8)] &= ~(0x80 >> (nb->bit%8));
4853 val &= 0x80 >> (nb->bit%8);
4854 b0 = (nb->gb0 == -1) ? nb->bit/8 :
4855 ((guint32)nb->gb0)/8;
4856 b1 = (nb->gb1 == -1) ? nb->bit/8 :
4857 ((guint32)nb->gb1)/8;
4858 proto_tree_add_item(tree, *(nb->p_id), tvb, offset + b0, b1 - b0 + 1, ENC_BIG_ENDIAN);
4859 } else { /* 8.6.2.4 */
4860 val = 0;
4861 proto_tree_add_boolean(tree, *(nb->p_id), tvb, offset + len, 0, 0x00);
4863 if (val) {
4864 if (item && nb->tstr) {
4865 proto_item_append_text(item, "%s%s", sep, nb->tstr);
4866 sep = ", ";
4867 term = TRUE;
4869 } else {
4870 if (item && nb->fstr) {
4871 proto_item_append_text(item, "%s%s", sep, nb->fstr);
4872 sep = ", ";
4873 term = TRUE;
4876 nb++;
4878 if (term)
4879 proto_item_append_text(item, ")");
4881 for (byteno = 0; byteno < len; byteno++) {
4882 if (bitstring[byteno]) {
4883 expert_add_info_format(
4884 actx->pinfo, item, &ei_ber_bits_unknown,
4885 "Unknown bit(s): 0x%s", bytes_to_str(bitstring, len));
4886 break;
4891 if ((pad > 0) && (pad < 8) && (len > 0)) {
4892 guint8 bits_in_pad = tvb_get_guint8(tvb, offset + len - 1) & (0xFF >> (8-pad));
4893 if (bits_in_pad) {
4894 expert_add_info_format(
4895 actx->pinfo, item, &ei_ber_bits_set_padded,
4896 "Bits set in padded area: 0x%02x", bits_in_pad);
4900 ber_check_length(8*len-pad, min_len, max_len, actx, item, TRUE);
4902 return end_offset;
4906 dissect_ber_bitstring(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const asn_namedbit *named_bits, gint hf_id, gint ett_id, tvbuff_t **out_tvb)
4908 return dissect_ber_constrained_bitstring(implicit_tag, actx, parent_tree, tvb, offset, -1, -1, named_bits, hf_id, ett_id, out_tvb);
4912 dissect_ber_bitstring32(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, int **bit_fields, gint hf_id, gint ett_id, tvbuff_t **out_tvb)
4914 tvbuff_t *tmp_tvb = NULL;
4915 proto_tree *tree;
4916 guint32 val;
4917 int **bf;
4918 header_field_info *hfi;
4919 const char *sep;
4920 gboolean term;
4921 unsigned int i, tvb_len;
4923 offset = dissect_ber_bitstring(implicit_tag, actx, parent_tree, tvb, offset, NULL, hf_id, ett_id, &tmp_tvb);
4925 tree = proto_item_get_subtree(actx->created_item);
4926 if (bit_fields && tree && tmp_tvb) {
4927 /* tmp_tvb points to the actual bitstring (including any pad bits at the end.
4928 * note that this bitstring is not neccessarily always encoded as 4 bytes
4929 * so we have to read it byte by byte.
4931 val = 0;
4932 tvb_len = tvb_length(tmp_tvb);
4933 for (i=0; i<4; i++) {
4934 val <<= 8;
4935 if (i < tvb_len) {
4936 val |= tvb_get_guint8(tmp_tvb, i);
4939 bf = bit_fields;
4940 sep = " (";
4941 term = FALSE;
4942 while (*bf) {
4943 if (**bf >= 0) {
4944 proto_tree_add_boolean(tree, **bf, tmp_tvb, 0, tvb_len, val);
4945 hfi = proto_registrar_get_nth(**bf);
4946 if (val & hfi->bitmask) {
4947 proto_item_append_text(actx->created_item, "%s%s", sep, hfi->name);
4948 sep = ", ";
4949 term = TRUE;
4952 bf++;
4954 if (term)
4955 proto_item_append_text(actx->created_item, ")");
4958 if (out_tvb)
4959 *out_tvb = tmp_tvb;
4961 return offset;
4965 * 8.18 Encoding of a value of the external type
4966 * 8.18.1 The encoding of a value of the external type shall be the BER encoding of the following
4967 * sequence type, assumed to be defined in an environment of EXPLICIT TAGS,
4968 * with a value as specified in the subclauses below:
4970 * [UNIVERSAL 8] IMPLICIT SEQUENCE {
4971 * direct-reference OBJECT IDENTIFIER OPTIONAL,
4972 * indirect-reference INTEGER OPTIONAL,
4973 * data-value-descriptor ObjectDescriptor OPTIONAL,
4974 * encoding CHOICE {
4975 * single-ASN1-type [0] ABSTRACT-SYNTAX.&Type,
4976 * octet-aligned [1] IMPLICIT OCTET STRING,
4977 * arbitrary [2] IMPLICIT BIT STRING } }
4981 static int
4982 dissect_ber_INTEGER(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index) {
4983 offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
4984 &actx->external.indirect_reference);
4985 actx->external.indirect_ref_present = TRUE;
4987 return offset;
4990 static int
4991 dissect_ber_T_octet_aligned(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
4993 if (actx->external.u.ber.ber_callback) {
4994 offset = actx->external.u.ber.ber_callback(FALSE, tvb, offset, actx, tree, hf_index);
4995 } else if (actx->external.direct_ref_present &&
4996 dissector_get_string_handle(ber_oid_dissector_table, actx->external.direct_reference)) {
4997 offset = call_ber_oid_callback(actx->external.direct_reference, tvb, offset, actx->pinfo, tree, NULL);
4998 } else {
4999 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index, &actx->external.octet_aligned);
5002 return offset;
5004 static int
5005 dissect_ber_OBJECT_IDENTIFIER(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index)
5007 offset = dissect_ber_object_identifier_str(implicit_tag, actx, tree, tvb, offset, hf_index, &actx->external.direct_reference);
5008 actx->external.direct_ref_present = TRUE;
5010 return offset;
5013 static int
5014 dissect_ber_ObjectDescriptor(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
5016 offset = dissect_ber_restricted_string(implicit_tag, BER_UNI_TAG_ObjectDescriptor,
5017 actx, tree, tvb, offset, hf_index,
5018 &actx->external.data_value_descriptor);
5020 return offset;
5023 static int
5024 dissect_ber_T_single_ASN1_type(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
5026 if (actx->external.u.ber.ber_callback) {
5027 offset = actx->external.u.ber.ber_callback(FALSE, tvb, offset, actx, tree, hf_index);
5028 } else {
5029 offset = call_ber_oid_callback(actx->external.direct_reference, tvb, offset, actx->pinfo, tree, NULL);
5032 return offset;
5035 static int
5036 dissect_ber_T_arbitrary(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
5038 if (actx->external.u.ber.ber_callback) {
5039 offset = actx->external.u.ber.ber_callback(FALSE, tvb, offset, actx, tree, hf_index);
5040 } else {
5041 offset = dissect_ber_bitstring(implicit_tag, actx, tree, tvb, offset,
5042 NULL, hf_index, -1, &actx->external.arbitrary);
5045 return offset;
5048 static const value_string ber_T_encoding_vals[] = {
5049 { 0, "single-ASN1-type" },
5050 { 1, "octet-aligned" },
5051 { 2, "arbitrary" },
5052 { 0, NULL }
5055 static const ber_choice_t T_encoding_choice[] = {
5056 { 0, &hf_ber_single_ASN1_type, BER_CLASS_CON, 0, 0, dissect_ber_T_single_ASN1_type },
5057 { 1, &hf_ber_octet_aligned , BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_ber_T_octet_aligned },
5058 { 2, &hf_ber_arbitrary , BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_ber_T_arbitrary },
5059 { 0, NULL, 0, 0, 0, NULL }
5063 static int
5064 dissect_ber_T_encoding(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index) {
5065 offset = dissect_ber_choice(actx, tree, tvb, offset,
5066 T_encoding_choice, hf_index, ett_ber_T_encoding,
5067 &actx->external.encoding);
5069 return offset;
5073 static const ber_sequence_t external_U_sequence[] = {
5074 { &hf_ber_direct_reference, BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ber_OBJECT_IDENTIFIER },
5075 { &hf_ber_indirect_reference, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ber_INTEGER },
5076 { &hf_ber_data_value_descriptor, BER_CLASS_UNI, BER_UNI_TAG_ObjectDescriptor, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ber_ObjectDescriptor },
5077 { &hf_ber_encoding, BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_ber_T_encoding },
5078 { NULL, 0, 0, 0, NULL }
5080 static int
5081 dissect_ber_external_U(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_ , proto_tree *tree, int hf_index _U_)
5083 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
5084 external_U_sequence, hf_index, ett_ber_EXTERNAL);
5085 return offset;
5089 dissect_ber_external_type(gboolean implicit_tag, proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, gint hf_id, ber_callback func) {
5091 actx->external.u.ber.ber_callback = func;
5093 offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
5094 hf_id, BER_CLASS_UNI, BER_UNI_TAG_EXTERNAL, TRUE, dissect_ber_external_U);
5096 asn1_ctx_clean_external(actx);
5098 return offset;
5100 /* Experimental */
5102 dissect_ber_EmbeddedPDV_Type(gboolean implicit_tag, proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, gint hf_id, ber_callback func _U_) {
5105 offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
5106 hf_id, BER_CLASS_UNI, BER_UNI_TAG_EMBEDDED_PDV, TRUE, dissect_ber_external_U);
5108 return offset;
5111 static void
5112 dissect_ber_syntax(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5114 (void) dissect_unknown_ber(pinfo, tvb, 0, tree);
5117 static void
5118 dissect_ber(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5120 const char *name;
5122 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BER");
5124 col_set_str(pinfo->cinfo, COL_DEF_SRC, "BER encoded file");
5126 if (!decode_as_syntax) {
5128 /* if we got here we couldn't find anything better */
5129 col_set_str(pinfo->cinfo, COL_INFO, "Unknown BER");
5131 (void) dissect_unknown_ber(pinfo, tvb, 0, tree);
5133 } else {
5135 (void) call_ber_syntax_callback(decode_as_syntax, tvb, 0, pinfo, tree);
5137 /* see if we have a better name */
5138 name = get_ber_oid_syntax(decode_as_syntax);
5139 col_add_fstr(pinfo->cinfo, COL_INFO, "Decoded as %s", name ? name : decode_as_syntax);
5143 gboolean
5144 oid_has_dissector(const char *oid) {
5145 return(dissector_get_string_handle(ber_oid_dissector_table, oid) != NULL);
5148 void
5149 proto_register_ber(void)
5151 static hf_register_info hf[] = {
5152 { &hf_ber_id_class, {
5153 "Class", "ber.id.class", FT_UINT8, BASE_DEC,
5154 VALS(ber_class_codes), 0xc0, "Class of BER TLV Identifier", HFILL }},
5155 { &hf_ber_bitstring_padding, {
5156 "Padding", "ber.bitstring.padding", FT_UINT8, BASE_DEC,
5157 NULL, 0x0, "Number of unused bits in the last octet of the bitstring", HFILL }},
5158 { &hf_ber_bitstring_empty, {
5159 "Empty", "ber.bitstring.empty", FT_UINT8, BASE_DEC,
5160 NULL, 0x0, "This is an empty bitstring", HFILL }},
5161 { &hf_ber_id_pc, {
5162 "P/C", "ber.id.pc", FT_BOOLEAN, 8,
5163 TFS(&ber_pc_codes), 0x20, "Primitive or Constructed BER encoding", HFILL }},
5164 { &hf_ber_id_uni_tag, {
5165 "Tag", "ber.id.uni_tag", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
5166 &ber_uni_tag_codes_ext, 0x1f, "Universal tag type", HFILL }},
5167 { &hf_ber_id_uni_tag_ext, {
5168 "Tag", "ber.id.uni_tag", FT_UINT32, BASE_DEC,
5169 NULL, 0, "Universal tag type", HFILL }},
5170 { &hf_ber_id_tag, {
5171 "Tag", "ber.id.tag", FT_UINT8, BASE_DEC,
5172 NULL, 0x1f, "Tag value for non-Universal classes", HFILL }},
5173 { &hf_ber_id_tag_ext, {
5174 "Tag", "ber.id.tag", FT_UINT32, BASE_DEC,
5175 NULL, 0, "Tag value for non-Universal classes", HFILL }},
5176 { &hf_ber_length, {
5177 "Length", "ber.length", FT_UINT32, BASE_DEC,
5178 NULL, 0, "Length of contents", HFILL }},
5179 { &hf_ber_unknown_OCTETSTRING, {
5180 "OCTETSTRING", "ber.unknown.OCTETSTRING", FT_BYTES, BASE_NONE,
5181 NULL, 0, "This is an unknown OCTETSTRING", HFILL }},
5182 { &hf_ber_unknown_BER_OCTETSTRING, {
5183 "OCTETSTRING [BER encoded]", "ber.unknown.OCTETSTRING", FT_NONE, BASE_NONE,
5184 NULL, 0, "This is an BER encoded OCTETSTRING", HFILL }},
5185 { &hf_ber_unknown_BER_primitive, {
5186 "Primitive [BER encoded]", "ber.unknown.primitive", FT_NONE, BASE_NONE,
5187 NULL, 0, "This is a BER encoded Primitive", HFILL }},
5188 { &hf_ber_unknown_OID, {
5189 "OID", "ber.unknown.OID", FT_OID, BASE_NONE,
5190 NULL, 0, "This is an unknown Object Identifier", HFILL }},
5191 { &hf_ber_unknown_GraphicString, {
5192 "GRAPHICSTRING", "ber.unknown.GRAPHICSTRING", FT_STRING, BASE_NONE,
5193 NULL, 0, "This is an unknown GRAPHICSTRING", HFILL }},
5194 { &hf_ber_unknown_NumericString, {
5195 "NumericString", "ber.unknown.NumericString", FT_STRING, BASE_NONE,
5196 NULL, 0, "This is an unknown NumericString", HFILL }},
5197 { &hf_ber_unknown_PrintableString, {
5198 "PrintableString", "ber.unknown.PrintableString", FT_STRING, BASE_NONE,
5199 NULL, 0, "This is an unknown PrintableString", HFILL }},
5200 { &hf_ber_unknown_TeletexString, {
5201 "TeletexString", "ber.unknown.TeletexString", FT_STRING, BASE_NONE,
5202 NULL, 0, "This is an unknown TeletexString", HFILL }},
5203 { &hf_ber_unknown_VisibleString, {
5204 "VisibleString", "ber.unknown.VisibleString", FT_STRING, BASE_NONE,
5205 NULL, 0, "This is an unknown VisibleString", HFILL }},
5206 { &hf_ber_unknown_GeneralString, {
5207 "GeneralString", "ber.unknown.GeneralString", FT_STRING, BASE_NONE,
5208 NULL, 0, "This is an unknown GeneralString", HFILL }},
5209 { &hf_ber_unknown_UniversalString, {
5210 "UniversalString", "ber.unknown.UniversalString", FT_STRING, BASE_NONE,
5211 NULL, 0, "This is an unknown UniversalString", HFILL }},
5212 { &hf_ber_unknown_BMPString, {
5213 "BMPString", "ber.unknown.BMPString", FT_STRING, BASE_NONE,
5214 NULL, 0, "This is an unknown BMPString", HFILL }},
5215 { &hf_ber_unknown_IA5String, {
5216 "IA5String", "ber.unknown.IA5String", FT_STRING, BASE_NONE,
5217 NULL, 0, "This is an unknown IA5String", HFILL }},
5218 { &hf_ber_unknown_UTCTime, {
5219 "UTCTime", "ber.unknown.UTCTime", FT_STRING, BASE_NONE,
5220 NULL, 0, "This is an unknown UTCTime", HFILL }},
5221 { &hf_ber_unknown_UTF8String, {
5222 "UTF8String", "ber.unknown.UTF8String", FT_STRING, BASE_NONE,
5223 NULL, 0, "This is an unknown UTF8String", HFILL }},
5224 { &hf_ber_unknown_GeneralizedTime, {
5225 "GeneralizedTime", "ber.unknown.GeneralizedTime", FT_STRING, BASE_NONE,
5226 NULL, 0, "This is an unknown GeneralizedTime", HFILL }},
5227 { &hf_ber_unknown_INTEGER, {
5228 "INTEGER", "ber.unknown.INTEGER", FT_INT64, BASE_DEC,
5229 NULL, 0, "This is an unknown INTEGER", HFILL }},
5230 { &hf_ber_unknown_BITSTRING, {
5231 "BITSTRING", "ber.unknown.BITSTRING", FT_BYTES, BASE_NONE,
5232 NULL, 0, "This is an unknown BITSTRING", HFILL }},
5233 { &hf_ber_unknown_BOOLEAN, {
5234 "BOOLEAN", "ber.unknown.BOOLEAN", FT_UINT8, BASE_HEX,
5235 NULL, 0, "This is an unknown BOOLEAN", HFILL }},
5236 { &hf_ber_unknown_ENUMERATED, {
5237 "ENUMERATED", "ber.unknown.ENUMERATED", FT_UINT32, BASE_DEC,
5238 NULL, 0, "This is an unknown ENUMERATED", HFILL }},
5239 { &hf_ber_error, {
5240 "BER Error", "ber.error", FT_STRING, BASE_NONE,
5241 NULL, 0, NULL, HFILL }},
5242 { &hf_ber_direct_reference,
5243 { "direct-reference", "ber.direct_reference",
5244 FT_OID, BASE_NONE, NULL, 0,
5245 "ber.OBJECT_IDENTIFIER", HFILL }},
5246 { &hf_ber_indirect_reference,
5247 { "indirect-reference", "ber.indirect_reference",
5248 FT_INT32, BASE_DEC, NULL, 0,
5249 "ber.INTEGER", HFILL }},
5250 { &hf_ber_data_value_descriptor,
5251 { "data-value-descriptor", "ber.data_value_descriptor",
5252 FT_STRING, BASE_NONE, NULL, 0,
5253 "ber.ObjectDescriptor", HFILL }},
5254 { &hf_ber_encoding,
5255 { "encoding", "ber.encoding",
5256 FT_UINT32, BASE_DEC, VALS(ber_T_encoding_vals), 0,
5257 "ber.T_encoding", HFILL }},
5258 { &hf_ber_octet_aligned,
5259 { "octet-aligned", "ber.octet_aligned",
5260 FT_BYTES, BASE_NONE, NULL, 0,
5261 "ber.T_octet_aligned", HFILL }},
5262 { &hf_ber_arbitrary,
5263 { "arbitrary", "ber.arbitrary",
5264 FT_BYTES, BASE_NONE, NULL, 0,
5265 "ber.T_arbitrary", HFILL }},
5266 { &hf_ber_single_ASN1_type,
5267 { "single-ASN1-type", "ber.single_ASN1_type",
5268 FT_NONE, BASE_NONE, NULL, 0,
5269 "ber.T_single_ASN1_type", HFILL }},
5271 /* Fragment entries */
5272 { &hf_ber_fragments,
5273 { "OCTET STRING fragments", "ber.octet_string.fragments", FT_NONE, BASE_NONE,
5274 NULL, 0x00, NULL, HFILL } },
5275 { &hf_ber_fragment,
5276 { "OCTET STRING fragment", "ber.octet_string.fragment", FT_FRAMENUM, BASE_NONE,
5277 NULL, 0x00, NULL, HFILL } },
5278 { &hf_ber_fragment_overlap,
5279 { "OCTET STRING fragment overlap", "ber.octet_string.fragment.overlap", FT_BOOLEAN,
5280 BASE_NONE, NULL, 0x0, NULL, HFILL } },
5281 { &hf_ber_fragment_overlap_conflicts,
5282 { "OCTET STRING fragment overlapping with conflicting data",
5283 "ber.octet_string.fragment.overlap.conflicts", FT_BOOLEAN, BASE_NONE, NULL,
5284 0x0, NULL, HFILL } },
5285 { &hf_ber_fragment_multiple_tails,
5286 { "OCTET STRING has multiple tail fragments",
5287 "ber.octet_string.fragment.multiple_tails", FT_BOOLEAN, BASE_NONE,
5288 NULL, 0x0, NULL, HFILL } },
5289 { &hf_ber_fragment_too_long_fragment,
5290 { "OCTET STRING fragment too long", "ber.octet_string.fragment.too_long_fragment",
5291 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL,
5292 HFILL } },
5293 { &hf_ber_fragment_error,
5294 { "OCTET STRING defragmentation error", "ber.octet_string.fragment.error", FT_FRAMENUM,
5295 BASE_NONE, NULL, 0x00, NULL, HFILL } },
5296 { &hf_ber_fragment_count,
5297 { "OCTET STRING fragment count", "ber.octet_string.fragment.count", FT_UINT32, BASE_DEC,
5298 NULL, 0x00, NULL, HFILL } },
5299 { &hf_ber_reassembled_in,
5300 { "Reassembled in", "ber.octet_string.reassembled.in", FT_FRAMENUM, BASE_NONE,
5301 NULL, 0x00, NULL, HFILL } },
5302 { &hf_ber_reassembled_length,
5303 { "Reassembled OCTET STRING length", "ber.octet_string.reassembled.length", FT_UINT32, BASE_DEC,
5304 NULL, 0x00, NULL, HFILL } }
5308 static gint *ett[] = {
5309 &ett_ber_octet_string,
5310 &ett_ber_reassembled_octet_string,
5311 &ett_ber_primitive,
5312 &ett_ber_unknown,
5313 &ett_ber_SEQUENCE,
5314 &ett_ber_EXTERNAL,
5315 &ett_ber_T_encoding,
5316 &ett_ber_fragment,
5317 &ett_ber_fragments
5319 static ei_register_info ei[] = {
5320 { &ei_ber_size_constraint_string, { "ber.size_constraint.string", PI_PROTOCOL, PI_WARN, "Size constraint: string", EXPFILL }},
5321 { &ei_ber_size_constraint_value, { "ber.size_constraint.value", PI_PROTOCOL, PI_WARN, "Size constraint: values", EXPFILL }},
5322 { &ei_ber_size_constraint_items, { "ber.size_constraint.items", PI_PROTOCOL, PI_WARN, "Size constraint: items", EXPFILL }},
5323 { &ei_ber_sequence_field_wrong, { "ber.error.sequence.field_wrong", PI_MALFORMED, PI_WARN, "BER Error: Wrong field in SEQUENCE", EXPFILL }},
5324 { &ei_ber_expected_octet_string, { "ber.error.expected.octet_string", PI_MALFORMED, PI_WARN, "BER Error: OctetString expected", EXPFILL }},
5325 { &ei_ber_expected_null, { "ber.error.expected.null", PI_MALFORMED, PI_WARN, "BER Error: NULL expected", EXPFILL }},
5326 { &ei_ber_expected_null_zero_length, { "ber.error.expected.null_zero_length", PI_MALFORMED, PI_WARN, "BER Error: NULL expect zero length", EXPFILL }},
5327 { &ei_ber_expected_sequence, { "ber.error.expected.sequence", PI_MALFORMED, PI_WARN, "BER Error: Sequence expected", EXPFILL }},
5328 { &ei_ber_expected_set, { "ber.error.expected.set", PI_MALFORMED, PI_WARN, "BER Error: SET expected", EXPFILL }},
5329 { &ei_ber_expected_string, { "ber.error.expected.string", PI_MALFORMED, PI_WARN, "BER Error: String expected", EXPFILL }},
5330 { &ei_ber_expected_object_identifier, { "ber.error.expected.object_identifier", PI_MALFORMED, PI_WARN, "BER Error: Object Identifier expected", EXPFILL }},
5331 { &ei_ber_expected_generalized_time, { "ber.error.expected.generalized_time", PI_MALFORMED, PI_WARN, "BER Error: GeneralizedTime expected", EXPFILL }},
5332 { &ei_ber_expected_utc_time, { "ber.error.expected.utc_time", PI_MALFORMED, PI_WARN, "BER Error: UTCTime expected", EXPFILL }},
5333 { &ei_ber_expected_bitstring, { "ber.error.expected.bitstring", PI_MALFORMED, PI_WARN, "BER Error: BitString expected", EXPFILL }},
5334 { &ei_ber_error_length, { "ber.error.length", PI_MALFORMED, PI_WARN, "BER Error length", EXPFILL }},
5335 { &ei_ber_wrong_tag_in_tagged_type, { "ber.error.wrong_tag_in_tagged_type", PI_MALFORMED, PI_WARN, "BER Error: Wrong tag in tagged type", EXPFILL }},
5336 { &ei_ber_universal_tag_unknown, { "ber.error.universal_tag_unknown", PI_MALFORMED, PI_WARN, "BER Error: can not handle universal", EXPFILL }},
5337 { &ei_ber_no_oid, { "ber.error.no_oid", PI_MALFORMED, PI_WARN, "BER Error: No OID supplied to call_ber_oid_callback", EXPFILL }},
5338 { &ei_ber_oid_not_implemented, { "ber.error.oid_not_implemented", PI_UNDECODED, PI_WARN, "BER: Dissector for OID not implemented. Contact Wireshark developers if you want this supported", EXPFILL }},
5339 { &ei_ber_syntax_not_implemented, { "ber.error.syntax_not_implemented", PI_UNDECODED, PI_WARN, "BER: Syntax not implemented", EXPFILL }},
5340 { &ei_ber_value_too_many_bytes, { "ber.error.value_too_many_bytes", PI_MALFORMED, PI_WARN, "Value is encoded with too many bytes", EXPFILL }},
5341 { &ei_ber_unknown_field_sequence, { "ber.error.unknown_field.sequence", PI_MALFORMED, PI_WARN, "BER Error: Unknown field in Sequence", EXPFILL }},
5342 { &ei_ber_unknown_field_set, { "ber.error.unknown_field.set", PI_MALFORMED, PI_WARN, "BER Error: Unknown field in SET", EXPFILL }},
5343 { &ei_ber_missing_field_set, { "ber.error.missing_field.set", PI_MALFORMED, PI_WARN, "BER Error: Missing field in SET", EXPFILL }},
5344 { &ei_ber_empty_choice, { "ber.error.empty_choice", PI_MALFORMED, PI_WARN, "BER Error: Empty choice was found", EXPFILL }},
5345 { &ei_ber_choice_not_found, { "ber.error.choice_not_found", PI_MALFORMED, PI_WARN, "BER Error: This choice field was not found", EXPFILL }},
5346 { &ei_ber_bits_unknown, { "ber.error.bits_unknown", PI_UNDECODED, PI_WARN, "BER Error: Bits unknown", EXPFILL }},
5347 { &ei_ber_bits_set_padded, { "ber.error.bits_set_padded", PI_UNDECODED, PI_WARN, "BER Error: Bits set in padded area", EXPFILL }},
5348 { &ei_ber_illegal_padding, { "ber.error.illegal_padding", PI_UNDECODED, PI_WARN, "Illegal padding", EXPFILL }},
5349 { &ei_ber_invalid_format_generalized_time, { "ber.error.invalid_format.generalized_time", PI_MALFORMED, PI_WARN, "BER Error: GeneralizedTime invalid format", EXPFILL }},
5350 { &ei_ber_invalid_format_utctime, { "ber.error.invalid_format.utctime", PI_MALFORMED, PI_WARN, "BER Error: malformed UTCTime encoding", EXPFILL }},
5353 module_t *ber_module;
5354 expert_module_t* expert_ber;
5355 uat_t* users_uat = uat_new("OID Tables",
5356 sizeof(oid_user_t),
5357 "oid",
5358 FALSE,
5359 (void**) &oid_users,
5360 &num_oid_users,
5361 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
5362 "ChObjectIdentifiers",
5363 oid_copy_cb,
5364 NULL,
5365 oid_free_cb,
5366 ber_update_oids,
5367 users_flds);
5369 proto_ber = proto_register_protocol("Basic Encoding Rules (ASN.1 X.690)", "BER", "ber");
5371 ber_handle = register_dissector("ber", dissect_ber, proto_ber);
5373 proto_register_field_array(proto_ber, hf, array_length(hf));
5374 proto_register_subtree_array(ett, array_length(ett));
5375 expert_ber = expert_register_protocol(proto_ber);
5376 expert_register_field_array(expert_ber, ei, array_length(ei));
5378 proto_set_cant_toggle(proto_ber);
5380 /* Register preferences */
5381 ber_module = prefs_register_protocol(proto_ber, NULL);
5383 prefs_register_bool_preference(ber_module, "show_internals",
5384 "Show internal BER encapsulation tokens",
5385 "Whether the dissector should also display internal"
5386 " ASN.1 BER details such as Identifier and Length fields", &show_internal_ber_fields);
5387 prefs_register_bool_preference(ber_module, "decode_unexpected",
5388 "Decode unexpected tags as BER encoded data",
5389 "Whether the dissector should decode unexpected tags as"
5390 " ASN.1 BER encoded data", &decode_unexpected);
5391 prefs_register_bool_preference(ber_module, "decode_octetstring",
5392 "Decode OCTET STRING as BER encoded data",
5393 "Whether the dissector should try decoding OCTET STRINGs as"
5394 " constructed ASN.1 BER encoded data", &decode_octetstring_as_ber);
5396 prefs_register_bool_preference(ber_module, "decode_primitive",
5397 "Decode Primitive as BER encoded data",
5398 "Whether the dissector should try decoding unknown primitive as"
5399 " constructed ASN.1 BER encoded data", &decode_primitive_as_ber);
5401 prefs_register_bool_preference(ber_module, "warn_too_many_bytes",
5402 "Warn if too many leading zero bits in encoded data",
5403 "Whether the dissector should warn if excessive leading zero (0) bits",
5404 &decode_warning_leading_zero_bits);
5406 prefs_register_uat_preference(ber_module, "oid_table", "Object Identifiers",
5407 "A table that provides names for object identifiers"
5408 " and the syntax of any associated values",
5409 users_uat);
5411 ber_oid_dissector_table = register_dissector_table("ber.oid", "BER OID Dissectors", FT_STRING, BASE_NONE);
5412 ber_syntax_dissector_table = register_dissector_table("ber.syntax", "BER Syntax Dissectors", FT_STRING, BASE_NONE);
5413 syntax_table = g_hash_table_new(g_str_hash, g_str_equal); /* oid to syntax */
5415 register_ber_syntax_dissector("ASN.1", proto_ber, dissect_ber_syntax);
5417 register_init_routine(ber_defragment_init);
5420 void
5421 proto_reg_handoff_ber(void)
5423 guint i = 1;
5425 oid_add_from_string("asn1", "2.1");
5426 oid_add_from_string("basic-encoding", "2.1.1");
5428 dissector_add_uint("wtap_encap", WTAP_ENCAP_BER, ber_handle);
5430 ber_decode_as_foreach(ber_add_syntax_name, &i);
5432 if (i > 1)
5433 qsort(&syntax_names[1], i - 1, sizeof(value_string), cmp_value_string);
5434 syntax_names[i].value = 0;
5435 syntax_names[i].strptr = NULL;
5437 /* allow the dissection of BER/DER carried over a TCP transport
5438 by using "Decode As..." */
5439 dissector_add_handle("tcp.port", ber_handle);
5441 ber_update_oids();