1 /*#define DEBUG_BER 1*/
2 /* TODO: change #.REGISTER signature to new_dissector_t and
3 * update call_ber_oid_callback() accordingly.
5 * Since we don't pass the TAG/LENGTH from the CHOICE/SEQUENCE/SEQUENCE OF/
6 * SET OF helpers through the callbacks to the next pabket-ber helper
7 * when the tags are IMPLICIT, this causes a problem when we also have
8 * indefinite length at the same time as the tags are implicit.
10 * While the proper fix is to change the signatures for packet-ber.c helpers
11 * as well as the signatures for the callbacks to include the indefinite length
12 * indication that would be a major job.
14 * Originally we used a kludge - we set a global variable in the
15 * CHOICE/SEQUENCE [OF]/SET [OF] helpers to indicate to the next helper
16 * whether the length is indefinite or not.
17 * That had currently only been implemented for {SEQUENCE|SET} [OF] but not
20 * This version attacks the problem(s) in a different way. If we see
21 * indefinite length the get_ber_length traverses the tags within the
22 * compound value and then we return the true length of the compound value
23 * including the EOC. Thus the tvb length is now always correct even for
24 * indefinite length, then if we get implicit tags they can be handled as
25 * if they were definite length.
29 * Helpers for ASN.1/BER dissection
30 * Ronnie Sahlberg (C) 2004
34 * Wireshark - Network traffic analyzer
35 * By Gerald Combs <gerald@wireshark.org>
36 * Copyright 1998 Gerald Combs
38 * This program is free software; you can redistribute it and/or
39 * modify it under the terms of the GNU General Public License
40 * as published by the Free Software Foundation; either version 2
41 * of the License, or (at your option) any later version.
43 * This program is distributed in the hope that it will be useful,
44 * but WITHOUT ANY WARRANTY; without even the implied warranty of
45 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46 * GNU General Public License for more details.
48 * You should have received a copy of the GNU General Public License
49 * along with this program; if not, write to the Free Software
50 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
54 * ITU-T Recommendation X.690 (07/2002),
55 * Information technology ASN.1 encoding rules:
56 * Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)
70 #include <epan/packet.h>
72 #include <epan/strutil.h>
73 #include <epan/to_str.h>
74 #include <epan/prefs.h>
75 #include <epan/reassemble.h>
76 #include <epan/oids.h>
77 #include <epan/expert.h>
78 #include <epan/asn1.h>
79 #include "packet-ber.h"
81 static gint proto_ber = -1;
82 static gint hf_ber_id_class = -1;
83 static gint hf_ber_id_pc = -1;
84 static gint hf_ber_id_uni_tag = -1;
85 static gint hf_ber_id_uni_tag_ext = -1;
86 static gint hf_ber_id_tag = -1;
87 static gint hf_ber_id_tag_ext = -1;
88 static gint hf_ber_length = -1;
89 static gint hf_ber_bitstring_padding = -1;
90 static gint hf_ber_bitstring_empty = -1;
91 static gint hf_ber_unknown_OID = -1;
92 static gint hf_ber_unknown_BOOLEAN = -1;
93 static gint hf_ber_unknown_OCTETSTRING = -1;
94 static gint hf_ber_unknown_BER_OCTETSTRING = -1;
95 static gint hf_ber_unknown_GraphicString = -1;
96 static gint hf_ber_unknown_NumericString = -1;
97 static gint hf_ber_unknown_PrintableString = -1;
98 static gint hf_ber_unknown_TeletexString = -1;
99 static gint hf_ber_unknown_VisibleString = -1;
100 static gint hf_ber_unknown_GeneralString = -1;
101 static gint hf_ber_unknown_UniversalString = -1;
102 static gint hf_ber_unknown_BMPString = -1;
103 static gint hf_ber_unknown_IA5String = -1;
104 static gint hf_ber_unknown_UTCTime = -1;
105 static gint hf_ber_unknown_UTF8String = -1;
106 static gint hf_ber_unknown_GeneralizedTime = -1;
107 static gint hf_ber_unknown_INTEGER = -1;
108 static gint hf_ber_unknown_BITSTRING = -1;
109 static gint hf_ber_unknown_ENUMERATED = -1;
110 static gint hf_ber_constructed_OCTETSTRING = -1;
111 static gint hf_ber_no_oid = -1;
112 static gint hf_ber_oid_not_implemented = -1;
113 static gint hf_ber_direct_reference = -1; /* OBJECT_IDENTIFIER */
114 static gint hf_ber_indirect_reference = -1; /* INTEGER */
115 static gint hf_ber_data_value_descriptor = -1; /* ObjectDescriptor */
116 static gint hf_ber_encoding = -1; /* T_encoding */
117 static gint hf_ber_single_ASN1_type = -1; /* T_single_ASN1_type */
118 static gint hf_ber_octet_aligned = -1; /* OCTET_STRING */
119 static gint hf_ber_arbitrary = -1; /* BIT_STRING */
121 static gint ett_ber_octet_string = -1;
122 static gint ett_ber_unknown = -1;
123 static gint ett_ber_SEQUENCE = -1;
124 static gint ett_ber_EXTERNAL = -1;
125 static gint ett_ber_T_encoding = -1;
127 static gboolean show_internal_ber_fields = FALSE;
128 static gboolean decode_octetstring_as_ber = FALSE;
129 static gboolean decode_unexpected = FALSE;
131 static gchar *decode_as_syntax = NULL;
132 static gchar *ber_filename = NULL;
134 static dissector_table_t ber_oid_dissector_table=NULL;
135 static dissector_table_t ber_syntax_dissector_table=NULL;
136 static GHashTable *syntax_table=NULL;
138 static const value_string ber_class_codes[] = {
139 { BER_CLASS_UNI, "UNIVERSAL" },
140 { BER_CLASS_APP, "APPLICATION" },
141 { BER_CLASS_CON, "CONTEXT" },
142 { BER_CLASS_PRI, "PRIVATE" },
146 static const true_false_string ber_pc_codes = {
147 "Constructed Encoding",
151 static const true_false_string ber_pc_codes_short = {
156 static const value_string ber_uni_tag_codes[] = {
157 { BER_UNI_TAG_EOC, "'end-of-content'" },
158 { BER_UNI_TAG_BOOLEAN, "BOOLEAN" },
159 { BER_UNI_TAG_INTEGER, "INTEGER" },
160 { BER_UNI_TAG_BITSTRING, "BIT STRING" },
161 { BER_UNI_TAG_OCTETSTRING, "OCTET STRING" },
162 { BER_UNI_TAG_NULL, "NULL" },
163 { BER_UNI_TAG_OID, "OBJECT IDENTIFIER" },
164 { BER_UNI_TAG_ObjectDescriptor, "ObjectDescriptor" },
165 { BER_UNI_TAG_EXTERNAL, "EXTERNAL" },
166 { BER_UNI_TAG_REAL, "REAL" },
167 { BER_UNI_TAG_ENUMERATED, "ENUMERATED" },
168 { BER_UNI_TAG_EMBEDDED_PDV, "EMBEDDED PDV" },
169 { BER_UNI_TAG_UTF8String, "UTF8String" },
170 { BER_UNI_TAG_RELATIVE_OID, "RELATIVE-OID" },
172 * Reserved for future editions of this
173 * Recommendation | International Standard
175 { BER_UNI_TAG_SEQUENCE, "SEQUENCE" },
176 { BER_UNI_TAG_SET, "SET" },
177 { BER_UNI_TAG_NumericString, "NumericString" },
178 { BER_UNI_TAG_PrintableString, "PrintableString" },
179 { BER_UNI_TAG_TeletexString, "TeletexString, T61String" },
180 { BER_UNI_TAG_VideotexString, "VideotexString" },
181 { BER_UNI_TAG_IA5String, "IA5String" },
182 { BER_UNI_TAG_UTCTime, "UTCTime" },
183 { BER_UNI_TAG_GeneralizedTime, "GeneralizedTime" },
184 { BER_UNI_TAG_GraphicString, "GraphicString" },
185 { BER_UNI_TAG_VisibleString, "VisibleString, ISO64String" },
186 { BER_UNI_TAG_GeneralString, "GeneralString" },
187 { BER_UNI_TAG_UniversalString, "UniversalString" },
188 { BER_UNI_TAG_CHARACTERSTRING, "CHARACTER STRING" },
189 { BER_UNI_TAG_BMPString, "BMPString" },
194 static const true_false_string ber_real_binary_vals = {
199 static const true_false_string ber_real_decimal_vals = {
204 typedef struct _da_data {
211 dissect_ber_oid_NULL_callback(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_)
218 register_ber_oid_dissector_handle(const char *oid, dissector_handle_t dissector, int proto _U_, const char *name)
220 dissector_add_string("ber.oid", oid, dissector);
221 oid_add_from_string(name, oid);
225 register_ber_oid_dissector(const char *oid, dissector_t dissector, int proto, const char *name)
227 dissector_handle_t dissector_handle;
229 dissector_handle=create_dissector_handle(dissector, proto);
230 dissector_add_string("ber.oid", oid, dissector_handle);
231 oid_add_from_string(name, oid);
235 register_ber_syntax_dissector(const char *syntax, int proto, dissector_t dissector)
237 dissector_handle_t dissector_handle;
239 dissector_handle=create_dissector_handle(dissector, proto);
240 dissector_add_string("ber.syntax", syntax, dissector_handle);
245 register_ber_oid_syntax(const char *oid, const char *name, const char *syntax)
248 if(syntax && *syntax)
249 g_hash_table_insert(syntax_table, (const gpointer)oid, (const gpointer)syntax);
252 register_ber_oid_name(oid, name);
255 /* Register the oid name to get translation in proto dissection */
257 register_ber_oid_name(const char *oid, const char *name)
259 oid_add_from_string(name, oid);
262 static void ber_decode_as_dt(const gchar *table_name _U_, ftenum_t selector_type _U_, gpointer key, gpointer value, gpointer user_data)
264 da_data *decode_as_data;
266 decode_as_data = (da_data *)user_data;
268 decode_as_data->func(key, value, decode_as_data->user_data);
271 void ber_decode_as_foreach(GHFunc func, gpointer user_data)
273 da_data decode_as_data;
275 decode_as_data.func = func;
276 decode_as_data.user_data = user_data;
278 dissector_table_foreach("ber.syntax", ber_decode_as_dt, &decode_as_data);
282 void ber_decode_as(const gchar *syntax)
285 if(decode_as_syntax) {
286 g_free(decode_as_syntax);
287 decode_as_syntax = NULL;
291 decode_as_syntax = g_strdup(syntax);
294 /* Get oid syntax from hash table to get translation in proto dissection(packet-per.c) */
296 get_ber_oid_syntax(const char *oid)
298 return g_hash_table_lookup(syntax_table, oid);
301 void ber_set_filename(gchar *filename)
306 g_free(ber_filename);
312 ber_filename = g_strdup(filename);
314 if((ptr = strrchr(ber_filename, '.')) != NULL) {
316 ber_decode_as(get_ber_oid_syntax(ptr));
322 int dissect_ber_tagged_type(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gint8 tag_cls, gint32 tag_tag, gboolean tag_impl, ber_type_fn type)
327 tvbuff_t *next_tvb = tvb;
333 header_field_info *hfinfo;
335 hfinfo = proto_registrar_get_nth(hf_id);
340 if(tvb_length_remaining(tvb,offset)>3){
341 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));
343 printf("dissect_ber_tagged_type(%s) entered\n",name);
349 offset = type(tag_impl, tvb, offset, actx, tree, hf_id);
353 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &tmp_cls, NULL, &tmp_tag);
354 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &tmp_len, NULL);
356 if ((tmp_cls != tag_cls) || (tmp_tag != tag_tag)) {
357 cause = proto_tree_add_text(tree, tvb, offset, tmp_len,
358 "BER Error: Wrong tag in tagged type - expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
359 val_to_str(tag_cls, ber_class_codes, "Unknown"), tag_cls, tag_tag, val_to_str(tag_tag, ber_uni_tag_codes,"Unknown"),
360 val_to_str(tmp_cls, ber_class_codes, "Unknown"), tmp_cls, tmp_tag);
361 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
362 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong tag in tagged type");
366 next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tmp_len);
367 type(tag_impl, next_tvb, 0, actx, tree, hf_id);
370 offset = type(tag_impl, tvb, offset, actx, tree, hf_id);
376 int dissect_unknown_ber(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree)
384 proto_item *item=NULL;
385 proto_tree *next_tree=NULL;
388 gboolean is_printable;
389 proto_item *pi, *cause;
393 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
395 offset=get_ber_identifier(tvb, offset, &class, &pc, &tag);
396 offset=get_ber_length(tvb, offset, &len, &ind);
398 if(len>(guint32)tvb_length_remaining(tvb, offset)){
399 /* hmm maybe something bad happened or the frame is short,
400 since these are not vital outputs just return instead of
401 throwing an exception.
404 if(show_internal_ber_fields) {
405 offset=dissect_ber_identifier(pinfo, tree, tvb, start_offset, &class, &pc, &tag);
406 offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
408 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: length:%u longer than tvb_length_ramaining:%d",len, tvb_length_remaining(tvb, offset));
409 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
410 expert_add_info_format(pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error length");
411 return tvb_length(tvb);
413 /* we dont care about the class only on the constructor flag */
416 case FALSE: /* this is not constructed */
418 switch(class) { /* we do care about the class */
419 case BER_CLASS_UNI: /* it a Universal tag - we can decode it */
421 case BER_UNI_TAG_EOC:
422 /* XXX: shouldn't really get here */
424 case BER_UNI_TAG_INTEGER:
425 offset = dissect_ber_integer(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_INTEGER, NULL);
427 case BER_UNI_TAG_BITSTRING:
428 offset = dissect_ber_bitstring(FALSE, &asn1_ctx, tree, tvb, start_offset, NULL, hf_ber_unknown_BITSTRING, -1, NULL);
430 case BER_UNI_TAG_ENUMERATED:
431 offset = dissect_ber_integer(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_ENUMERATED, NULL);
433 case BER_UNI_TAG_GraphicString:
434 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_GraphicString, NULL);
436 case BER_UNI_TAG_OCTETSTRING:
437 if (decode_octetstring_as_ber) {
440 ber_offset = get_ber_identifier(tvb, offset, NULL, &pc, NULL);
441 ber_offset = get_ber_length(tvb, ber_offset, &ber_len, NULL);
442 if (pc && (ber_len + (ber_offset - offset) == len)) {
443 /* Decoded a constructed ASN.1 tag with a length indicating this
444 * could be BER encoded data. Try dissecting as unknown BER.
446 if (show_internal_ber_fields) {
447 offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, NULL, NULL, NULL);
448 offset = dissect_ber_length(pinfo, tree, tvb, offset, NULL, NULL);
450 item = proto_tree_add_item(tree, hf_ber_unknown_BER_OCTETSTRING, tvb, offset, len, FALSE);
451 next_tree = proto_item_add_subtree(item, ett_ber_octet_string);
452 offset = dissect_unknown_ber(pinfo, tvb, offset, next_tree);
454 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_OCTETSTRING, NULL);
457 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_OCTETSTRING, NULL);
460 case BER_UNI_TAG_OID:
461 offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_OID, NULL);
463 case BER_UNI_TAG_NumericString:
464 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_NumericString, NULL);
466 case BER_UNI_TAG_PrintableString:
467 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_PrintableString, NULL);
469 case BER_UNI_TAG_TeletexString:
470 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_TeletexString, NULL);
472 case BER_UNI_TAG_VisibleString:
473 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_VisibleString, NULL);
475 case BER_UNI_TAG_GeneralString:
476 offset = dissect_ber_GeneralString(&asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_GeneralString, NULL, 0);
478 case BER_UNI_TAG_BMPString:
479 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_BMPString, NULL);
481 case BER_UNI_TAG_UniversalString:
482 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_UniversalString, NULL);
484 case BER_UNI_TAG_IA5String:
485 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_IA5String, NULL);
487 case BER_UNI_TAG_UTCTime:
488 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_UTCTime, NULL);
490 case BER_UNI_TAG_NULL:
491 proto_tree_add_text(tree, tvb, offset, len, "NULL tag");
493 case BER_UNI_TAG_UTF8String:
494 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_UTF8String, NULL);
496 case BER_UNI_TAG_GeneralizedTime:
497 offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_GeneralizedTime, NULL);
499 case BER_UNI_TAG_BOOLEAN:
500 offset = dissect_ber_boolean(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_BOOLEAN, NULL);
503 offset=dissect_ber_identifier(pinfo, tree, tvb, start_offset, &class, &pc, &tag);
504 offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
505 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: can not handle universal tag:%d",tag);
506 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
507 expert_add_info_format(pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: can not handle universal");
515 /* we can't dissect this directly as it is specific */
517 /* we dissect again if show_internal_ber_fields is set */
518 if(show_internal_ber_fields) {
519 offset=dissect_ber_identifier(pinfo, tree, tvb, start_offset, &class, &pc, &tag);
520 offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
523 pi = proto_tree_add_text(tree, tvb, offset, len, "[%s %d] ", val_to_str(class,ber_class_codes,"Unknown"), tag);
524 /* we may want to do better and show the bytes */
527 c = tvb_get_guint8(tvb, offset+i);
529 if(is_printable && !g_ascii_isprint(c))
532 proto_item_append_text(pi,"%02x",c);
535 if(is_printable) { /* give a nicer representation if it looks like a string */
536 proto_item_append_text(pi," (");
538 proto_item_append_text(pi,"%c",tvb_get_guint8(tvb, offset+i));
540 proto_item_append_text(pi,")");
548 case TRUE: /* this is constructed */
550 /* we dissect again if show_internal_ber_fields is set */
551 if(show_internal_ber_fields) {
552 offset=dissect_ber_identifier(pinfo, tree, tvb, start_offset, &class, &pc, &tag);
553 offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
556 hdr_len=offset-start_offset;
560 item=proto_tree_add_text(tree, tvb, offset, len, "%s", val_to_str(tag,ber_uni_tag_codes,"Unknown"));
562 next_tree=proto_item_add_subtree(item, ett_ber_SEQUENCE);
564 while(offset < (int)(start_offset + len + hdr_len))
565 offset=dissect_unknown_ber(pinfo, tvb, offset, next_tree);
571 item=proto_tree_add_text(tree, tvb, offset, len, "[%s %d]", val_to_str(class,ber_class_codes,"Unknown"), tag);
573 next_tree=proto_item_add_subtree(item, ett_ber_SEQUENCE);
575 while(offset < (int)(start_offset + len + hdr_len))
576 offset=dissect_unknown_ber(pinfo, tvb, offset, next_tree);
589 call_ber_oid_callback(const char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
593 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
595 !dissector_try_string(ber_oid_dissector_table, oid, next_tvb, pinfo, tree)){
596 proto_item *item=NULL;
597 proto_tree *next_tree=NULL;
598 gint length_remaining;
600 length_remaining = tvb_length_remaining(tvb, offset);
603 item=proto_tree_add_none_format(tree, hf_ber_no_oid, next_tvb, 0, length_remaining, "BER: No OID supplied to call_ber_oid_callback");
604 proto_item_set_expert_flags(item, PI_MALFORMED, PI_WARN);
605 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_WARN, "BER Error: No OID supplied");
607 item=proto_tree_add_none_format(tree, hf_ber_oid_not_implemented, next_tvb, 0, length_remaining, "BER: Dissector for OID:%s not implemented. Contact Wireshark developers if you want this supported", oid);
608 proto_item_set_expert_flags(item, PI_MALFORMED, PI_WARN);
609 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_WARN, "BER Error Dissector for OID not implemented");
611 if (decode_unexpected) {
616 next_tree=proto_item_add_subtree(item, ett_ber_unknown);
618 ber_offset = get_ber_identifier(next_tvb, 0, NULL, NULL, NULL);
619 ber_offset = get_ber_length(next_tvb, ber_offset, &ber_len, NULL);
620 if ((ber_len + ber_offset) == length_remaining) {
621 /* Decoded an ASN.1 tag with a length indicating this
622 * could be BER encoded data. Try dissecting as unknown BER.
624 dissect_unknown_ber(pinfo, next_tvb, 0, next_tree);
626 proto_tree_add_text(next_tree, next_tvb, 0, length_remaining,
627 "Unknown Data (%d byte%s)", length_remaining,
628 plurality(length_remaining, "", "s"));
634 /*XXX until we change the #.REGISTER signature for _PDU()s
635 * into new_dissector_t we have to do this kludge with
636 * manually step past the content in the ANY type.
638 offset+=tvb_length_remaining(tvb, offset);
644 call_ber_syntax_callback(const char *syntax, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
648 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
650 !dissector_try_string(ber_syntax_dissector_table, syntax, next_tvb, pinfo, tree)){
651 proto_item *item=NULL;
652 proto_tree *next_tree=NULL;
655 item=proto_tree_add_none_format(tree, hf_ber_no_oid, next_tvb, 0, tvb_length_remaining(tvb, offset), "BER: No syntax supplied to call_ber_syntax_callback");
657 item=proto_tree_add_none_format(tree, hf_ber_oid_not_implemented, next_tvb, 0, tvb_length_remaining(tvb, offset), "BER: Dissector for syntax: %s not implemented. Contact Wireshark developers if you want this supported", syntax);
659 next_tree=proto_item_add_subtree(item, ett_ber_unknown);
661 dissect_unknown_ber(pinfo, next_tvb, 0, next_tree);
664 /*XXX until we change the #.REGISTER signature for _PDU()s
665 * into new_dissector_t we have to do this kludge with
666 * manually step past the content in the ANY type.
668 offset+=tvb_length_remaining(tvb, offset);
673 static int dissect_ber_sq_of(gboolean implicit_tag, gint32 type, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id);
674 static int 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);
676 /* 8.1 General rules for encoding */
678 /* 8.1.2 Identifier octets */
679 int get_ber_identifier(tvbuff_t *tvb, int offset, gint8 *class, gboolean *pc, gint32 *tag) {
685 id = tvb_get_guint8(tvb, offset);
688 printf ("BER ID=%02x", id);
691 tmp_class = (id>>6) & 0x03;
692 tmp_pc = (id>>5) & 0x01;
695 if (tmp_tag == 0x1F) {
697 while (tvb_length_remaining(tvb, offset) > 0) {
698 t = tvb_get_guint8(tvb, offset);
705 if (!(t & 0x80)) break;
722 int dissect_ber_identifier(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gint8 *class, gboolean *pc, gint32 *tag)
724 int old_offset = offset;
729 offset = get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
731 if(show_internal_ber_fields){
732 proto_tree_add_uint(tree, hf_ber_id_class, tvb, old_offset, 1, tmp_class<<6);
733 proto_tree_add_boolean(tree, hf_ber_id_pc, tvb, old_offset, 1, (tmp_pc)?0x20:0x00);
735 if(tmp_class==BER_CLASS_UNI){
736 proto_tree_add_uint(tree, hf_ber_id_uni_tag_ext, tvb, old_offset + 1, offset - (old_offset + 1), tmp_tag);
738 proto_tree_add_uint(tree, hf_ber_id_tag_ext, tvb, old_offset + 1, offset - (old_offset + 1), tmp_tag);
741 if(tmp_class==BER_CLASS_UNI){
742 proto_tree_add_uint(tree, hf_ber_id_uni_tag, tvb, old_offset, 1, tmp_tag);
744 proto_tree_add_uint(tree, hf_ber_id_tag, tvb, old_offset, 1, tmp_tag);
759 /* this function gets the length octets of the BER TLV.
760 * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
762 /* 8.1.3 Length octets */
764 get_ber_length(tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind) {
769 int tmp_offset,s_offset;
776 oct = tvb_get_guint8(tvb, offset);
787 oct = tvb_get_guint8(tvb, offset);
789 tmp_length = (tmp_length<<8) + oct;
795 /* ok in here we can traverse the BER to find the length, this will fix most indefinite length issues */
796 /* Assumption here is that indefinite length is always used on constructed types*/
798 while (tvb_get_guint8(tvb, offset) || tvb_get_guint8(tvb, offset+1)) {
799 /* not an EOC at offset */
801 offset= get_ber_identifier(tvb, offset, &tclass, &tpc, &ttag);
802 offset= get_ber_length(tvb,offset, &tmp_len, NULL);
803 tmp_length += tmp_len+(offset-s_offset); /* length + tag and length */
805 /* Make sure we've moved forward in the packet */
806 if (offset <= s_offset)
807 THROW(ReportedBoundsError);
816 *length = tmp_length;
821 printf("get BER length %d, offset %d (remaining %d)\n", tmp_length, offset, tvb_length_remaining(tvb, offset));
827 /* this function dissects the length octets of the BER TLV.
828 * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
831 dissect_ber_length(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind)
833 int old_offset = offset;
837 offset = get_ber_length(tvb, offset, &tmp_length, &tmp_ind);
839 if(show_internal_ber_fields){
841 proto_tree_add_text(tree, tvb, old_offset, 1, "Length: Indefinite length %d", tmp_length);
843 proto_tree_add_uint(tree, hf_ber_length, tvb, old_offset, offset - old_offset, tmp_length);
847 *length = tmp_length;
852 printf("dissect BER length %d, offset %d (remaining %d)\n", tmp_length, offset, tvb_length_remaining(tvb, offset));
858 reassemble_octet_string(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 con_len, gboolean ind, tvbuff_t **out_tvb)
860 static GHashTable *octet_segment_table = NULL;
861 static GHashTable *octet_reassembled_table = NULL;
862 fragment_data *fd_head = NULL;
863 tvbuff_t *next_tvb = NULL;
864 tvbuff_t *reassembled_tvb = NULL;
866 int start_offset = offset;
867 gboolean fragment = TRUE;
868 gboolean firstFragment = TRUE;
870 if(octet_segment_table == NULL) {
871 /* I assume I can take this late binding approach */
872 fragment_table_init(&octet_segment_table);
873 reassembled_table_init(&octet_reassembled_table);
877 /* so we need to consume octet strings for the given length */
879 /* not sure we need this */
880 actx->pinfo->fragmented = TRUE;
884 offset = dissect_ber_octet_string(FALSE, actx, tree, tvb, offset, hf_ber_constructed_OCTETSTRING, &next_tvb);
886 if (next_tvb == NULL) {
887 /* Assume that we have a malformed packet. */
888 THROW(ReportedBoundsError);
892 /* this was indefinite length - so check for EOC */
894 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)) {
901 if((guint32)(offset - start_offset) >= con_len)
905 if(!fragment && firstFragment) {
906 /* there is only one fragment (I'm sure there's a reason it was constructed) */
907 /* anyway, we can get out of here */
908 reassembled_tvb = next_tvb;
913 if (tvb_length(next_tvb) < 1) {
914 /* Don't cause an assertion in the reassembly code. */
915 THROW(ReportedBoundsError);
917 fd_head = fragment_add_seq_next(next_tvb, 0, actx->pinfo, dst_ref,
919 octet_reassembled_table,
920 tvb_length(next_tvb),
923 firstFragment = FALSE;
928 reassembled_tvb = tvb_new_real_data(fd_head->data,
932 tvb_set_child_real_data_tvbuff(next_tvb, reassembled_tvb);
934 /* not sure I really want to do this here - should be nearer the application where we can give it a better name*/
935 add_new_data_source(actx->pinfo, reassembled_tvb, "Reassembled OCTET STRING");
941 *out_tvb = reassembled_tvb;
943 /* again - not sure we need this */
944 actx->pinfo->fragmented = FALSE;
950 /* 8.7 Encoding of an octetstring value */
952 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) {
959 proto_item *it, *cause;
965 header_field_info *hfinfo;
967 hfinfo = proto_registrar_get_nth(hf_id);
972 if(tvb_length_remaining(tvb,offset)>3){
973 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));
975 printf("OCTET STRING dissect_ber_octet_string(%s) entered\n",name);
982 /* read header and len for the octet string */
983 offset=dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
984 offset=dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
985 end_offset=offset+len;
987 /* sanity check: we only handle Constructed Universal Sequences */
988 if ((class!=BER_CLASS_APP)&&(class!=BER_CLASS_PRI))
990 if( (class!=BER_CLASS_UNI)
991 ||((tag<BER_UNI_TAG_NumericString)&&(tag!=BER_UNI_TAG_OCTETSTRING)&&(tag!=BER_UNI_TAG_UTF8String)) ){
992 tvb_ensure_bytes_exist(tvb, hoffset, 2);
993 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: OctetString expected but class:%s(%d) %s tag:%d was unexpected", val_to_str(class,ber_class_codes,"Unknown"), class, pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tag);
994 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
995 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: OctetString expected");
996 if (decode_unexpected) {
997 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
998 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1005 /* implicit tag so just trust the length of the tvb */
1007 len=tvb_length_remaining(tvb,offset);
1008 end_offset=offset+len;
1011 actx->created_item = NULL;
1015 end_offset = reassemble_octet_string(actx, tree, tvb, offset, len, ind, out_tvb);
1018 gint length_remaining;
1020 length_remaining = tvb_length_remaining(tvb, offset);
1022 if(length_remaining<1){
1029 if(len<=(guint32)length_remaining){
1030 length_remaining=len;
1033 it = proto_tree_add_item(tree, hf_id, tvb, offset, length_remaining, FALSE);
1034 actx->created_item = it;
1038 pi=proto_tree_add_text(tree, tvb, offset, len, "Unknown OctetString: Length: 0x%02x, Value: 0x", len);
1041 proto_item_append_text(pi,"%02x",tvb_get_guint8(tvb, offset));
1048 *out_tvb = tvb_new_subset(tvb, offset, length_remaining, len);
1054 int dissect_ber_octet_string_wcb(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, ber_callback func)
1056 tvbuff_t *out_tvb = NULL;
1058 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_id, (func)?&out_tvb:NULL);
1059 if (func && out_tvb && (tvb_length(out_tvb)>0)) {
1061 tree = proto_item_add_subtree(actx->created_item, ett_ber_octet_string);
1062 /* TODO Should hf_id2 be pased as last parameter???*/
1063 func(FALSE, out_tvb, 0, actx, tree, -1);
1068 int 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)
1070 tvbuff_t *out_tvb = NULL;
1072 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_id, (func)?&out_tvb:NULL);
1073 if (func && out_tvb && (tvb_length(out_tvb)>0)) {
1075 tree = proto_item_add_subtree(actx->created_item, ett_ber_octet_string);
1076 /* TODO Should hf_id2 be pased as last parameter???*/
1077 func(tree, out_tvb, 0, actx);
1081 /* 8.8 Encoding of a null value */
1083 dissect_ber_null(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id) {
1093 offset_old = offset;
1094 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
1096 (!implicit_tag && ((class != BER_CLASS_UNI) || (tag != BER_UNI_TAG_NULL)))) {
1097 cause = proto_tree_add_text(tree, tvb, offset_old, offset - offset_old, "BER Error: NULL expected but class:%s(%d) %s tag:%d was unexpected", val_to_str(class,ber_class_codes,"Unknown"), class, pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tag);
1098 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1099 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: NULL expected");
1102 offset_old = offset;
1103 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
1105 proto_tree_add_text(tree, tvb, offset_old, offset - offset_old, "BER Error: NULL expect zero length but Length=%d", len);
1106 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: unexpected data in NULL type");
1107 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1108 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: NULL expect zero length");
1113 proto_tree_add_item(tree, hf_id, tvb, offset, 0, FALSE);
1118 dissect_ber_integer64(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gint64 *value)
1130 header_field_info *hfinfo;
1132 hfinfo = proto_registrar_get_nth(hf_id);
1137 if(tvb_length_remaining(tvb,offset)>3){
1138 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));
1140 printf("INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d \n",name,implicit_tag);
1147 offset=dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
1148 offset=dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
1150 gint32 remaining=tvb_length_remaining(tvb, offset);
1151 len=remaining>0 ? remaining : 0;
1154 /* we cant handle integers > 64 bits */
1156 header_field_info *hfinfo;
1157 proto_item *pi = NULL;
1160 hfinfo = proto_registrar_get_nth(hf_id);
1161 pi=proto_tree_add_text(tree, tvb, offset, len, "%s : 0x", hfinfo->name);
1165 proto_item_append_text(pi,"%02x",tvb_get_guint8(tvb, offset));
1176 /* extend sign bit */
1177 if(tvb_get_guint8(tvb, offset)&0x80){
1181 val=(val<<8)|tvb_get_guint8(tvb, offset);
1186 actx->created_item=NULL;
1190 if(len < 1 || len > 8) {
1191 proto_tree_add_text(tree, tvb, offset-len, len, "Can't handle integer length: %u", len);
1193 header_field_info* hfi;
1195 hfi = proto_registrar_get_nth(hf_id);
1201 actx->created_item=proto_tree_add_uint(tree, hf_id, tvb, offset-len, len, (guint32)val);
1207 actx->created_item=proto_tree_add_int(tree, hf_id, tvb, offset-len, len, (gint32)val);
1210 actx->created_item=proto_tree_add_int64(tree, hf_id, tvb, offset-len, len, val);
1213 actx->created_item=proto_tree_add_uint64(tree, hf_id, tvb, offset-len, len, (guint64)val);
1216 DISSECTOR_ASSERT_NOT_REACHED();
1229 dissect_ber_integer(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, guint32 *value)
1233 offset=dissect_ber_integer64(implicit_tag, actx, tree, tvb, offset, hf_id, &val);
1235 *value=(guint32)val;
1243 dissect_ber_boolean(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gboolean *value)
1250 header_field_info *hfi;
1253 offset=dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
1254 offset=dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
1255 /*if(class!=BER_CLASS_UNI)*/
1257 /* nothing to do here, yet */
1260 val=tvb_get_guint8(tvb, offset);
1263 actx->created_item=NULL;
1266 hfi = proto_registrar_get_nth(hf_id);
1267 if(hfi->type == FT_BOOLEAN)
1268 actx->created_item=proto_tree_add_boolean(tree, hf_id, tvb, offset-1, 1, val);
1270 actx->created_item=proto_tree_add_uint(tree, hf_id, tvb, offset-1, 1, val?1:0);
1274 *value=(val?TRUE:FALSE);
1281 /* 8.5 Encoding of a real value */
1284 dissect_ber_real(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id _U_, double *value)
1289 guint32 val_length, end_offset;
1293 offset=dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
1294 offset=dissect_ber_length(actx->pinfo, tree, tvb, offset, &val_length, NULL);
1296 /* 8.5.1 The encoding of a real value shall be primitive. */
1297 DISSECTOR_ASSERT_NOT_REACHED();
1299 /* 8.5.2 If the real value is the value zero,
1300 * there shall be no contents octets in the encoding.
1307 end_offset = offset + val_length;
1309 val = asn1_get_real(tvb_get_ptr(tvb, offset, val_length), val_length);
1310 actx->created_item = proto_tree_add_double(tree, hf_id, tvb, offset, val_length, val);
1312 if (value) *value = val;
1317 /* this function dissects a BER sequence
1319 int dissect_ber_sequence(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
1321 gboolean pcx, ind = 0, ind_field, imp_tag=FALSE;
1324 proto_tree *tree = parent_tree;
1325 proto_item *item = NULL;
1330 gint length_remaining;
1337 header_field_info *hfinfo;
1339 hfinfo = proto_registrar_get_nth(hf_id);
1344 if(tvb_length_remaining(tvb,offset)>3){
1345 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));
1347 printf("SEQUENCE dissect_ber_sequence(%s) entered\n",name);
1353 offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
1354 offset = get_ber_length(tvb, offset, &lenx, NULL);
1356 /* was implicit tag so just use the length of the tvb */
1357 lenx=tvb_length_remaining(tvb,offset);
1358 end_offset=offset+lenx;
1360 /* create subtree */
1363 item = proto_tree_add_item(parent_tree, hf_id, tvb, hoffset, lenx + offset - hoffset, FALSE);
1364 tree = proto_item_add_subtree(item, ett_id);
1370 /* first we must read the sequence header */
1371 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
1372 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
1374 /* Fixed the length is correctly returned from dissect ber_length
1375 end_offset = tvb_length(tvb);*/
1376 end_offset = offset + lenx -2;
1378 end_offset = offset + lenx;
1381 /* sanity check: we only handle Constructed Universal Sequences */
1382 if((classx!=BER_CLASS_APP)&&(classx!=BER_CLASS_PRI))
1384 ||(!implicit_tag&&((classx!=BER_CLASS_UNI)
1385 ||(tagx!=BER_UNI_TAG_SEQUENCE)))) {
1386 tvb_ensure_bytes_exist(tvb, hoffset, 2);
1387 cause = proto_tree_add_text(tree, tvb, offset, lenx, "BER Error: Sequence expected but class:%s(%d) %s tag:%d was unexpected", val_to_str(classx,ber_class_codes,"Unknown"), classx, pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tagx);
1388 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1389 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Sequence expected");
1390 if (decode_unexpected) {
1391 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
1392 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1397 /* loop over all entries until we reach the end of the sequence */
1398 while (offset < end_offset){
1405 /*if(ind){ this sequence was of indefinite length, if this is implicit indefinite impossible maybe
1406 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
1407 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
1408 /* If the first bytes is 00 00 of a indefenert length field it's a zero length field*/
1409 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
1410 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
1411 proto_item_append_text(item," 0 items");
1414 if(show_internal_ber_fields){
1415 proto_tree_add_text(tree, tvb, s_offset, offset+2, "ERROR WRONG SEQ EOC");
1422 /* read header and len for next field */
1423 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
1424 offset = get_ber_length(tvb, offset, &len, &ind_field);
1425 eoffset = offset + len;
1426 /* Make sure we move forward */
1427 if (eoffset <= hoffset)
1428 THROW(ReportedBoundsError);
1430 /*if(ind_field && (len == 2)){
1431 / disgusting indefinite length zero length field, what are these people doing /
1437 ber_sequence_try_again:
1438 /* have we run out of known entries in the sequence ?*/
1440 /* it was not, move to the next one and try again */
1441 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
1442 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
1443 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: This field lies beyond the end of the known sequence definition.");
1444 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1445 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Unknown field in Sequence");
1446 if (decode_unexpected) {
1447 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
1448 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1454 /* Verify that this one is the one we want.
1455 * Skip check completely if class==ANY
1456 * of if NOCHKTAG is set
1458 /* XXX Bug in asn2eth,
1459 * for scope [7] Scope OPTIONAL,
1461 * { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_scope },
1462 * and there should not be a NOTCHKTAG here
1464 if( ((seq->class==BER_CLASS_CON)||(seq->class==BER_CLASS_APP)||(seq->class==BER_CLASS_PRI)) && (!(seq->flags&BER_FLAGS_NOOWNTAG)) ){
1465 if( (seq->class!=BER_CLASS_ANY)
1467 &&( (seq->class!=class)
1468 ||(seq->tag!=tag) ) ){
1469 /* it was not, move to the next one and try again */
1470 if(seq->flags&BER_FLAGS_OPTIONAL){
1471 /* well this one was optional so just skip to the next one and try again. */
1473 goto ber_sequence_try_again;
1475 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
1476 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
1477 if( seq->class == BER_CLASS_UNI){
1478 cause = proto_tree_add_text(tree, tvb, offset, len,
1479 "BER Error: Wrong field in SEQUENCE expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
1480 val_to_str(seq->class,ber_class_codes,"Unknown"),seq->class,
1481 seq->tag,val_to_str(seq->tag,ber_uni_tag_codes,"Unknown"),
1482 val_to_str(class,ber_class_codes,"Unknown"),class,tag);
1483 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1484 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong field in SEQUENCE");
1486 cause = proto_tree_add_text(tree, tvb, offset, len,
1487 "BER Error: Wrong field in SEQUENCE expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
1488 val_to_str(seq->class,ber_class_codes,"Unknown"),seq->class,
1489 seq->tag,val_to_str(class,ber_class_codes,"Unknown"),class,tag);
1490 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1491 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong field in SEQUENCE");
1493 if (decode_unexpected) {
1494 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
1495 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1501 } else if(!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
1502 if( (seq->class!=BER_CLASS_ANY)
1504 &&( (seq->class!=class)
1505 ||(seq->tag!=tag) ) ){
1506 /* it was not, move to the next one and try again */
1507 if(seq->flags&BER_FLAGS_OPTIONAL){
1508 /* well this one was optional so just skip to the next one and try again. */
1510 goto ber_sequence_try_again;
1513 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
1514 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
1515 if( seq->class == BER_CLASS_UNI){
1516 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in sequence expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d",val_to_str(seq->class,ber_class_codes,"Unknown"),seq->class,seq->tag,val_to_str(seq->tag,ber_uni_tag_codes,"Unknown"),val_to_str(class,ber_class_codes,"Unknown"),class,tag);
1517 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1518 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong field in sequence");
1520 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in sequence expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",val_to_str(seq->class,ber_class_codes,"Unknown"),seq->class,seq->tag,val_to_str(class,ber_class_codes,"Unknown"),class,tag);
1521 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1522 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong field in sequence");
1524 if (decode_unexpected) {
1525 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
1526 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1534 if(!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
1535 /* dissect header and len for field */
1536 if(ind_field && (len == 2)){
1537 /* This is a Zero length field */
1538 next_tvb = tvb_new_subset(tvb, offset, len, len);
1541 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
1542 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
1543 length_remaining=tvb_length_remaining(tvb, hoffset);
1544 if (length_remaining>eoffset-hoffset-(2*ind_field))
1545 length_remaining=eoffset-hoffset-(2*ind_field);
1546 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset-hoffset-(2*ind_field));
1550 length_remaining=tvb_length_remaining(tvb, hoffset);
1551 if (length_remaining>eoffset-hoffset)
1552 length_remaining=eoffset-hoffset;
1553 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset-hoffset);
1556 /* call the dissector for this field */
1557 /*if ((eoffset-hoffset)>length_remaining) {*/
1558 /* If the field is indefinite (i.e. we dont know the
1559 * length) of if the tvb is short, then just
1560 * give it all of the tvb and hope for the best.
1562 /*next_tvb = tvb_new_subset(tvb, hoffset, -1, -1);*/
1570 header_field_info *hfinfo;
1572 hfinfo = proto_registrar_get_nth(hf_id);
1577 if(tvb_length_remaining(next_tvb,0)>3){
1578 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));
1580 printf("SEQUENCE dissect_ber_sequence(%s) calling subdissector\n",name);
1584 if (next_tvb == NULL) {
1585 /* Assume that we have a malformed packet. */
1586 THROW(ReportedBoundsError);
1589 if (seq->flags & BER_FLAGS_IMPLTAG){
1593 count=seq->func(imp_tag, next_tvb, 0, actx, tree, *seq->p_id);
1598 header_field_info *hfinfo;
1600 hfinfo = proto_registrar_get_nth(hf_id);
1605 printf("SEQUENCE dissect_ber_sequence(%s) subdissector ate %d bytes\n",name,count);
1608 /* if it was optional and no bytes were eaten and it was */
1609 /* supposed to (len<>0), just try again. */
1610 if((len!=0)&&(count==0)&&(seq->flags&BER_FLAGS_OPTIONAL)){
1612 goto ber_sequence_try_again;
1613 /* move the offset to the beginning of the next sequenced item */
1617 if(!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
1618 /* if we stripped the tag and length we should also strip the EOC is ind_len
1619 * Unless its a zero length field (len = 2)
1621 if((ind_field == 1)&&(len>2))
1624 if(show_internal_ber_fields){
1625 proto_tree_add_text(tree, tvb, offset, count, "SEQ FIELD EOC");
1631 /* if we didnt end up at exactly offset, then we ate too many bytes */
1632 if(offset != end_offset) {
1633 tvb_ensure_bytes_exist(tvb, offset-2, 2);
1634 cause = proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Sequence ate %d too many bytes", offset-end_offset);
1635 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1636 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: too many bytes in Sequence");
1639 /* need to eat this EOC
1640 end_offset = tvb_length(tvb);*/
1642 if(show_internal_ber_fields){
1643 proto_tree_add_text(tree, tvb, end_offset-2,2 , "SEQ EOC");
1649 int 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) {
1651 gboolean pcx, ind = 0, ind_field;
1654 proto_tree *tree = parent_tree;
1655 proto_item *item = NULL;
1660 gint length_remaining;
1667 header_field_info *hfinfo;
1669 hfinfo = proto_registrar_get_nth(hf_id);
1674 if(tvb_length_remaining(tvb,offset)>3){
1675 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));
1677 printf("SEQUENCE dissect_ber_old_sequence(%s) entered\n",name);
1683 offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
1684 offset = get_ber_length(tvb, offset, &lenx, NULL);
1686 /* was implicit tag so just use the length of the tvb */
1687 lenx=tvb_length_remaining(tvb,offset);
1688 end_offset=offset+lenx;
1690 /* create subtree */
1693 item = proto_tree_add_item(parent_tree, hf_id, tvb, hoffset, lenx + offset - hoffset, FALSE);
1694 tree = proto_item_add_subtree(item, ett_id);
1700 /* first we must read the sequence header */
1701 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
1702 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
1704 /* Fixed the length is correctly returned from dissect ber_length
1705 end_offset = tvb_length(tvb);*/
1706 end_offset = offset + lenx -2;
1708 end_offset = offset + lenx;
1711 /* sanity check: we only handle Constructed Universal Sequences */
1712 if((classx!=BER_CLASS_APP)&&(classx!=BER_CLASS_PRI))
1714 ||(!implicit_tag&&((classx!=BER_CLASS_UNI)
1715 ||(tagx!=BER_UNI_TAG_SEQUENCE)))) {
1716 tvb_ensure_bytes_exist(tvb, hoffset, 2);
1717 cause = proto_tree_add_text(tree, tvb, offset, lenx, "BER Error: Sequence expected but class:%s(%d) %s tag:%d was unexpected", val_to_str(classx,ber_class_codes,"Unknown"), classx, pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tagx);
1718 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1719 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Sequence expected");
1720 if (decode_unexpected) {
1721 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
1722 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1727 /* loop over all entries until we reach the end of the sequence */
1728 while (offset < end_offset){
1735 /*if(ind){ this sequence was of indefinite length, if this is implicit indefinite impossible maybe
1736 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
1737 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
1738 /* If the first bytes is 00 00 of a indefenert length field it's a zero length field*/
1739 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
1740 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
1741 proto_item_append_text(item," 0 items");
1744 if(show_internal_ber_fields){
1745 proto_tree_add_text(tree, tvb, s_offset, offset+2, "ERROR WRONG SEQ EOC");
1752 /* read header and len for next field */
1753 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
1754 offset = get_ber_length(tvb, offset, &len, &ind_field);
1755 eoffset = offset + len;
1756 /* Make sure we move forward */
1757 if (eoffset <= hoffset)
1758 THROW(ReportedBoundsError);
1760 /*if(ind_field && (len == 2)){
1761 / disgusting indefinite length zero length field, what are these people doing /
1767 ber_old_sequence_try_again:
1768 /* have we run out of known entries in the sequence ?*/
1770 /* it was not, move to the next one and try again */
1771 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
1772 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
1773 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: This field lies beyond the end of the known sequence definition.");
1774 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1775 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Unknown field in Sequence");
1776 if (decode_unexpected) {
1777 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
1778 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1784 /* Verify that this one is the one we want.
1785 * Skip check completely if class==ANY
1786 * of if NOCHKTAG is set
1788 /* XXX Bug in asn2eth,
1789 * for scope [7] Scope OPTIONAL,
1791 * { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_scope },
1792 * and there should not be a NOTCHKTAG here
1794 if( ((seq->class==BER_CLASS_CON)||(seq->class==BER_CLASS_APP)||(seq->class==BER_CLASS_PRI)) && (!(seq->flags&BER_FLAGS_NOOWNTAG)) ){
1795 if( (seq->class!=BER_CLASS_ANY)
1797 &&( (seq->class!=class)
1798 ||(seq->tag!=tag) ) ){
1799 /* it was not, move to the next one and try again */
1800 if(seq->flags&BER_FLAGS_OPTIONAL){
1801 /* well this one was optional so just skip to the next one and try again. */
1803 goto ber_old_sequence_try_again;
1805 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
1806 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
1807 if( seq->class == BER_CLASS_UNI){
1808 cause = proto_tree_add_text(tree, tvb, offset, len,
1809 "BER Error: Wrong field in SEQUENCE expected class:%s(%d) tag:%d (%s) but found class:%s(%d) tag:%d",
1810 val_to_str(seq->class,ber_class_codes,"Unknown"),seq->class,
1811 seq->tag,val_to_str(seq->tag,ber_uni_tag_codes,"Unknown"),
1812 val_to_str(class,ber_class_codes,"Unknown"),class,tag);
1813 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1814 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong field in SEQUENCE");
1816 cause = proto_tree_add_text(tree, tvb, offset, len,
1817 "BER Error: Wrong field in SEQUENCE expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",
1818 val_to_str(seq->class,ber_class_codes,"Unknown"),seq->class,
1819 seq->tag,val_to_str(class,ber_class_codes,"Unknown"),class,tag);
1820 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1821 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong field in SEQUENCE");
1823 if (decode_unexpected) {
1824 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
1825 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1831 } else if(!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
1832 if( (seq->class!=BER_CLASS_ANY)
1834 &&( (seq->class!=class)
1835 ||(seq->tag!=tag) ) ){
1836 /* it was not, move to the next one and try again */
1837 if(seq->flags&BER_FLAGS_OPTIONAL){
1838 /* well this one was optional so just skip to the next one and try again. */
1840 goto ber_old_sequence_try_again;
1843 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
1844 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, NULL, NULL);
1845 if( seq->class == BER_CLASS_UNI){
1846 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in sequence expected class:%s(%d) tag:%d(%s) but found class:%s(%d) tag:%d",val_to_str(seq->class,ber_class_codes,"Unknown"),seq->class,seq->tag,val_to_str(seq->tag,ber_uni_tag_codes,"Unknown"),val_to_str(class,ber_class_codes,"Unknown"),class,tag);
1847 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1848 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong field in sequence");
1850 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in sequence expected class:%s(%d) tag:%d but found class:%s(%d) tag:%d",val_to_str(seq->class,ber_class_codes,"Unknown"),seq->class,seq->tag,val_to_str(class,ber_class_codes,"Unknown"),class,tag);
1851 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1852 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong field in sequence");
1854 if (decode_unexpected) {
1855 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
1856 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
1864 if(!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
1865 /* dissect header and len for field */
1866 if(ind_field && (len == 2)){
1867 /* This is a Zero length field */
1868 next_tvb = tvb_new_subset(tvb, offset, len, len);
1871 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
1872 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
1873 length_remaining=tvb_length_remaining(tvb, hoffset);
1874 if (length_remaining>eoffset-hoffset-(2*ind_field))
1875 length_remaining=eoffset-hoffset-(2*ind_field);
1876 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset-hoffset-(2*ind_field));
1880 length_remaining=tvb_length_remaining(tvb, hoffset);
1881 if (length_remaining>eoffset-hoffset)
1882 length_remaining=eoffset-hoffset;
1883 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset-hoffset);
1886 /* call the dissector for this field */
1887 /*if ((eoffset-hoffset)>length_remaining) {*/
1888 /* If the field is indefinite (i.e. we dont know the
1889 * length) of if the tvb is short, then just
1890 * give it all of the tvb and hope for the best.
1892 /*next_tvb = tvb_new_subset(tvb, hoffset, -1, -1);*/
1900 header_field_info *hfinfo;
1902 hfinfo = proto_registrar_get_nth(hf_id);
1907 if(tvb_length_remaining(next_tvb,0)>3){
1908 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));
1910 printf("SEQUENCE dissect_ber_old_sequence(%s) calling subdissector\n",name);
1914 if (next_tvb == NULL) {
1915 /* Assume that we have a malformed packet. */
1916 THROW(ReportedBoundsError);
1918 count=seq->func(tree, next_tvb, 0, actx);
1923 header_field_info *hfinfo;
1925 hfinfo = proto_registrar_get_nth(hf_id);
1930 printf("SEQUENCE dissect_ber_old_sequence(%s) subdissector ate %d bytes\n",name,count);
1933 /* if it was optional and no bytes were eaten and it was */
1934 /* supposed to (len<>0), just try again. */
1935 if((len!=0)&&(count==0)&&(seq->flags&BER_FLAGS_OPTIONAL)){
1937 goto ber_old_sequence_try_again;
1938 /* move the offset to the beginning of the next sequenced item */
1942 if(!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
1943 /* if we stripped the tag and length we should also strip the EOC is ind_len
1944 * Unless its a zero length field (len = 2)
1946 if((ind_field == 1)&&(len>2))
1949 if(show_internal_ber_fields){
1950 proto_tree_add_text(tree, tvb, offset, count, "SEQ FIELD EOC");
1956 /* if we didnt end up at exactly offset, then we ate too many bytes */
1957 if(offset != end_offset) {
1958 tvb_ensure_bytes_exist(tvb, offset-2, 2);
1959 cause = proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Sequence ate %d too many bytes", offset-end_offset);
1960 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
1961 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: too many bytes in Sequence");
1964 /* need to eat this EOC
1965 end_offset = tvb_length(tvb);*/
1967 if(show_internal_ber_fields){
1968 proto_tree_add_text(tree, tvb, end_offset-2,2 , "SEQ EOC");
1974 /* This function dissects a BER set
1976 int dissect_ber_set(gboolean implicit_tag,asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *set, gint hf_id, gint ett_id) {
1978 gboolean pcx, ind = 0, ind_field, imp_tag = FALSE;
1981 proto_tree *tree = parent_tree;
1982 proto_item *item = NULL;
1984 int end_offset, s_offset;
1986 gint length_remaining;
1988 const ber_sequence_t *cset = NULL;
1989 # define MAX_SET_ELEMENTS 32
1990 guint32 mandatory_fields = 0;
1992 gboolean first_pass;
1997 header_field_info *hfinfo;
1999 hfinfo = proto_registrar_get_nth(hf_id);
2004 if(tvb_length_remaining(tvb,offset)>3){
2005 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));
2007 printf("SET dissect_ber_set(%s) entered\n",name);
2014 /* first we must read the sequence header */
2015 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
2016 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
2018 /* Fixed the length is correctly returned from dissect ber_length
2019 end_offset = tvb_length(tvb);*/
2020 end_offset = offset + lenx -2;
2022 end_offset = offset + lenx;
2025 /* sanity check: we only handle Constructed Universal Sets */
2026 if ((classx!=BER_CLASS_APP)&&(classx!=BER_CLASS_PRI))
2028 ||(!implicit_tag&&((classx!=BER_CLASS_UNI)
2029 ||(tagx!=BER_UNI_TAG_SET)))) {
2030 tvb_ensure_bytes_exist(tvb, hoffset, 2);
2031 cause = proto_tree_add_text(tree, tvb, offset, lenx, "BER Error: SET expected but class:%s(%d) %s tag:%d was found", val_to_str(classx,ber_class_codes,"Unknown"), classx, pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tagx);
2032 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2033 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: SET expected");
2034 if (decode_unexpected) {
2035 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2036 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2041 /* was implicit tag so just use the length of the tvb */
2042 lenx=tvb_length_remaining(tvb,offset);
2043 end_offset=offset+lenx;
2046 /* create subtree */
2049 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, lenx, FALSE);
2050 tree = proto_item_add_subtree(item, ett_id);
2054 /* record the mandatory elements of the set so we can check we found everything at the end
2055 we can only record 32 elements for now ... */
2056 for(set_idx = 0; (cset=&set[set_idx])->func && (set_idx < MAX_SET_ELEMENTS); set_idx++) {
2058 if(!(cset->flags & BER_FLAGS_OPTIONAL))
2059 mandatory_fields |= 1 << set_idx;
2063 /* loop over all entries until we reach the end of the set */
2064 while (offset < end_offset){
2071 /*if(ind){ this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2072 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2074 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
2075 if(show_internal_ber_fields){
2076 proto_tree_add_text(tree, tvb, s_offset, offset+2, "SEQ EOC");
2082 /* read header and len for next field */
2083 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
2084 offset = get_ber_length(tvb, offset, &len, &ind_field);
2085 eoffset = offset + len;
2087 /* Look through the Set to see if this class/id exists and
2088 * hasn't been seen before
2089 * Skip check completely if class==ANY
2090 * of if NOCHKTAG is set
2094 for(first_pass=TRUE, cset = set, set_idx = 0; cset->func || first_pass; cset++, set_idx++) {
2096 /* we reset for a second pass when we will look for choices */
2100 cset=set; /* reset to the beginning */
2104 if((first_pass && ((cset->class==class) && (cset->tag==tag))) ||
2105 (!first_pass && ((cset->class== BER_CLASS_ANY) && (cset->tag == -1))) ) /* choices */
2108 if (!(cset->flags & BER_FLAGS_NOOWNTAG) ) {
2109 /* dissect header and len for field */
2110 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2111 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
2112 length_remaining=tvb_length_remaining(tvb, hoffset);
2113 if (length_remaining>eoffset-hoffset-(2*ind_field))
2114 length_remaining=eoffset-hoffset-(2*ind_field);
2115 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset-hoffset-(2*ind_field));
2118 length_remaining=tvb_length_remaining(tvb, hoffset);
2119 if (length_remaining>eoffset-hoffset)
2120 length_remaining=eoffset-hoffset;
2121 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset-hoffset);
2125 /* call the dissector for this field */
2126 /*if ((eoffset-hoffset)>length_remaining) {*/
2127 /* If the field is indefinite (i.e. we dont know the
2128 * length) of if the tvb is short, then just
2129 * give it all of the tvb and hope for the best.
2131 /*next_tvb = tvb_new_subset(tvb, hoffset, -1, -1);*/
2139 header_field_info *hfinfo;
2141 hfinfo = proto_registrar_get_nth(hf_id);
2146 if(tvb_length_remaining(next_tvb,0)>3){
2147 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));
2149 printf("SET dissect_ber_set(%s) calling subdissector\n",name);
2153 if (next_tvb == NULL) {
2154 /* Assume that we have a malformed packet. */
2155 THROW(ReportedBoundsError);
2158 if ((cset->flags & BER_FLAGS_IMPLTAG))
2160 count=cset->func(imp_tag, next_tvb, 0, actx, tree, *cset->p_id);
2162 /* if we consumed some bytes,
2163 or we knew the length was zero (during the first pass only) */
2164 if(count || (first_pass && (len == 0 || (ind_field == 1 && len == 2)))) {
2166 if(set_idx < MAX_SET_ELEMENTS)
2167 mandatory_fields &= ~(1 << set_idx);
2171 if(!(cset->flags & BER_FLAGS_NOOWNTAG) ) {
2172 /* if we stripped the tag and length we should also strip the EOC is ind_len */
2175 if(show_internal_ber_fields){
2176 proto_tree_add_text(tree, tvb, offset, count, "SET FIELD EOC");
2186 /* we didn't find a match */
2187 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: Unknown field in SET class:%s(%d) tag:%d",val_to_str(class,ber_class_codes,"Unknown"),class,tag);
2188 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2189 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Unknown field in SET");
2190 if (decode_unexpected) {
2191 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2192 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2198 if(mandatory_fields) {
2200 /* OK - we didn't find some of the elements we expected */
2202 for(set_idx = 0; (cset = &set[set_idx])->func && (set_idx < MAX_SET_ELEMENTS); set_idx++) {
2204 if(mandatory_fields & (1 << set_idx)) {
2206 /* here is something we should have seen - but didn't! */
2207 cause = proto_tree_add_text(tree, tvb, offset, lenx,
2208 "BER Error: Missing field in SET class:%s(%d) tag:%d expected",
2209 val_to_str(cset->class,ber_class_codes,"Unknown"),cset->class,
2211 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2212 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Missing field in SET");
2219 /* if we didnt end up at exactly offset, then we ate too many bytes */
2220 if (offset != end_offset) {
2221 tvb_ensure_bytes_exist(tvb, offset-2, 2);
2222 cause = proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: SET ate %d too many bytes", offset-end_offset);
2223 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2224 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: too many bytes in SET");
2228 /* need to eat this EOC
2229 end_offset = tvb_length(tvb);*/
2231 if(show_internal_ber_fields){
2232 proto_tree_add_text(tree, tvb, end_offset-2,2 , "SET EOC");
2240 int 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) {
2242 gboolean pcx, ind = 0, ind_field;
2245 proto_tree *tree = parent_tree;
2246 proto_item *item = NULL;
2248 int end_offset, s_offset;
2250 gint length_remaining;
2252 const ber_old_sequence_t *cset = NULL;
2253 # define MAX_SET_ELEMENTS 32
2254 guint32 mandatory_fields = 0;
2256 gboolean first_pass;
2261 header_field_info *hfinfo;
2263 hfinfo = proto_registrar_get_nth(hf_id);
2268 if(tvb_length_remaining(tvb,offset)>3){
2269 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));
2271 printf("SET dissect_old_ber_set(%s) entered\n",name);
2278 /* first we must read the sequence header */
2279 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
2280 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
2282 /* Fixed the length is correctly returned from dissect ber_length
2283 end_offset = tvb_length(tvb);*/
2284 end_offset = offset + lenx -2;
2286 end_offset = offset + lenx;
2289 /* sanity check: we only handle Constructed Universal Sets */
2290 if ((classx!=BER_CLASS_APP)&&(classx!=BER_CLASS_PRI))
2292 ||(!implicit_tag&&((classx!=BER_CLASS_UNI)
2293 ||(tagx!=BER_UNI_TAG_SET)))) {
2294 tvb_ensure_bytes_exist(tvb, hoffset, 2);
2295 cause = proto_tree_add_text(tree, tvb, offset, lenx, "BER Error: SET expected but class:%s(%d) %s tag:%d was found", val_to_str(classx,ber_class_codes,"Unknown"), classx, pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tagx);
2296 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2297 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: SET expected");
2298 if (decode_unexpected) {
2299 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2300 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2305 /* was implicit tag so just use the length of the tvb */
2306 lenx=tvb_length_remaining(tvb,offset);
2307 end_offset=offset+lenx;
2310 /* create subtree */
2313 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, lenx, FALSE);
2314 tree = proto_item_add_subtree(item, ett_id);
2318 /* record the mandatory elements of the set so we can check we found everything at the end
2319 we can only record 32 elements for now ... */
2320 for(set_idx = 0; (cset=&set[set_idx])->func && (set_idx < MAX_SET_ELEMENTS); set_idx++) {
2322 if(!(cset->flags & BER_FLAGS_OPTIONAL))
2323 mandatory_fields |= 1 << set_idx;
2327 /* loop over all entries until we reach the end of the set */
2328 while (offset < end_offset){
2335 /*if(ind){ this sequence was of indefinite length, if this is implicit indefinite impossible maybe
2336 but ber dissector uses this to eat the tag length then pass into here... EOC still on there...*/
2338 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
2339 if(show_internal_ber_fields){
2340 proto_tree_add_text(tree, tvb, s_offset, offset+2, "SEQ EOC");
2346 /* read header and len for next field */
2347 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
2348 offset = get_ber_length(tvb, offset, &len, &ind_field);
2349 eoffset = offset + len;
2351 /* Look through the Set to see if this class/id exists and
2352 * hasn't been seen before
2353 * Skip check completely if class==ANY
2354 * of if NOCHKTAG is set
2358 for(first_pass=TRUE, cset = set, set_idx = 0; cset->func || first_pass; cset++, set_idx++) {
2360 /* we reset for a second pass when we will look for choices */
2364 cset=set; /* reset to the beginning */
2368 if((first_pass && ((cset->class==class) && (cset->tag==tag))) ||
2369 (!first_pass && ((cset->class== BER_CLASS_ANY) && (cset->tag == -1))) ) /* choices */
2372 if (!(cset->flags & BER_FLAGS_NOOWNTAG) ) {
2373 /* dissect header and len for field */
2374 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
2375 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
2376 length_remaining=tvb_length_remaining(tvb, hoffset);
2377 if (length_remaining>eoffset-hoffset-(2*ind_field))
2378 length_remaining=eoffset-hoffset-(2*ind_field);
2379 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset-hoffset-(2*ind_field));
2382 length_remaining=tvb_length_remaining(tvb, hoffset);
2383 if (length_remaining>eoffset-hoffset)
2384 length_remaining=eoffset-hoffset;
2385 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset-hoffset);
2389 /* call the dissector for this field */
2390 /*if ((eoffset-hoffset)>length_remaining) {*/
2391 /* If the field is indefinite (i.e. we dont know the
2392 * length) of if the tvb is short, then just
2393 * give it all of the tvb and hope for the best.
2395 /*next_tvb = tvb_new_subset(tvb, hoffset, -1, -1);*/
2403 header_field_info *hfinfo;
2405 hfinfo = proto_registrar_get_nth(hf_id);
2410 if(tvb_length_remaining(next_tvb,0)>3){
2411 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));
2413 printf("SET dissect_old_ber_set(%s) calling subdissector\n",name);
2417 if (next_tvb == NULL) {
2418 /* Assume that we have a malformed packet. */
2419 THROW(ReportedBoundsError);
2421 count=cset->func(tree, next_tvb, 0, actx);
2423 /* if we consumed some bytes,
2424 or we knew the length was zero (during the first pass only) */
2425 if(count || (first_pass && (len == 0 || (ind_field == 1 && len == 2)))) {
2427 if(set_idx < MAX_SET_ELEMENTS)
2428 mandatory_fields &= ~(1 << set_idx);
2432 if(!(cset->flags & BER_FLAGS_NOOWNTAG) ) {
2433 /* if we stripped the tag and length we should also strip the EOC is ind_len */
2436 if(show_internal_ber_fields){
2437 proto_tree_add_text(tree, tvb, offset, count, "SET FIELD EOC");
2447 /* we didn't find a match */
2448 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: Unknown field in SET class:%s(%d) tag:%d",val_to_str(class,ber_class_codes,"Unknown"),class,tag);
2449 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2450 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Unknown field in SET");
2451 if (decode_unexpected) {
2452 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
2453 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
2459 if(mandatory_fields) {
2461 /* OK - we didn't find some of the elements we expected */
2463 for(set_idx = 0; (cset = &set[set_idx])->func && (set_idx < MAX_SET_ELEMENTS); set_idx++) {
2465 if(mandatory_fields & (1 << set_idx)) {
2467 /* here is something we should have seen - but didn't! */
2468 cause = proto_tree_add_text(tree, tvb, offset, lenx,
2469 "BER Error: Missing field in SET class:%s(%d) tag:%d expected",
2470 val_to_str(cset->class,ber_class_codes,"Unknown"),cset->class,
2472 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2473 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Missing field in SET");
2480 /* if we didnt end up at exactly offset, then we ate too many bytes */
2481 if (offset != end_offset) {
2482 tvb_ensure_bytes_exist(tvb, offset-2, 2);
2483 cause = proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: SET ate %d too many bytes", offset-end_offset);
2484 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2485 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: too many bytes in SET");
2489 /* need to eat this EOC
2490 end_offset = tvb_length(tvb);*/
2492 if(show_internal_ber_fields){
2493 proto_tree_add_text(tree, tvb, end_offset-2,2 , "SET EOC");
2500 /* this function dissects a BER choice
2501 * If we did not find a matching choice, just return offset unchanged
2502 * in case it was a CHOICE { } OPTIONAL
2505 #define DEBUG_BER_CHOICE
2509 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)
2512 gboolean pc, ind, imp_tag = FALSE;
2515 const ber_choice_t *ch;
2516 proto_tree *tree=parent_tree;
2517 proto_item *item=NULL;
2518 int end_offset, start_offset, count;
2519 int hoffset = offset;
2520 header_field_info *hfinfo;
2521 gint length, length_remaining;
2523 gboolean first_pass;
2525 #ifdef DEBUG_BER_CHOICE
2528 header_field_info *hfinfo;
2530 hfinfo = proto_registrar_get_nth(hf_id);
2535 if(tvb_length_remaining(tvb,offset)>3){
2536 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));
2538 printf("CHOICE dissect_ber_choice(%s) entered len:%d\n",name,tvb_length_remaining(tvb,offset));
2542 start_offset=offset;
2544 if(tvb_length_remaining(tvb,offset) == 0) {
2545 item = proto_tree_add_text(parent_tree, tvb, offset, 0, "BER Error: Empty choice was found");
2546 proto_item_set_expert_flags(item, PI_MALFORMED, PI_WARN);
2547 expert_add_info_format(actx->pinfo, item, PI_MALFORMED, PI_WARN, "BER Error: Empty choice was found");
2551 /* read header and len for choice field */
2552 offset=get_ber_identifier(tvb, offset, &class, &pc, &tag);
2553 offset=get_ber_length(tvb, offset, &len, &ind);
2554 end_offset = offset + len ;
2556 /* Some sanity checks.
2557 * The hf field passed to us MUST be an integer type
2560 hfinfo=proto_registrar_get_nth(hf_id);
2561 switch(hfinfo->type) {
2568 proto_tree_add_text(tree, tvb, offset, len,"dissect_ber_choice(): Was passed a HF field that was not integer type : %s",hfinfo->abbrev);
2569 fprintf(stderr,"dissect_ber_choice(): frame:%u offset:%d Was passed a HF field that was not integer type : %s\n",actx->pinfo->fd->num,offset,hfinfo->abbrev);
2576 /* loop over all entries until we find the right choice or
2577 run out of entries */
2583 while(ch->func || first_pass){
2587 /* we reset for a second pass when we will look for choices */
2590 ch = choice; /* reset to the beginning */
2597 #ifdef DEBUG_BER_CHOICE
2598 printf("CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d:(expected)%d flags:%d\n",ch,class,ch->class,tag,ch->tag,ch->flags);
2600 if( (first_pass && (((ch->class==class)&&(ch->tag==tag))
2601 || ((ch->class==class)&&(ch->tag==-1)&&(ch->flags&BER_FLAGS_NOOWNTAG)))) ||
2602 (!first_pass && (((ch->class == BER_CLASS_ANY) && (ch->tag == -1)))) /* we failed on the first pass so now try any choices */
2604 if(!(ch->flags & BER_FLAGS_NOOWNTAG)){
2605 /* dissect header and len for field */
2606 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, start_offset, NULL, NULL, NULL);
2607 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
2608 start_offset=hoffset;
2619 length = end_offset- hoffset;
2620 /* create subtree */
2623 item = proto_tree_add_uint(parent_tree, hf_id, tvb, hoffset, end_offset - hoffset, ch->value);
2624 tree = proto_item_add_subtree(item, ett_id);
2628 length_remaining=tvb_length_remaining(tvb, hoffset);
2629 if(length_remaining>length)
2630 length_remaining=length;
2633 /* This is bogus and makes the OID_1.0.9506.1.1.cap file
2634 * in Steven J Schaeffer's email of 2005-09-12 fail to dissect
2635 * properly. Maybe we should get rid of 'first_pass'
2637 * It was added as a qad workaround for some problem CMIP
2639 * God, this file is a mess and it is my fault. /ronnie
2642 next_tvb=tvb_new_subset(tvb, hoffset, length_remaining, length);
2644 next_tvb = tvb; /* we didn't make selection on this class/tag so pass it on */
2646 next_tvb=tvb_new_subset(tvb, hoffset, length_remaining, length);
2649 #ifdef DEBUG_BER_CHOICE
2652 header_field_info *hfinfo;
2654 hfinfo = proto_registrar_get_nth(hf_id);
2659 if(tvb_length_remaining(next_tvb,0)>3){
2660 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));
2662 printf("CHOICE dissect_ber_choice(%s) calling subdissector len:%d\n",name,tvb_length(next_tvb));
2666 if (next_tvb == NULL) {
2667 /* Assume that we have a malformed packet. */
2668 THROW(ReportedBoundsError);
2671 if ((ch->flags & BER_FLAGS_IMPLTAG))
2673 count=ch->func(imp_tag, next_tvb, 0, actx, tree, *ch->p_id);
2674 #ifdef DEBUG_BER_CHOICE
2677 header_field_info *hfinfo;
2679 hfinfo = proto_registrar_get_nth(hf_id);
2684 printf("CHOICE dissect_ber_choice(%s) subdissector ate %d bytes\n",name,count);
2687 if((count==0)&&(((ch->class==class)&&(ch->tag==-1)&&(ch->flags&BER_FLAGS_NOOWNTAG)) || !first_pass)){
2688 /* wrong one, break and try again */
2690 #ifdef DEBUG_BER_CHOICE
2693 header_field_info *hfinfo;
2695 hfinfo = proto_registrar_get_nth(hf_id);
2700 printf("CHOICE dissect_ber_choice(%s) trying again\n",name);
2703 goto choice_try_again;
2705 if(!(ch->flags & BER_FLAGS_NOOWNTAG)){
2708 /* we are traversing a indfinite length choice where we did not pass the tag length */
2709 /* we need to eat the EOC */
2710 if(show_internal_ber_fields){
2711 proto_tree_add_text(tree, tvb, start_offset, count+2, "CHOICE EOC");
2720 /* none of the branches were taken so set the param
2726 /*XXX here we should have another flag to the CHOICE to distinguish
2727 * between the case when we know it is a mandatory or if the CHOICE is optional == no arm matched */
2729 /* oops no more entries and we still havent found
2732 item = proto_tree_add_text(tree, tvb, offset, len, "BER Error: This choice field was not found.");
2733 proto_item_set_expert_flags(item, PI_MALFORMED, PI_WARN);
2734 expert_add_info_format(actx->pinfo, item, PI_MALFORMED, PI_WARN, "BER Error: This choice field was not found");
2738 return start_offset;
2742 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)
2748 const ber_old_choice_t *ch;
2749 proto_tree *tree=parent_tree;
2750 proto_item *item=NULL;
2751 int end_offset, start_offset, count;
2752 int hoffset = offset;
2753 header_field_info *hfinfo;
2754 gint length, length_remaining;
2756 gboolean first_pass;
2758 #ifdef DEBUG_BER_CHOICE
2761 header_field_info *hfinfo;
2763 hfinfo = proto_registrar_get_nth(hf_id);
2768 if(tvb_length_remaining(tvb,offset)>3){
2769 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));
2771 printf("CHOICE dissect_ber_old_choice(%s) entered len:%d\n",name,tvb_length_remaining(tvb,offset));
2775 start_offset=offset;
2777 if(tvb_length_remaining(tvb,offset) == 0) {
2778 item = proto_tree_add_text(parent_tree, tvb, offset, 0, "BER Error: Empty choice was found");
2779 proto_item_set_expert_flags(item, PI_MALFORMED, PI_WARN);
2780 expert_add_info_format(actx->pinfo, item, PI_MALFORMED, PI_WARN, "BER Error: Empty choice was found");
2784 /* read header and len for choice field */
2785 offset=get_ber_identifier(tvb, offset, &class, &pc, &tag);
2786 offset=get_ber_length(tvb, offset, &len, &ind);
2787 end_offset = offset + len ;
2789 /* Some sanity checks.
2790 * The hf field passed to us MUST be an integer type
2793 hfinfo=proto_registrar_get_nth(hf_id);
2794 switch(hfinfo->type) {
2801 proto_tree_add_text(tree, tvb, offset, len,"dissect_ber_old_choice(): Was passed a HF field that was not integer type : %s",hfinfo->abbrev);
2802 fprintf(stderr,"dissect_ber_old_choice(): frame:%u offset:%d Was passed a HF field that was not integer type : %s\n",actx->pinfo->fd->num,offset,hfinfo->abbrev);
2809 /* loop over all entries until we find the right choice or
2810 run out of entries */
2816 while(ch->func || first_pass){
2820 /* we reset for a second pass when we will look for choices */
2823 ch = choice; /* reset to the beginning */
2830 #ifdef DEBUG_BER_CHOICE
2831 printf("CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d:(expected)%d flags:%d\n",ch,class,ch->class,tag,ch->tag,ch->flags);
2833 if( (first_pass && (((ch->class==class)&&(ch->tag==tag))
2834 || ((ch->class==class)&&(ch->tag==-1)&&(ch->flags&BER_FLAGS_NOOWNTAG)))) ||
2835 (!first_pass && (((ch->class == BER_CLASS_ANY) && (ch->tag == -1)))) /* we failed on the first pass so now try any choices */
2837 if(!(ch->flags & BER_FLAGS_NOOWNTAG)){
2838 /* dissect header and len for field */
2839 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, start_offset, NULL, NULL, NULL);
2840 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
2841 start_offset=hoffset;
2852 length = end_offset- hoffset;
2853 /* create subtree */
2856 item = proto_tree_add_uint(parent_tree, hf_id, tvb, hoffset, end_offset - hoffset, ch->value);
2857 tree = proto_item_add_subtree(item, ett_id);
2861 length_remaining=tvb_length_remaining(tvb, hoffset);
2862 if(length_remaining>length)
2863 length_remaining=length;
2866 /* This is bogus and makes the OID_1.0.9506.1.1.cap file
2867 * in Steven J Schaeffer's email of 2005-09-12 fail to dissect
2868 * properly. Maybe we should get rid of 'first_pass'
2870 * It was added as a qad workaround for some problem CMIP
2872 * God, this file is a mess and it is my fault. /ronnie
2875 next_tvb=tvb_new_subset(tvb, hoffset, length_remaining, length);
2877 next_tvb = tvb; /* we didn't make selection on this class/tag so pass it on */
2879 next_tvb=tvb_new_subset(tvb, hoffset, length_remaining, length);
2882 #ifdef DEBUG_BER_CHOICE
2885 header_field_info *hfinfo;
2887 hfinfo = proto_registrar_get_nth(hf_id);
2892 if(tvb_length_remaining(next_tvb,0)>3){
2893 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));
2895 printf("CHOICE dissect_ber_old_choice(%s) calling subdissector len:%d\n",name,tvb_length(next_tvb));
2899 if (next_tvb == NULL) {
2900 /* Assume that we have a malformed packet. */
2901 THROW(ReportedBoundsError);
2903 count=ch->func(tree, next_tvb, 0, actx);
2904 #ifdef DEBUG_BER_CHOICE
2907 header_field_info *hfinfo;
2909 hfinfo = proto_registrar_get_nth(hf_id);
2914 printf("CHOICE dissect_ber_old_choice(%s) subdissector ate %d bytes\n",name,count);
2917 if((count==0)&&(((ch->class==class)&&(ch->tag==-1)&&(ch->flags&BER_FLAGS_NOOWNTAG)) || !first_pass)){
2918 /* wrong one, break and try again */
2920 #ifdef DEBUG_BER_CHOICE
2923 header_field_info *hfinfo;
2925 hfinfo = proto_registrar_get_nth(hf_id);
2930 printf("CHOICE dissect_ber_old_choice(%s) trying again\n",name);
2933 goto choice_try_again;
2935 if(!(ch->flags & BER_FLAGS_NOOWNTAG)){
2938 /* we are traversing a indfinite length choice where we did not pass the tag length */
2939 /* we need to eat the EOC */
2940 if(show_internal_ber_fields){
2941 proto_tree_add_text(tree, tvb, start_offset, count+2, "CHOICE EOC");
2950 /* none of the branches were taken so set the param
2956 /*XXX here we should have another flag to the CHOICE to distinguish
2957 * between the case when we know it is a mandatory or if the CHOICE is optional == no arm matched */
2959 /* oops no more entries and we still havent found
2962 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: This choice field was not found.");
2963 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2964 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: This choice field was not found");
2968 return start_offset;
2972 /* this function dissects a BER GeneralString
2975 dissect_ber_GeneralString(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, int name_len)
2996 /* first we must read the GeneralString header */
2997 offset=dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
2998 offset=dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
2999 end_offset=offset+len;
3001 /* sanity check: we only handle Universal GeneralString*/
3002 if( (class!=BER_CLASS_UNI)
3003 ||(tag!=BER_UNI_TAG_GENSTR) ){
3004 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3005 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: GeneralString expected but class:%s(%d) %s tag:%d was unexpected", val_to_str(class,ber_class_codes,"Unknown"), class, pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tag);
3006 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
3007 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: GeneralString expected");
3008 if (decode_unexpected) {
3009 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3010 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3015 if(len>=(max_len-1)){
3019 tvb_memcpy(tvb, str, offset, len);
3023 proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
3029 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) {
3035 int hoffset = offset;
3041 header_field_info *hfinfo;
3043 hfinfo = proto_registrar_get_nth(hf_id);
3048 if(tvb_length_remaining(tvb,offset)>3){
3049 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));
3051 printf("RESTRICTED STRING dissect_ber_octet_string(%s) entered\n",name);
3057 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
3058 offset = get_ber_length(tvb, offset, &len, NULL);
3059 eoffset = offset + len;
3062 if( (class!=BER_CLASS_UNI)
3064 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3065 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: String with tag=%d expected but class:%s(%d) %s tag:%d was unexpected", type, val_to_str(class,ber_class_codes,"Unknown"), class, pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tag);
3066 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
3067 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: String expected");
3068 if (decode_unexpected) {
3069 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3070 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3077 return dissect_ber_octet_string(implicit_tag, actx, tree, tvb, hoffset, hf_id, out_tvb);
3081 dissect_ber_GeneralString(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, guint name_len)
3083 tvbuff_t *out_tvb = NULL;
3085 offset = dissect_ber_restricted_string(FALSE, BER_UNI_TAG_GeneralString, actx, tree, tvb, offset, hf_id, (name_string)?&out_tvb:NULL);
3088 if(out_tvb && tvb_length(out_tvb) >= name_len) {
3089 tvb_memcpy(out_tvb, (guint8*)name_string, 0, name_len-1);
3090 name_string[name_len-1] = '\0';
3091 } else if(out_tvb) {
3092 tvb_memcpy(out_tvb, (guint8*)name_string, 0, -1);
3093 name_string[tvb_length(out_tvb)] = '\0';
3100 /* 8.19 Encoding of an object identifier value.
3102 int dissect_ber_object_identifier(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **value_tvb)
3112 header_field_info *hfi;
3118 header_field_info *hfinfo;
3120 hfinfo = proto_registrar_get_nth(hf_id);
3125 if(tvb_length_remaining(tvb,offset)>3){
3126 printf("OBJECT IDENTIFIER dissect_ber_object_identifier(%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));
3128 printf("OBJECT IDENTIFIER dissect_ber_object_identifier(%s) entered\n",name);
3136 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
3137 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
3138 eoffset = offset + len;
3139 if( (class!=BER_CLASS_UNI)
3140 ||(tag != BER_UNI_TAG_OID) ){
3141 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3142 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: Object Identifier expected but class:%s(%d) %s tag:%d was unexpected", val_to_str(class,ber_class_codes,"Unknown"), class, pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tag);
3143 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
3144 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Object Identifier expected");
3145 if (decode_unexpected) {
3146 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3147 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3152 len=tvb_length_remaining(tvb,offset);
3156 actx->created_item=NULL;
3157 hfi = proto_registrar_get_nth(hf_id);
3158 if (hfi->type == FT_OID) {
3159 actx->created_item = proto_tree_add_item(tree, hf_id, tvb, offset, len, FALSE);
3160 } else if (IS_FT_STRING(hfi->type)) {
3161 str = oid_encoded2string(tvb_get_ptr(tvb, offset, len), len);
3162 actx->created_item = proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
3163 if(actx->created_item){
3164 /* see if we know the name of this oid */
3165 name = oid_resolved_from_encoded(tvb_get_ptr(tvb, offset, len), len);
3167 proto_item_append_text(actx->created_item, " (%s)", name);
3171 DISSECTOR_ASSERT_NOT_REACHED();
3175 *value_tvb = tvb_new_subset(tvb, offset, len, len);
3180 int dissect_ber_object_identifier_str(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, const char **value_stringx)
3182 tvbuff_t *value_tvb = NULL;
3185 offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_id, (value_stringx) ? &value_tvb : NULL);
3187 if (value_stringx) {
3188 if (value_tvb && (length = tvb_length(value_tvb))) {
3189 *value_stringx = oid_encoded2string(tvb_get_ptr(value_tvb, 0, length), length);
3191 *value_stringx = "";
3199 #define DEBUG_BER_SQ_OF
3202 static int dissect_ber_sq_of(gboolean implicit_tag, gint32 type, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
3204 gboolean pcx, ind = FALSE, ind_field;
3208 proto_tree *tree = parent_tree;
3209 proto_item *item = NULL;
3211 int cnt, hoffsetx, end_offset;
3212 header_field_info *hfi;
3213 gint length_remaining;
3216 #ifdef DEBUG_BER_SQ_OF
3219 header_field_info *hfinfo;
3221 hfinfo = proto_registrar_get_nth(hf_id);
3226 if(tvb_length_remaining(tvb,offset)>3){
3227 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));
3229 printf("SQ OF dissect_ber_sq_of(%s) entered\n",name);
3236 /* first we must read the sequence header */
3237 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
3238 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
3240 /* if the length is indefinite we dont really know (yet) where the
3241 * object ends so assume it spans the rest of the tvb for now.
3243 end_offset = offset + lenx;
3245 end_offset = offset + lenx;
3248 /* sanity check: we only handle Constructed Universal Sequences */
3249 if((classx!=BER_CLASS_APP)&&(classx!=BER_CLASS_PRI))
3251 ||(!implicit_tag&&((classx!=BER_CLASS_UNI)
3253 tvb_ensure_bytes_exist(tvb, hoffsetx, 2);
3254 causex = proto_tree_add_text(tree, tvb, offset, lenx, "BER Error: %s Of expected but class:%s(%d) %s tag:%d was unexpected",
3255 (type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence", val_to_str(classx,ber_class_codes,"Unknown"), classx, pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tagx);
3256 proto_item_set_expert_flags(causex, PI_MALFORMED, PI_WARN);
3257 expert_add_info_format(actx->pinfo, causex, PI_MALFORMED, PI_WARN, "BER Error: %s Of expected",(type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence");
3258 if (decode_unexpected) {
3259 proto_tree *unknown_tree = proto_item_add_subtree(causex, ett_ber_unknown);
3260 dissect_unknown_ber(actx->pinfo, tvb, hoffsetx, unknown_tree);
3265 /* the tvb length should be correct now nope we could be comming from an implicit choice or sequence, thus we
3266 read the items we match and return the length*/
3267 lenx=tvb_length_remaining(tvb,offset);
3268 end_offset = offset + lenx;
3271 /* count number of items */
3274 /* only count the number of items IFF we have the full blob,
3275 * else this will just generate a [short frame] before we even start
3276 * dissecting a single item.
3278 /* XXX Do we really need to count them at all ? ronnie */
3279 if(tvb_length_remaining(tvb, offset)==tvb_reported_length_remaining(tvb, offset)){
3280 while (offset < end_offset){
3286 if(ind){ /* this sequence of was of indefinite length, so check for EOC */
3287 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
3292 /* read header and len for next field */
3293 offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
3294 offset = get_ber_length(tvb, offset, &len, &ind);
3295 /* best place to get real length of implicit sequence of or set of is here... */
3296 /* adjust end_offset if we find somthing that doesnt match */
3299 if (offset <= s_offset)
3300 THROW(ReportedBoundsError);
3305 /* create subtree */
3307 hfi = proto_registrar_get_nth(hf_id);
3309 if(hfi->type == FT_NONE) {
3310 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, lenx, FALSE);
3311 proto_item_append_text(item, ":");
3313 item = proto_tree_add_uint(parent_tree, hf_id, tvb, offset, lenx, cnt);
3314 proto_item_append_text(item, (cnt==1)?" item":" items");
3316 tree = proto_item_add_subtree(item, ett_id);
3320 /* loop over all entries until we reach the end of the sequence */
3321 while (offset < end_offset){
3332 if(ind){ /*this sequence of was of indefinite length, so check for EOC */
3333 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
3334 if(show_internal_ber_fields){
3335 proto_tree_add_text(tree, tvb, hoffset, end_offset-hoffset, "SEQ OF EOC");
3340 /* read header and len for next field */
3341 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
3342 offset = get_ber_length(tvb, offset, &len, &ind_field);
3343 eoffset = offset + len;
3344 /* Make sure we move forward */
3345 if (eoffset <= hoffset)
3346 THROW(ReportedBoundsError);
3348 if((class==BER_CLASS_UNI)&&(tag==BER_UNI_TAG_EOC)){
3349 /* This is a zero length sequence of*/
3350 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
3351 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3354 /* verify that this one is the one we want */
3355 /* ahup if we are implicit then we return to the uper layer how much we have used */
3356 if(seq->class!=BER_CLASS_ANY){
3357 if((seq->class!=class)
3358 ||(seq->tag!=tag) ){
3359 if(!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
3360 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in SQ OF(tag %u expected %u)",tag,seq->tag);
3361 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
3362 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong field in Sequence Of");
3363 if (decode_unexpected) {
3364 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3365 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3374 if(!(seq->flags & BER_FLAGS_NOOWNTAG) && !(seq->flags & BER_FLAGS_IMPLTAG)) {
3375 /* dissect header and len for field */
3376 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
3377 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3379 if((seq->flags == BER_FLAGS_IMPLTAG)&&(seq->class==BER_CLASS_CON)) {
3380 /* Constructed sequence of with a tag */
3381 /* dissect header and len for field */
3382 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
3383 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3384 /* Function has IMPLICIT TAG */
3387 length_remaining=tvb_length_remaining(tvb, hoffset);
3388 if (length_remaining>eoffset-hoffset)
3389 length_remaining=eoffset-hoffset;
3390 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset-hoffset);
3393 if(seq->flags == BER_FLAGS_IMPLTAG)
3395 /* call the dissector for this field */
3396 count=seq->func(imp_tag, next_tvb, 0, actx, tree, *seq->p_id)-hoffset;
3397 /* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
3398 doesnt match the next item, thus this implicit sequence is over, return the number of bytes
3399 we have eaten to allow the possible upper sequence continue... */
3404 /* if we didnt end up at exactly offset, then we ate too many bytes */
3405 if(offset != end_offset) {
3406 tvb_ensure_bytes_exist(tvb, offset-2, 2);
3407 causex =proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: %s Of ate %d too many bytes",
3408 (type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence", offset-end_offset);
3409 proto_item_set_expert_flags(causex, PI_MALFORMED, PI_WARN);
3410 expert_add_info_format(actx->pinfo, causex, PI_MALFORMED, PI_WARN, "BER Error:too many byte in %s",(type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence");
3416 static int 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) {
3418 gboolean pcx, ind = FALSE, ind_field;
3422 proto_tree *tree = parent_tree;
3423 proto_item *item = NULL;
3425 int cnt, hoffsetx, end_offset;
3426 header_field_info *hfi;
3427 gint length_remaining;
3430 #ifdef DEBUG_BER_SQ_OF
3433 header_field_info *hfinfo;
3435 hfinfo = proto_registrar_get_nth(hf_id);
3440 if(tvb_length_remaining(tvb,offset)>3){
3441 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));
3443 printf("SQ OF dissect_ber_old_sq_of(%s) entered\n",name);
3450 /* first we must read the sequence header */
3451 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &classx, &pcx, &tagx);
3452 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &lenx, &ind);
3454 /* if the length is indefinite we dont really know (yet) where the
3455 * object ends so assume it spans the rest of the tvb for now.
3457 end_offset = offset + lenx;
3459 end_offset = offset + lenx;
3462 /* sanity check: we only handle Constructed Universal Sequences */
3463 if((classx!=BER_CLASS_APP)&&(classx!=BER_CLASS_PRI))
3465 ||(!implicit_tag&&((classx!=BER_CLASS_UNI)
3467 tvb_ensure_bytes_exist(tvb, hoffsetx, 2);
3468 causex = proto_tree_add_text(tree, tvb, offset, lenx, "BER Error: %s Of expected but class:%s(%d) %s tag:%d was unexpected",
3469 (type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence", val_to_str(classx,ber_class_codes,"Unknown"), classx, pcx ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tagx);
3470 proto_item_set_expert_flags(causex, PI_MALFORMED, PI_WARN);
3471 expert_add_info_format(actx->pinfo, causex, PI_MALFORMED, PI_WARN, "BER Error: %s Of expected",(type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence");
3472 if (decode_unexpected) {
3473 proto_tree *unknown_tree = proto_item_add_subtree(causex, ett_ber_unknown);
3474 dissect_unknown_ber(actx->pinfo, tvb, hoffsetx, unknown_tree);
3479 /* the tvb length should be correct now nope we could be comming from an implicit choice or sequence, thus we
3480 read the items we match and return the length*/
3481 lenx=tvb_length_remaining(tvb,offset);
3482 end_offset = offset + lenx;
3485 /* count number of items */
3488 /* only count the number of items IFF we have the full blob,
3489 * else this will just generate a [short frame] before we even start
3490 * dissecting a single item.
3492 /* XXX Do we really need to count them at all ? ronnie */
3493 if(tvb_length_remaining(tvb, offset)==tvb_reported_length_remaining(tvb, offset)){
3494 while (offset < end_offset){
3500 if(ind){ /* this sequence of was of indefinite length, so check for EOC */
3501 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
3506 /* read header and len for next field */
3507 offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
3508 offset = get_ber_length(tvb, offset, &len, &ind);
3509 /* best place to get real length of implicit sequence of or set of is here... */
3510 /* adjust end_offset if we find somthing that doesnt match */
3513 if (offset <= s_offset)
3514 THROW(ReportedBoundsError);
3519 /* create subtree */
3521 hfi = proto_registrar_get_nth(hf_id);
3523 if(hfi->type == FT_NONE) {
3524 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, lenx, FALSE);
3525 proto_item_append_text(item, ":");
3527 item = proto_tree_add_uint(parent_tree, hf_id, tvb, offset, lenx, cnt);
3528 proto_item_append_text(item, (cnt==1)?" item":" items");
3530 tree = proto_item_add_subtree(item, ett_id);
3534 /* loop over all entries until we reach the end of the sequence */
3535 while (offset < end_offset){
3545 if(ind){ /*this sequence of was of indefinite length, so check for EOC */
3546 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
3547 if(show_internal_ber_fields){
3548 proto_tree_add_text(tree, tvb, hoffset, end_offset-hoffset, "SEQ OF EOC");
3553 /* read header and len for next field */
3554 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
3555 offset = get_ber_length(tvb, offset, &len, &ind_field);
3556 eoffset = offset + len;
3557 /* Make sure we move forward */
3558 if (eoffset <= hoffset)
3559 THROW(ReportedBoundsError);
3561 if((class==BER_CLASS_UNI)&&(tag==BER_UNI_TAG_EOC)){
3562 /* This is a zero length sequence of*/
3563 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
3564 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3567 /* verify that this one is the one we want */
3568 /* ahup if we are implicit then we return to the uper layer how much we have used */
3569 if(seq->class!=BER_CLASS_ANY){
3570 if((seq->class!=class)
3571 ||(seq->tag!=tag) ){
3572 if(!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
3573 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in SQ OF");
3574 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
3575 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: Wrong field in Sequence Of");
3576 if (decode_unexpected) {
3577 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3578 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3587 if(!(seq->flags & BER_FLAGS_NOOWNTAG) && !(seq->flags & BER_FLAGS_IMPLTAG)) {
3588 /* dissect header and len for field */
3589 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
3590 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3592 if((seq->flags == BER_FLAGS_IMPLTAG)&&(seq->class==BER_CLASS_CON)) {
3593 /* Constructed sequence of with a tag */
3594 /* dissect header and len for field */
3595 hoffset = dissect_ber_identifier(actx->pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
3596 hoffset = dissect_ber_length(actx->pinfo, tree, tvb, hoffset, NULL, NULL);
3599 length_remaining=tvb_length_remaining(tvb, hoffset);
3600 if (length_remaining>eoffset-hoffset)
3601 length_remaining=eoffset-hoffset;
3602 next_tvb = tvb_new_subset(tvb, hoffset, length_remaining, eoffset-hoffset);
3605 /* call the dissector for this field */
3606 count=seq->func(tree, tvb, hoffset, actx)-hoffset;
3607 /* hold on if we are implicit and the result is zero, i.e. the item in the sequence of
3608 doesnt match the next item, thus this implicit sequence is over, return the number of bytes
3609 we have eaten to allow the possible upper sequence continue... */
3614 /* if we didnt end up at exactly offset, then we ate too many bytes */
3615 if(offset != end_offset) {
3616 tvb_ensure_bytes_exist(tvb, offset-2, 2);
3617 causex =proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: %s Of ate %d too many bytes",
3618 (type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence", offset-end_offset);
3619 proto_item_set_expert_flags(causex, PI_MALFORMED, PI_WARN);
3620 expert_add_info_format(actx->pinfo, causex, PI_MALFORMED, PI_WARN, "BER Error:too many byte in %s",(type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence");
3626 int dissect_ber_sequence_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
3627 return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SEQUENCE, actx, parent_tree, tvb, offset, seq, hf_id, ett_id);
3630 int dissect_ber_set_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
3631 return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SET, actx, parent_tree, tvb, offset, seq, hf_id, ett_id);
3634 int 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) {
3635 return dissect_ber_old_sq_of(implicit_tag, BER_UNI_TAG_SEQUENCE, actx, parent_tree, tvb, offset, seq, hf_id, ett_id);
3638 int 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) {
3639 return dissect_ber_old_sq_of(implicit_tag, BER_UNI_TAG_SET, actx, parent_tree, tvb, offset, seq, hf_id, ett_id);
3643 dissect_ber_GeneralizedTime(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
3646 const guint8 *tmpstr;
3648 char first_delim[2];
3650 char second_delim[2];
3662 offset=dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
3663 offset=dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
3664 end_offset=offset+len;
3666 /* sanity check. we only handle universal/generalized time */
3667 if( (class!=BER_CLASS_UNI)
3668 ||(tag!=BER_UNI_TAG_GeneralizedTime)){
3669 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3670 cause = proto_tree_add_text(tree, tvb, offset, len, "BER Error: GeneralizedTime expected but class:%s(%d) %s tag:%d was unexpected", val_to_str(class,ber_class_codes,"Unknown"), class, pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tag);
3671 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
3672 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: GeneralizedTime expected");
3673 if (decode_unexpected) {
3674 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3675 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3680 len=tvb_length_remaining(tvb,offset);
3681 end_offset=offset+len;
3684 tmpstr=tvb_get_ptr(tvb, offset, len);
3686 /* those fields are allways present */
3687 strptr += g_snprintf(str, 20, "%.4s-%.2s-%.2s %.2s:%.2s:%.2s",
3688 tmpstr, tmpstr+4, tmpstr+6, tmpstr+8,
3689 tmpstr+10, tmpstr+12);
3693 sscanf( tmpstr, "%*14d%1[.,+-Z]%4d%1[+-Z]%4d", first_delim, &first_digits, second_delim, &second_digits);
3695 switch (first_delim[0]) {
3698 strptr += g_snprintf(strptr, 5, "%c%.3d", first_delim[0], first_digits);
3699 switch (second_delim[0]) {
3702 g_snprintf(strptr, 12, " (UTC%c%.4d)", second_delim[0], second_digits);
3705 g_snprintf(strptr, 7, " (UTC)");
3710 /* handle the malformed field */
3716 g_snprintf(strptr, 12, " (UTC%c%.4d)", first_delim[0], first_digits);
3719 g_snprintf(strptr, 7, " (UTC)");
3724 /* handle the malformed field */
3729 proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
3738 dissect_ber_UTCTime(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
3741 char *outstrptr = outstr;
3742 const guint8 *instr;
3752 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
3753 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL);
3755 /* sanity check: we only handle UTCTime */
3756 if( (class!=BER_CLASS_UNI) || (tag!=BER_UNI_TAG_UTCTime) ) {
3757 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3758 cause = proto_tree_add_text(tree, tvb, offset, len,
3759 "BER Error: UTCTime expected but class:%s(%d) %s tag:%d was unexpected",
3760 val_to_str(class,ber_class_codes,"Unknown"), class,
3761 pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tag);
3762 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
3763 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: UTCTime expected");
3764 if (decode_unexpected) {
3765 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3766 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3771 len = tvb_length_remaining(tvb,offset);
3774 instr = tvb_get_ptr(tvb, offset, len);
3778 if(instr[i] < '0' || instr[i] > '9') {
3779 cause = proto_tree_add_text(tree, tvb, offset, len,
3780 "BER Error: malformed UTCTime encoding, "
3781 "first 10 octets have to contain YYMMDDhhmm in digits");
3785 g_snprintf(outstrptr, 15, "%.2s-%.2s-%.2s %.2s:%.2s", instr, instr+2, instr+4, instr+6, instr+8);
3790 if(instr[i] >= '0' && instr[i] <= '9') {
3792 if(instr[i] >= '0' && instr[i] <= '9') {
3794 g_snprintf(outstrptr, 4, ":%.2s", instr+10);
3797 cause = proto_tree_add_text(tree, tvb, offset, len,
3798 "BER Error: malformed UTCTime encoding, "
3799 "if 11th octet is a digit for seconds, "
3800 "the 12th octet has to be a digit, too");
3810 cause = proto_tree_add_text(tree, tvb, offset, len,
3811 "BER Error: malformed UTCTime encoding, "
3812 "there must be no further octets after \'Z\'");
3815 g_snprintf(outstrptr, 7, " (UTC)");
3821 cause = proto_tree_add_text(tree, tvb, offset, len,
3822 "BER Error: malformed UTCTime encoding, "
3823 "4 digits must follow on \'+\' resp. \'-\'");
3826 for(n=i+1;n<i+5;n++) {
3827 if(instr[n] < '0' || instr[n] > '9') {
3828 cause = proto_tree_add_text(tree, tvb, offset, len,
3829 "BER Error: malformed UTCTime encoding, "
3830 "4 digits must follow on \'+\' resp. \'-\'");
3834 g_snprintf(outstrptr, 12, " (UTC%c%.4s)", instr[i], instr+i+1);
3838 cause = proto_tree_add_text(tree, tvb, offset, len,
3839 "BER Error: malformed UTCTime encoding, "
3840 "unexpected character in %dth octet, "
3841 "must be \'Z\', \'+\' or \'-\'", i+1);
3847 cause = proto_tree_add_text(tree, tvb, offset, len,
3848 "BER Error: malformed UTCTime encoding, "
3849 "%d unexpected character%s after %dth octet",
3850 len-i, (len==i-1?"s":""), i);
3855 proto_tree_add_string(tree, hf_id, tvb, offset, len, outstr);
3860 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
3861 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: malformed UTCTime encoding");
3862 g_snprintf(outstr, (len>29)?31:len+1, "%s", instr);
3864 proto_tree_add_string(tree, hf_id, tvb, offset, len, outstr);
3870 /* 8.6 Encoding of a bitstring value */
3871 int 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)
3877 guint8 pad=0, b0, b1, val;
3880 proto_item *item = NULL;
3882 proto_tree *tree = NULL;
3883 const asn_namedbit *nb;
3889 /* read header and len for the octet string */
3890 offset = dissect_ber_identifier(actx->pinfo, parent_tree, tvb, offset, &class, &pc, &tag);
3891 offset = dissect_ber_length(actx->pinfo, parent_tree, tvb, offset, &len, &ind);
3892 end_offset = offset + len;
3894 /* sanity check: we only handle Universal BitSrings */
3896 /* for an IMPLICIT APPLICATION tag asn2eth seems to call this
3897 function with implicit_tag = FALSE. BER_FLAGS_NOOWNTAG was
3898 set so the APPLICATION tag was still present.
3899 So here we relax it for APPLICATION tags. CONTEXT tags may
3900 still cause a problem. */
3902 if(!implicit_tag && (class!=BER_CLASS_APP)) {
3903 if( (class!=BER_CLASS_UNI)
3904 ||(tag!=BER_UNI_TAG_BITSTRING) ){
3905 tvb_ensure_bytes_exist(tvb, hoffset, 2);
3906 cause = proto_tree_add_text(parent_tree, tvb, offset, len, "BER Error: BitString expected but class:%s(%d) %s tag:%d was unexpected", val_to_str(class,ber_class_codes,"Unknown"), class, pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, tag);
3907 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
3908 expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "BER Error: BitString expected");
3909 if (decode_unexpected) {
3910 proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown);
3911 dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree);
3918 len=tvb_length_remaining(tvb,offset);
3919 end_offset=offset+len;
3922 actx->created_item = NULL;
3929 pad = tvb_get_guint8(tvb, offset);
3930 if(pad == 0 && len == 1) {
3932 proto_tree_add_item(parent_tree, hf_ber_bitstring_empty, tvb, offset, 1, FALSE);
3935 proto_tree_add_item(parent_tree, hf_ber_bitstring_padding, tvb, offset, 1, FALSE);
3940 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, FALSE);
3941 actx->created_item= item;
3943 tree = proto_item_add_subtree(item, ett_id);
3947 if(len<=(guint32)tvb_length_remaining(tvb, offset)){
3948 *out_tvb = tvb_new_subset(tvb, offset, len, len);
3950 *out_tvb = tvb_new_subset(tvb, offset, -1, -1);
3960 if(nb->bit < (8*len-pad)) {
3961 val = tvb_get_guint8(tvb, offset + nb->bit/8);
3962 val &= 0x80 >> (nb->bit%8);
3963 b0 = (nb->gb0 == -1) ? nb->bit/8 :
3964 ((guint32)nb->gb0)/8;
3965 b1 = (nb->gb1 == -1) ? nb->bit/8 :
3966 ((guint32)nb->gb1)/8;
3967 proto_tree_add_item(tree, *(nb->p_id), tvb, offset + b0, b1 - b0 + 1, FALSE);
3968 } else { /* 8.6.2.4 */
3970 proto_tree_add_boolean(tree, *(nb->p_id), tvb, offset + len, 0, 0x00);
3973 if(item && nb->tstr) {
3974 proto_item_append_text(item, "%s%s", sep, nb->tstr);
3979 if(item && nb->fstr) {
3980 proto_item_append_text(item, "%s%s", sep, nb->fstr);
3988 proto_item_append_text(item, ")");
3994 int 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)
3996 tvbuff_t *tmp_tvb = NULL;
4000 header_field_info *hfi;
4003 unsigned int i, tvb_len;
4005 offset = dissect_ber_bitstring(implicit_tag, actx, parent_tree, tvb, offset, NULL, hf_id, ett_id, &tmp_tvb);
4007 tree = proto_item_get_subtree(actx->created_item);
4008 if(bit_fields && tree && tmp_tvb) {
4009 /* tmp_tvb points to the actual bitstring (including any pad bits at the end.
4010 * note that this bitstring is not neccessarily always encoded as 4 bytes
4011 * so we have to read it byte by byte.
4014 tvb_len=tvb_length(tmp_tvb);
4018 val|=tvb_get_guint8(tmp_tvb,i);
4025 proto_tree_add_boolean(tree, **bf, tmp_tvb, 0, tvb_len, val);
4027 hfi = proto_registrar_get_nth(**bf);
4028 if(val & hfi->bitmask) {
4029 proto_item_append_text(actx->created_item, "%s%s", sep, hfi->name);
4037 proto_item_append_text(actx->created_item, ")");
4047 * 8.18 Encoding of a value of the external type
4048 * 8.18.1 The encoding of a value of the external type shall be the BER encoding of the following
4049 * sequence type, assumed to be defined in an environment of EXPLICIT TAGS,
4050 * with a value as specified in the subclauses below:
4052 * [UNIVERSAL 8] IMPLICIT SEQUENCE {
4053 * direct-reference OBJECT IDENTIFIER OPTIONAL,
4054 * indirect-reference INTEGER OPTIONAL,
4055 * data-value-descriptor ObjectDescriptor OPTIONAL,
4057 * single-ASN1-type [0] ABSTRACT-SYNTAX.&Type,
4058 * octet-aligned [1] IMPLICIT OCTET STRING,
4059 * arbitrary [2] IMPLICIT BIT STRING } }
4064 dissect_ber_INTEGER(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
4065 offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
4066 &actx->external.indirect_reference);
4067 actx->external.indirect_ref_present = TRUE;
4073 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_)
4075 if (actx->external.u.ber.ber_callback) {
4076 offset = actx->external.u.ber.ber_callback(FALSE, tvb, offset, actx, tree, hf_index);
4077 } else if (actx->external.direct_ref_present &&
4078 dissector_get_string_handle(ber_oid_dissector_table, actx->external.direct_reference)) {
4079 offset = call_ber_oid_callback(actx->external.direct_reference, tvb, offset, actx->pinfo, tree);
4081 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index, &actx->external.octet_aligned);
4087 dissect_ber_OBJECT_IDENTIFIER(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
4089 offset = dissect_ber_object_identifier_str(implicit_tag, actx, tree, tvb, offset, hf_index, &actx->external.direct_reference);
4090 actx->external.direct_ref_present = TRUE;
4096 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_)
4098 offset = dissect_ber_restricted_string(implicit_tag, BER_UNI_TAG_ObjectDescriptor,
4099 actx, tree, tvb, offset, hf_index,
4100 &actx->external.data_value_descriptor);
4106 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_)
4108 if (actx->external.u.ber.ber_callback) {
4109 offset = actx->external.u.ber.ber_callback(FALSE, tvb, offset, actx, tree, hf_index);
4111 offset = call_ber_oid_callback(actx->external.direct_reference, tvb, offset, actx->pinfo, tree);
4118 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_)
4120 if (actx->external.u.ber.ber_callback) {
4121 offset = actx->external.u.ber.ber_callback(FALSE, tvb, offset, actx, tree, hf_index);
4123 offset = dissect_ber_bitstring(implicit_tag, actx, tree, tvb, offset,
4124 NULL, hf_index, -1, &actx->external.arbitrary);
4130 static const value_string ber_T_encoding_vals[] = {
4131 { 0, "single-ASN1-type" },
4132 { 1, "octet-aligned" },
4137 static const ber_choice_t T_encoding_choice[] = {
4138 { 0, &hf_ber_single_ASN1_type, BER_CLASS_CON, 0, 0, dissect_ber_T_single_ASN1_type },
4139 { 1, &hf_ber_octet_aligned , BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_ber_T_octet_aligned },
4140 { 2, &hf_ber_arbitrary , BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_ber_T_arbitrary },
4141 { 0, NULL, 0, 0, 0, NULL }
4146 dissect_ber_T_encoding(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
4147 offset = dissect_ber_choice(actx, tree, tvb, offset,
4148 T_encoding_choice, hf_index, ett_ber_T_encoding,
4149 &actx->external.encoding);
4155 static const ber_sequence_t external_U_sequence[] = {
4156 { &hf_ber_direct_reference, BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ber_OBJECT_IDENTIFIER },
4157 { &hf_ber_indirect_reference, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ber_INTEGER },
4158 { &hf_ber_data_value_descriptor, BER_CLASS_UNI, BER_UNI_TAG_ObjectDescriptor, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ber_ObjectDescriptor },
4159 { &hf_ber_encoding , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_ber_T_encoding },
4160 { NULL, 0, 0, 0, NULL }
4163 dissect_ber_external_U(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_ , proto_tree *tree, int hf_index _U_)
4165 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
4166 external_U_sequence, hf_index, ett_ber_EXTERNAL);
4171 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){
4173 actx->external.u.ber.ber_callback = func;
4175 offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
4176 hf_id, BER_CLASS_UNI, BER_UNI_TAG_EXTERNAL, TRUE, dissect_ber_external_U);
4178 asn1_ctx_clean_external(actx);
4184 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_){
4187 offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
4188 hf_id, BER_CLASS_UNI, BER_UNI_TAG_EMBEDDED_PDV, TRUE, dissect_ber_external_U);
4194 dissect_ber(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4198 if (check_col(pinfo->cinfo, COL_PROTOCOL))
4199 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BER");
4201 if (check_col(pinfo->cinfo, COL_DEF_SRC))
4202 col_set_str(pinfo->cinfo, COL_DEF_SRC, "BER encoded file");
4204 if(!decode_as_syntax) {
4206 /* if we got here we couldn't find anything better */
4207 if (check_col(pinfo->cinfo, COL_INFO)) {
4208 col_clear(pinfo->cinfo, COL_INFO);
4209 col_append_str(pinfo->cinfo, COL_INFO, "Unknown BER");
4212 (void) dissect_unknown_ber(pinfo, tvb, 0, tree);
4216 (void) call_ber_syntax_callback(decode_as_syntax, tvb, 0, pinfo, tree);
4218 if (check_col(pinfo->cinfo, COL_INFO)) {
4220 /* see if we have a better name */
4221 name = get_ber_oid_syntax(decode_as_syntax);
4223 col_clear(pinfo->cinfo, COL_INFO);
4224 col_append_fstr(pinfo->cinfo, COL_INFO, "Decoded as %s", name ? name : decode_as_syntax);
4230 proto_register_ber(void)
4232 static hf_register_info hf[] = {
4233 { &hf_ber_id_class, {
4234 "Class", "ber.id.class", FT_UINT8, BASE_DEC,
4235 VALS(ber_class_codes), 0xc0, "Class of BER TLV Identifier", HFILL }},
4236 { &hf_ber_bitstring_padding, {
4237 "Padding", "ber.bitstring.padding", FT_UINT8, BASE_DEC,
4238 NULL, 0x0, "Number of unsused bits in the last octet of the bitstring", HFILL }},
4239 { &hf_ber_bitstring_empty, {
4240 "Empty", "ber.bitstring.empty", FT_UINT8, BASE_DEC,
4241 NULL, 0x0, "This is an empty bitstring", HFILL }},
4243 "P/C", "ber.id.pc", FT_BOOLEAN, 8,
4244 TFS(&ber_pc_codes), 0x20, "Primitive or Constructed BER encoding", HFILL }},
4245 { &hf_ber_id_uni_tag, {
4246 "Tag", "ber.id.uni_tag", FT_UINT8, BASE_DEC,
4247 VALS(ber_uni_tag_codes), 0x1f, "Universal tag type", HFILL }},
4248 { &hf_ber_id_uni_tag_ext, {
4249 "Tag", "ber.id.uni_tag", FT_UINT32, BASE_DEC,
4250 NULL, 0, "Universal tag type", HFILL }},
4252 "Tag", "ber.id.tag", FT_UINT8, BASE_DEC,
4253 NULL, 0x1f, "Tag value for non-Universal classes", HFILL }},
4254 { &hf_ber_id_tag_ext, {
4255 "Tag", "ber.id.tag", FT_UINT32, BASE_DEC,
4256 NULL, 0, "Tag value for non-Universal classes", HFILL }},
4258 "Length", "ber.length", FT_UINT32, BASE_DEC,
4259 NULL, 0, "Length of contents", HFILL }},
4260 { &hf_ber_unknown_OCTETSTRING, {
4261 "OCTETSTRING", "ber.unknown.OCTETSTRING", FT_BYTES, BASE_HEX,
4262 NULL, 0, "This is an unknown OCTETSTRING", HFILL }},
4263 { &hf_ber_unknown_BER_OCTETSTRING, {
4264 "OCTETSTRING [BER encoded]", "ber.unknown.OCTETSTRING", FT_NONE, BASE_HEX,
4265 NULL, 0, "This is an BER encoded OCTETSTRING", HFILL }},
4266 { &hf_ber_unknown_OID, {
4267 "OID", "ber.unknown.OID", FT_OID, BASE_NONE,
4268 NULL, 0, "This is an unknown Object Identifier", HFILL }},
4269 { &hf_ber_unknown_GraphicString, {
4270 "GRAPHICSTRING", "ber.unknown.GRAPHICSTRING", FT_STRING, BASE_HEX,
4271 NULL, 0, "This is an unknown GRAPHICSTRING", HFILL }},
4272 { &hf_ber_unknown_NumericString, {
4273 "NumericString", "ber.unknown.NumericString", FT_STRING, BASE_NONE,
4274 NULL, 0, "This is an unknown NumericString", HFILL }},
4275 { &hf_ber_unknown_PrintableString, {
4276 "PrintableString", "ber.unknown.PrintableString", FT_STRING, BASE_NONE,
4277 NULL, 0, "This is an unknown PrintableString", HFILL }},
4278 { &hf_ber_unknown_TeletexString, {
4279 "TeletexString", "ber.unknown.TeletexString", FT_STRING, BASE_NONE,
4280 NULL, 0, "This is an unknown TeletexString", HFILL }},
4281 { &hf_ber_unknown_VisibleString, {
4282 "VisibleString", "ber.unknown.VisibleString", FT_STRING, BASE_NONE,
4283 NULL, 0, "This is an unknown VisibleString", HFILL }},
4284 { &hf_ber_unknown_GeneralString, {
4285 "GeneralString", "ber.unknown.GeneralString", FT_STRING, BASE_NONE,
4286 NULL, 0, "This is an unknown GeneralString", HFILL }},
4287 { &hf_ber_unknown_UniversalString, {
4288 "UniversalString", "ber.unknown.UniversalString", FT_STRING, BASE_NONE,
4289 NULL, 0, "This is an unknown UniversalString", HFILL }},
4290 { &hf_ber_unknown_BMPString, {
4291 "BMPString", "ber.unknown.BMPString", FT_STRING, BASE_NONE,
4292 NULL, 0, "This is an unknown BMPString", HFILL }},
4293 { &hf_ber_unknown_IA5String, {
4294 "IA5String", "ber.unknown.IA5String", FT_STRING, BASE_NONE,
4295 NULL, 0, "This is an unknown IA5String", HFILL }},
4296 { &hf_ber_unknown_UTCTime, {
4297 "UTCTime", "ber.unknown.UTCTime", FT_STRING, BASE_NONE,
4298 NULL, 0, "This is an unknown UTCTime", HFILL }},
4299 { &hf_ber_unknown_UTF8String, {
4300 "UTF8String", "ber.unknown.UTF8String", FT_STRING, BASE_NONE,
4301 NULL, 0, "This is an unknown UTF8String", HFILL }},
4302 { &hf_ber_unknown_GeneralizedTime, {
4303 "GeneralizedTime", "ber.unknown.GeneralizedTime", FT_STRING, BASE_NONE,
4304 NULL, 0, "This is an unknown GeneralizedTime", HFILL }},
4305 { &hf_ber_unknown_INTEGER, {
4306 "INTEGER", "ber.unknown.INTEGER", FT_UINT32, BASE_DEC,
4307 NULL, 0, "This is an unknown INTEGER", HFILL }},
4308 { &hf_ber_unknown_BITSTRING, {
4309 "BITSTRING", "ber.unknown.BITSTRING", FT_BYTES, BASE_DEC,
4310 NULL, 0, "This is an unknown BITSTRING", HFILL }},
4311 { &hf_ber_unknown_BOOLEAN, {
4312 "BOOLEAN", "ber.unknown.BOOLEAN", FT_UINT8, BASE_HEX,
4313 NULL, 0, "This is an unknown BOOLEAN", HFILL }},
4314 { &hf_ber_unknown_ENUMERATED, {
4315 "ENUMERATED", "ber.unknown.ENUMERATED", FT_UINT32, BASE_DEC,
4316 NULL, 0, "This is an unknown ENUMERATED", HFILL }},
4317 { &hf_ber_constructed_OCTETSTRING, {
4318 "OCTETSTRING", "ber.constructed.OCTETSTRING", FT_BYTES, BASE_HEX,
4319 NULL, 0, "This is a component of an constructed OCTETSTRING", HFILL }},
4321 "No OID", "ber.no_oid", FT_NONE, BASE_NONE,
4322 NULL, 0, "No OID supplied to call_ber_oid_callback", HFILL }},
4323 { &hf_ber_oid_not_implemented, {
4324 "OID not implemented", "ber.oid_not_implemented", FT_NONE, BASE_NONE,
4325 NULL, 0, "Dissector for OID not implemented", HFILL }},
4326 { &hf_ber_direct_reference,
4327 { "direct-reference", "ber.direct_reference",
4328 FT_OID, BASE_NONE, NULL, 0,
4329 "ber.OBJECT_IDENTIFIER", HFILL }},
4330 { &hf_ber_indirect_reference,
4331 { "indirect-reference", "ber.indirect_reference",
4332 FT_INT32, BASE_DEC, NULL, 0,
4333 "ber.INTEGER", HFILL }},
4334 { &hf_ber_data_value_descriptor,
4335 { "data-value-descriptor", "ber.data_value_descriptor",
4336 FT_STRING, BASE_NONE, NULL, 0,
4337 "ber.ObjectDescriptor", HFILL }},
4339 { "encoding", "ber.encoding",
4340 FT_UINT32, BASE_DEC, VALS(ber_T_encoding_vals), 0,
4341 "ber.T_encoding", HFILL }},
4342 { &hf_ber_octet_aligned,
4343 { "octet-aligned", "ber.octet_aligned",
4344 FT_BYTES, BASE_HEX, NULL, 0,
4345 "ber.T_octet_aligned", HFILL }},
4346 { &hf_ber_arbitrary,
4347 { "arbitrary", "ber.arbitrary",
4348 FT_BYTES, BASE_HEX, NULL, 0,
4349 "ber.T_arbitrary", HFILL }},
4350 { &hf_ber_single_ASN1_type,
4351 { "single-ASN1-type", "ber.single_ASN1_type",
4352 FT_NONE, BASE_NONE, NULL, 0,
4353 "ber.T_single_ASN1_type", HFILL }},
4357 static gint *ett[] = {
4358 &ett_ber_octet_string,
4362 &ett_ber_T_encoding,
4364 module_t *ber_module;
4366 proto_ber = proto_register_protocol("Basic Encoding Rules (ASN.1 X.690)", "BER", "ber");
4367 proto_register_field_array(proto_ber, hf, array_length(hf));
4368 proto_register_subtree_array(ett, array_length(ett));
4370 proto_set_cant_toggle(proto_ber);
4372 /* Register preferences */
4373 ber_module = prefs_register_protocol(proto_ber, NULL);
4374 prefs_register_bool_preference(ber_module, "show_internals",
4375 "Show internal BER encapsulation tokens",
4376 "Whether the dissector should also display internal"
4377 " ASN.1 BER details such as Identifier and Length fields", &show_internal_ber_fields);
4378 prefs_register_bool_preference(ber_module, "decode_unexpected",
4379 "Decode unexpected tags as BER encoded data",
4380 "Whether the dissector should decode unexpected tags as"
4381 " ASN.1 BER encoded data", &decode_unexpected);
4382 prefs_register_bool_preference(ber_module, "decode_octetstring",
4383 "Decode OCTET STRING as BER encoded data",
4384 "Whether the dissector should try decoding OCTET STRINGs as"
4385 " constructed ASN.1 BER encoded data", &decode_octetstring_as_ber);
4387 ber_oid_dissector_table = register_dissector_table("ber.oid", "BER OID Dissectors", FT_STRING, BASE_NONE);
4388 ber_syntax_dissector_table = register_dissector_table("ber.syntax", "BER Syntax Dissectors", FT_STRING, BASE_NONE);
4389 syntax_table=g_hash_table_new(g_str_hash, g_str_equal); /* oid to syntax */
4393 proto_reg_handoff_ber(void)
4395 dissector_handle_t ber_handle;
4398 oid_add_from_string("asn1","2.1");
4399 oid_add_from_string("basic-encoding","2.1.1");
4401 ber_handle = create_dissector_handle(dissect_ber, proto_ber);
4402 dissector_add("wtap_encap", WTAP_ENCAP_BER, ber_handle);
4405 gboolean oid_has_dissector(const char *oid) {
4406 return(dissector_get_string_handle(ber_oid_dissector_table, oid) != NULL);