removed some gcc warnings (hopefully)
[obnox/wireshark/wip.git] / epan / dissectors / packet-ber.c
1 /*#define DEBUG_BER 1*/
2 /* TODO: change #.REGISTER signature to new_dissector_t and
3  * update call_ber_oid_callback() accordingly.
4  */
5 /* packet-ber.c
6  * Helpers for ASN.1/BER dissection
7  * Ronnie Sahlberg (C) 2004
8  *
9  * $Id$
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@ethereal.com>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 /* 
31  * ITU-T Recommendation X.690 (07/2002),
32  *   Information technology ASN.1 encoding rules:
33  *     Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)
34  * 
35  */ 
36
37 #ifdef HAVE_CONFIG_H
38 # include "config.h"
39 #endif
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <ctype.h>
44
45 #include <glib.h>
46
47 #include <epan/packet.h>
48
49 #include <epan/strutil.h>
50 #include <epan/prefs.h>
51 #include "packet-ber.h"
52
53
54 static gint proto_ber = -1;
55 static gint hf_ber_id_class = -1;
56 static gint hf_ber_id_pc = -1;
57 static gint hf_ber_id_uni_tag = -1;
58 static gint hf_ber_id_tag = -1;
59 static gint hf_ber_length = -1;
60 static gint hf_ber_bitstring_padding = -1;
61 static gint hf_ber_unknown_OID = -1;
62 static gint hf_ber_unknown_OCTETSTRING = -1;
63 static gint hf_ber_unknown_NumericString = -1;
64 static gint hf_ber_unknown_PrintableString = -1;
65 static gint hf_ber_unknown_IA5String = -1;
66 static gint hf_ber_unknown_INTEGER = -1;
67 static gint hf_ber_unknown_ENUMERATED = -1;
68
69 static gint ett_ber_octet_string = -1;
70 static gint ett_ber_unknown = -1;
71 static gint ett_ber_SEQUENCE = -1;
72
73 static gboolean show_internal_ber_fields = FALSE;
74
75 proto_item *ber_last_created_item=NULL;
76
77 static dissector_table_t ber_oid_dissector_table=NULL;
78
79 static const value_string ber_class_codes[] = {
80         { BER_CLASS_UNI,        "Universal" },
81         { BER_CLASS_APP,        "Application" },
82         { BER_CLASS_CON,        "Context Specific" },
83         { BER_CLASS_PRI,        "Private" },
84         { 0, NULL }
85 };
86
87 static const true_false_string ber_pc_codes = {
88         "Constructed Encoding",
89         "Primitive Encoding"
90 };
91
92 static const value_string ber_uni_tag_codes[] = {
93         { BER_UNI_TAG_EOC                               , "'end-of-content'" },
94         { BER_UNI_TAG_BOOLEAN                   , "BOOLEAN" },
95         { BER_UNI_TAG_INTEGER                   , "INTEGER" },
96         { BER_UNI_TAG_BITSTRING         , "BIT STRING" },
97         { BER_UNI_TAG_OCTETSTRING               , "OCTET STRING" },
98         { BER_UNI_TAG_NULL                      , "NULL" },
99         { BER_UNI_TAG_OID                               , "OBJECT IDENTIFIER" },
100         { BER_UNI_TAG_ObjectDescriptor, "ObjectDescriptor" },
101         { BER_UNI_TAG_REAL                      , "REAL" },
102         { BER_UNI_TAG_ENUMERATED                , "ENUMERATED" },
103         { BER_UNI_TAG_EMBEDDED_PDV      , "EMBEDDED PDV" },
104         { BER_UNI_TAG_UTF8String                , "UTF8String" },
105         { BER_UNI_TAG_RELATIVE_OID      , "RELATIVE-OID" },
106         { BER_UNI_TAG_SEQUENCE          , "SEQUENCE, SEQUENCE OF" },
107         { BER_UNI_TAG_SET                               , "SET, SET OF" },
108         { BER_UNI_TAG_NumericString     , "NumericString" },
109         { BER_UNI_TAG_PrintableString   , "PrintableString" },
110         { BER_UNI_TAG_TeletexString     , "TeletexString, T61String" },
111         { BER_UNI_TAG_VideotexString    , "VideotexString" },
112         { BER_UNI_TAG_IA5String         , "IA5String" },
113         { BER_UNI_TAG_UTCTime           , "UTCTime" },
114         { BER_UNI_TAG_GeneralizedTime   , "GeneralizedTime" },
115         { BER_UNI_TAG_GraphicString     , "GraphicString" },
116         { BER_UNI_TAG_VisibleString     , "VisibleString, ISO64String" },
117         { BER_UNI_TAG_GeneralString     , "GeneralString" },
118         { BER_UNI_TAG_UniversalString   , "UniversalString" },
119         { BER_UNI_TAG_CHARACTERSTRING   , "CHARACTER STRING" },
120         { BER_UNI_TAG_BMPString         , "BMPString" },
121         { 0, NULL }
122 };
123
124
125 proto_item *get_ber_last_created_item(void) {
126   return ber_last_created_item;
127 }
128
129
130 static GHashTable *oid_table=NULL;
131
132 void
133 dissect_ber_oid_NULL_callback(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_)
134 {
135         return;
136 }
137
138 void
139 register_ber_oid_dissector(char *oid, dissector_t dissector, int proto, char *name)
140 {
141         dissector_handle_t dissector_handle;
142
143         dissector_handle=create_dissector_handle(dissector, proto);
144         dissector_add_string("ber.oid", oid, dissector_handle);
145         g_hash_table_insert(oid_table, oid, name);
146 }
147 /* Register the oid name to get translation in proto dissection */
148 void
149 register_ber_oid_name(char *oid, char *name)
150 {
151         g_hash_table_insert(oid_table, oid, name);
152 }
153
154 /* Get oid name fom has table to get translation in proto dissection(packet-per.c) */
155 char *
156 get_ber_oid_name(char *oid)
157 {
158         return g_hash_table_lookup(oid_table, oid);
159 }
160
161
162 /* this function tries to dissect an unknown blob as much as possible.
163  * everytime this function is called it is a failure to implement a proper
164  * dissector in ethereal.
165  * something is missing, so dont become too comfy with this one,
166  * when it is called it is a BAD thing  not a good thing.
167  * It can not handle IMPLICIT tags nor indefinite length.
168  */
169 static int
170 dissect_unknown_ber(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree)
171 {
172         int start_offset;
173         guint8 class;
174         gboolean pc, ind;
175         guint32 tag;
176         guint32 len;
177         proto_item *item=NULL;
178         proto_tree *next_tree=NULL;
179
180         start_offset=offset;
181
182         offset=dissect_ber_identifier(pinfo, NULL, tvb, offset, &class, &pc, &tag);
183         offset=dissect_ber_length(pinfo, NULL, tvb, offset, &len, &ind);
184
185         if(len>(guint32)tvb_length_remaining(tvb, offset)){
186                 /* hmm   maybe something bad happened or the frame is short,
187                    since these are not vital outputs just return instead of 
188                    throwing en exception.
189                  */
190                 proto_tree_add_text(tree, tvb, offset, len, "BER: Error length:%d longer than tvb_length_ramaining:%d",len, tvb_length_remaining(tvb, offset));
191                 return tvb_length(tvb);
192         }
193
194         switch(class){
195         case BER_CLASS_UNI:
196                 switch(tag){
197                 case BER_UNI_TAG_INTEGER:
198                         offset = dissect_ber_integer(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_INTEGER, NULL);
199                         break;
200                 case BER_UNI_TAG_ENUMERATED:
201                         offset = dissect_ber_integer(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_ENUMERATED, NULL);
202                         break;
203                 case BER_UNI_TAG_OCTETSTRING:
204                         offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_OCTETSTRING, NULL);
205                         break;
206                 case BER_UNI_TAG_OID:
207                         offset=dissect_ber_object_identifier(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_OID, NULL);
208                         break;
209                 case BER_UNI_TAG_SEQUENCE:
210                         item=proto_tree_add_text(tree, tvb, start_offset, len, "SEQUENCE");
211                         if(item){
212                                 next_tree=proto_item_add_subtree(item, ett_ber_SEQUENCE);
213                         }
214                         offset=dissect_unknown_ber(pinfo, tvb, offset, next_tree);
215                         break;
216                 case BER_UNI_TAG_NumericString:
217                         offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_NumericString, NULL);
218                         break;
219                 case BER_UNI_TAG_PrintableString:
220                         offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_PrintableString, NULL);
221                         break;
222                 case BER_UNI_TAG_IA5String:
223                         offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_IA5String, NULL);
224                         break;
225                 default:
226                         proto_tree_add_text(tree, tvb, offset, len, "BER: Error can not handle universal tag:%d",tag);
227                         offset += len;
228                 }
229                 break;
230         case BER_CLASS_CON:
231                 item=proto_tree_add_text(tree, tvb, start_offset, len, "[%d]",tag);
232                 if(item){
233                         next_tree=proto_item_add_subtree(item, ett_ber_SEQUENCE);
234                 }
235                 offset=dissect_unknown_ber(pinfo, tvb, offset, next_tree);
236                 break;
237         default:
238                 proto_tree_add_text(tree, tvb, offset, len, "BER: Error can not handle class:%d (0x%02x)",class,tvb_get_guint8(tvb, start_offset));
239                 /* some printout here? aborting dissection */
240                 return tvb_length(tvb);
241         }
242
243         /* were there more data to eat? */
244         if(offset<(int)tvb_length(tvb)){
245                 offset=dissect_unknown_ber(pinfo, tvb, offset, tree);
246         }
247
248         return offset;
249 }
250
251
252 int
253 call_ber_oid_callback(char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
254 {
255         tvbuff_t *next_tvb;
256
257         next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_length_remaining(tvb, offset));
258         if(!dissector_try_string(ber_oid_dissector_table, oid, next_tvb, pinfo, tree)){
259                 proto_item *item=NULL;
260                 proto_tree *next_tree=NULL;
261
262                 item=proto_tree_add_text(tree, next_tvb, 0, tvb_length_remaining(tvb, offset), "BER: Dissector for OID:%s not implemented. Contact Ethereal developers if you want this supported", oid);
263                 if(item){
264                         next_tree=proto_item_add_subtree(item, ett_ber_unknown);
265                 }
266                 dissect_unknown_ber(pinfo, next_tvb, offset, next_tree);
267         }
268
269         /*XXX until we change the #.REGISTER signature for _PDU()s 
270          * into new_dissector_t   we have to do this kludge with
271          * manually step past the content in the ANY type.
272          */
273         offset+=tvb_length_remaining(tvb, offset);
274
275         return offset;
276 }
277
278
279 static int dissect_ber_sq_of(gboolean implicit_tag, gint32 type, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id);
280
281 /* 8.1 General rules for encoding */
282
283 /*  8.1.2 Identifier octets */
284 int get_ber_identifier(tvbuff_t *tvb, int offset, gint8 *class, gboolean *pc, gint32 *tag) {
285         guint8 id, t;
286         gint8 tmp_class;
287         gboolean tmp_pc;
288         gint32 tmp_tag;
289
290         id = tvb_get_guint8(tvb, offset);
291         offset += 1;
292         
293         /* 8.1.2.2 */
294         tmp_class = (id>>6) & 0x03;
295         tmp_pc = (id>>5) & 0x01;
296         tmp_tag = id&0x1F;
297         /* 8.1.2.4 */
298         if (tmp_tag == 0x1F) {
299                 tmp_tag = 0;
300                 while (tvb_length_remaining(tvb, offset) > 0) {
301                         t = tvb_get_guint8(tvb, offset);
302                         offset += 1;
303                         tmp_tag <<= 7;       
304                         tmp_tag |= t & 0x7F;
305                         if (t & 0x80) break;
306                 }
307         }
308
309         if (class)
310                 *class = tmp_class;
311         if (pc)
312                 *pc = tmp_pc;
313         if (tag)
314                 *tag = tmp_tag;
315
316         return offset;
317 }
318
319 int dissect_ber_identifier(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gint8 *class, gboolean *pc, gint32 *tag) 
320 {
321         int old_offset = offset;
322         gint8 tmp_class;
323         gboolean tmp_pc;
324         gint32 tmp_tag;
325
326         offset = get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
327         
328         if(show_internal_ber_fields){
329                 proto_tree_add_uint(tree, hf_ber_id_class, tvb, old_offset, 1, tmp_class<<6);
330                 proto_tree_add_boolean(tree, hf_ber_id_pc, tvb, old_offset, 1, (tmp_pc)?0x20:0x00);
331                 if(tmp_class==BER_CLASS_UNI){
332                         proto_tree_add_uint(tree, hf_ber_id_uni_tag, tvb, old_offset, offset - old_offset, tmp_tag);
333                 } else {
334                         proto_tree_add_uint(tree, hf_ber_id_tag, tvb, old_offset, offset - old_offset, tmp_tag);
335                 }
336         }
337
338         if (class)
339                 *class = tmp_class;
340         if (pc)
341                 *pc = tmp_pc;
342         if (tag)
343                 *tag = tmp_tag;
344
345         return offset;
346 }
347
348 /* this function gets the length octets of the BER TLV.
349  * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
350  */
351 /* 8.1.3 Length octets */
352 int
353 get_ber_length(tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind) {
354         guint8 oct, len;
355         guint32 tmp_length;
356         gboolean tmp_ind;
357
358         tmp_length = 0;
359         tmp_ind = FALSE;
360
361         oct = tvb_get_guint8(tvb, offset);
362         offset += 1;
363         
364         if (!(oct&0x80)) {
365                 /* 8.1.3.4 */
366                 tmp_length = oct;
367         } else {
368                 len = oct & 0x7F;
369                 if (len) {
370                         /* 8.1.3.5 */
371                         while (len--) {
372                                 oct = tvb_get_guint8(tvb, offset);
373                                 offset++;
374                                 tmp_length = (tmp_length<<8) + oct;
375                         }
376                 } else {
377                         /* 8.1.3.6 */
378                         tmp_ind = TRUE;
379                         /* TO DO */
380                 }
381         }
382
383         if (length)
384                 *length = tmp_length;
385         if (ind)
386                 *ind = tmp_ind;
387
388         return offset;
389 }
390
391 /* this function dissects the length octets of the BER TLV.
392  * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
393  */
394 int
395 dissect_ber_length(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind)
396 {
397         int old_offset = offset;
398         guint32 tmp_length;
399         gboolean tmp_ind;
400
401         offset = get_ber_length(tvb, offset, &tmp_length, &tmp_ind);
402         
403         if(show_internal_ber_fields){
404                 if(tmp_ind){
405                         proto_tree_add_text(tree, tvb, old_offset, 1, "Length: Indefinite length");
406                 } else {
407                         proto_tree_add_uint(tree, hf_ber_length, tvb, old_offset, offset - old_offset, tmp_length);
408                 }
409         }
410         if (length)
411                 *length = tmp_length;
412         if (ind)
413                 *ind = tmp_ind;
414         return offset;
415 }
416
417 /* 8.7 Encoding of an octetstring value */
418 int 
419 dissect_ber_octet_string(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb) {
420         guint8 class;
421         gboolean pc, ind;
422         guint32 tag;
423         guint32 len;
424         int end_offset;
425         proto_item *it;
426
427 #ifdef DEBUG_BER
428 {
429 char *name;
430 header_field_info *hfinfo;
431 if(hf_id>0){
432 hfinfo = proto_registrar_get_nth(hf_id);
433 name=hfinfo->name;
434 } else {
435 name="unnamed";
436 }
437 if(tvb_length_remaining(tvb,offset)>3){
438 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));
439 }else{
440 printf("OCTET STRING dissect_ber_octet_string(%s) entered\n",name);
441 }
442 }
443 #endif
444
445         if (!implicit_tag) {
446                 /* read header and len for the octet string */
447                 offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
448                 offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, &ind);
449                 end_offset=offset+len;
450         
451                 /* sanity check: we only handle Constructed Universal Sequences */
452                 if( (class!=BER_CLASS_UNI) 
453                   ||((tag<BER_UNI_TAG_NumericString)&&(tag!=BER_UNI_TAG_OCTETSTRING)&&(tag!=BER_UNI_TAG_UTF8String)) ){
454                     proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: OctetString expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
455                         return end_offset;
456                 }
457         } else {
458                 /* implicit tag so just trust the length of the tvb */
459                 pc=FALSE;
460                 len=tvb_length_remaining(tvb,offset);
461                 end_offset=offset+len;
462         }               
463
464         ber_last_created_item = NULL;
465         if (pc) {
466                 /* constructed */
467                 /* TO DO */
468         } else {
469                 /* primitive */
470                 if (hf_id != -1) {
471                         it = proto_tree_add_item(tree, hf_id, tvb, offset, len, FALSE);
472                         ber_last_created_item = it;
473                 }
474                 if (out_tvb) {
475                         if(len<=(guint32)tvb_length_remaining(tvb, offset)){
476                                 *out_tvb = tvb_new_subset(tvb, offset, len, len);
477                         } else {
478                                 *out_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_length_remaining(tvb, offset));
479                         }
480                 }
481         }
482         return end_offset;
483 }
484
485 int dissect_ber_octet_string_wcb(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, ber_callback func)
486 {
487         tvbuff_t *out_tvb;
488
489         offset = dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, offset, hf_id, (func)?&out_tvb:NULL);
490         if (func && (tvb_length(out_tvb)>0)) {
491                 if (hf_id != -1)
492                         tree = proto_item_add_subtree(ber_last_created_item, ett_ber_octet_string);
493                 func(pinfo, tree, out_tvb, 0);
494         }
495         return offset;
496 }
497
498
499 int
500 dissect_ber_integer(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, guint32 *value)
501 {
502         guint8 class;
503         gboolean pc;
504         guint32 tag;
505         guint32 len;
506         gint32 val;
507         gint64 val64;
508         guint32 i;
509
510 #ifdef DEBUG_BER
511 {
512 char *name;
513 header_field_info *hfinfo;
514 if(hf_id>0){
515 hfinfo = proto_registrar_get_nth(hf_id);
516 name=hfinfo->name;
517 } else {
518 name="unnamed";
519 }
520 if(tvb_length_remaining(tvb,offset)>3){
521 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));
522 }else{
523 printf("INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d len:%d\n",name,implicit_tag,len);
524 }
525 }
526 #endif
527
528
529         if(!implicit_tag){
530           offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
531           offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
532         } else {
533           len=tvb_length_remaining(tvb, offset);
534         }
535
536         /* ok,  we cant handle >4 byte integers so lets fake them */
537         if(len>8){
538                 header_field_info *hfinfo;
539                 proto_item *pi;
540
541                 hfinfo = proto_registrar_get_nth(hf_id);
542                 pi=proto_tree_add_text(tree, tvb, offset, len, "%s : 0x", hfinfo->name);
543                 if(pi){
544                         for(i=0;i<len;i++){
545                                 proto_item_append_text(pi,"%02x",tvb_get_guint8(tvb, offset));
546                                 offset++;
547                         }
548                 }
549                 return offset;
550         }
551         if(len>4){
552                 header_field_info *hfinfo;
553
554                 val64=0;
555                 if (len > 0) {
556                         /* extend sign bit */
557                         val64 = (gint8)tvb_get_guint8(tvb, offset);
558                         offset++;
559                 }
560                 for(i=1;i<len;i++){
561                         val64=(val64<<8)|tvb_get_guint8(tvb, offset);
562                         offset++;
563                 }
564                 hfinfo = proto_registrar_get_nth(hf_id);
565                 proto_tree_add_text(tree, tvb, offset-len, len, "%s: %" PRIu64, hfinfo->name, val64);
566                 return offset;
567         }
568         
569         val=0;
570         if (len > 0) {
571                 /* extend sign bit */
572                 val = (gint8)tvb_get_guint8(tvb, offset);
573                 offset++;
574         }
575         for(i=1;i<len;i++){
576                 val=(val<<8)|tvb_get_guint8(tvb, offset);
577                 offset++;
578         }
579
580         ber_last_created_item=NULL;
581
582         if(hf_id!=-1){  
583                 /* XXX - what if "len" is not 1, 2, 3, or 4? */
584                 ber_last_created_item=proto_tree_add_item(tree, hf_id, tvb, offset-len, len, FALSE);
585         }
586         if(value){
587                 *value=val;
588         }
589
590         return offset;
591 }
592
593
594 int
595 dissect_ber_boolean(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
596 {
597         guint8 class;
598         gboolean pc;
599         guint32 tag;
600         guint32 len;
601         guint8 val;
602         header_field_info *hfi;
603
604         offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
605         offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
606
607 /*      if(class!=BER_CLASS_UNI)*/
608         
609         val=tvb_get_guint8(tvb, offset);
610         offset+=1;
611
612         ber_last_created_item=NULL;
613
614         if(hf_id!=-1){
615                 hfi = proto_registrar_get_nth(hf_id);
616                 if (hfi->type == FT_BOOLEAN)
617                         ber_last_created_item=proto_tree_add_boolean(tree, hf_id, tvb, offset-1, 1, val);
618                 else
619                         ber_last_created_item=proto_tree_add_uint(tree, hf_id, tvb, offset-1, 1, val?1:0);
620         }
621
622         return offset;
623 }
624
625
626
627
628
629 /* this function dissects a BER sequence 
630  */
631 int dissect_ber_sequence(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
632         gint8 class;
633         gboolean pc, ind, ind_field;
634         gint32 tag;
635         guint32 len;
636         proto_tree *tree = parent_tree;
637         proto_item *item = NULL;
638         int end_offset;
639         tvbuff_t *next_tvb;
640
641 #ifdef DEBUG_BER
642 {
643 char *name;
644 header_field_info *hfinfo;
645 if(hf_id>0){
646 hfinfo = proto_registrar_get_nth(hf_id);
647 name=hfinfo->name;
648 } else {
649 name="unnamed";
650 }
651 if(tvb_length_remaining(tvb,offset)>3){
652 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));
653 }else{
654 printf("SEQUENCE dissect_ber_sequence(%s) entered\n",name);
655 }
656 }
657 #endif
658         if(!implicit_tag){
659                 /* first we must read the sequence header */
660                 offset = dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
661                 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, &ind);
662                 if(ind){
663                   /* if the length is indefinite we dont really know (yet) where the
664                    * object ends so assume it spans the rest of the tvb for now.
665                    */
666                   end_offset = tvb_length(tvb);
667                 } else {
668                   end_offset = offset + len;
669                 }
670
671                 /* sanity check: we only handle Constructed Universal Sequences */
672                 if ((!pc)
673                 ||(!implicit_tag&&((class!=BER_CLASS_UNI)
674                                                         ||(tag!=BER_UNI_TAG_SEQUENCE)))) {
675                         proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Sequence expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
676                         return end_offset;
677                 }
678         } else {
679                 /* was implicit tag so just use the length of the tvb */
680                 len=tvb_length_remaining(tvb,offset);
681                 end_offset=offset+len;
682         }
683
684         /* create subtree */
685         if (hf_id != -1) {
686                 if(parent_tree){
687                         item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, FALSE);
688                         tree = proto_item_add_subtree(item, ett_id);
689                 }
690         }
691
692         /* loop over all entries until we reach the end of the sequence */
693         while (offset < end_offset){
694                 gint8 class;
695                 gboolean pc;
696                 gint32 tag;
697                 guint32 len;
698                 int hoffset, eoffset, count;
699
700                 if(ind){ /* this sequence was of indefinite length, so check for EOC */
701                         if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
702                                 if(show_internal_ber_fields){
703                                         proto_tree_add_text(tree, tvb, offset, 2, "EOC");
704                                 }
705                                 return offset+2;
706                         }
707                 }
708                 hoffset = offset;
709                 /* read header and len for next field */
710                 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
711                 offset = get_ber_length(tvb, offset, &len, &ind_field);
712                 eoffset = offset + len;
713 ber_sequence_try_again:
714                 /* have we run out of known entries in the sequence ?*/
715                 if (!seq->func) {
716                         /* it was not,  move to the enxt one and try again */
717                         proto_tree_add_text(tree, tvb, offset, len, "BER Error: This field lies beyond the end of the known sequence definition.");
718                         offset = eoffset;
719                         continue;
720                 }
721
722                 /* Verify that this one is the one we want.
723                  * Skip check completely if class==ANY
724                  * of if NOCHKTAG is set
725                  */
726 /* XXX Bug in asn2eth,
727  * for   scope            [7]  Scope OPTIONAL,
728  * it generates         
729  *   { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_scope },
730  * and there should not be a NOTCHKTAG here
731  */
732                 if( (seq->class==BER_CLASS_CON) && (!(seq->flags&BER_FLAGS_NOOWNTAG)) ){
733                   if( (seq->class!=BER_CLASS_ANY) 
734                   &&  (seq->tag!=-1)  
735                   &&( (seq->class!=class)
736                     ||(seq->tag!=tag) ) ){
737                         /* it was not,  move to the enxt one and try again */
738                         if(seq->flags&BER_FLAGS_OPTIONAL){
739                                 /* well this one was optional so just skip to the next one and try again. */
740                                 seq++;
741                                 goto ber_sequence_try_again;
742                         }
743
744                         proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in SEQUENCE  expected class:%d tag:%d but found class:%d tag:%d",seq->class,seq->tag,class,tag);
745                         seq++;
746                         offset=eoffset;
747                         continue;
748                   }
749                 } else if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
750                   if( (seq->class!=BER_CLASS_ANY) 
751                   &&  (seq->tag!=-1)  
752                   &&( (seq->class!=class)
753                     ||(seq->tag!=tag) ) ){
754                         /* it was not,  move to the enxt one and try again */
755                         if(seq->flags&BER_FLAGS_OPTIONAL){
756                                 /* well this one was optional so just skip to the next one and try again. */
757                                 seq++;
758                                 goto ber_sequence_try_again;
759                         }
760
761                         proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in sequence  expected class:%d tag:%d but found class:%d tag:%d",seq->class,seq->tag,class,tag);
762                         seq++;
763                         offset=eoffset;
764                         continue;
765                   }
766                 }
767
768                 if (!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
769                         /* dissect header and len for field */
770                         hoffset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
771                         hoffset = dissect_ber_length(pinfo, tree, tvb, hoffset, NULL, NULL);
772                 }
773                 
774                 /* call the dissector for this field */
775                 if(ind_field 
776                 || ((eoffset-hoffset)>tvb_length_remaining(tvb, hoffset)) ){
777                         /* If the field is indefinite (i.e. we dont know the
778                          * length) of if the tvb is short, then just
779                          * give it all of the tvb and hope for the best.
780                          */
781                         next_tvb = tvb_new_subset(tvb, hoffset, tvb_length_remaining(tvb,hoffset), tvb_length_remaining(tvb,hoffset));
782                 } else {
783                         next_tvb = tvb_new_subset(tvb, hoffset, eoffset-hoffset, eoffset-hoffset);
784                 }
785
786 #ifdef DEBUG_BER
787 {
788 char *name;
789 header_field_info *hfinfo;
790 if(hf_id>0){
791 hfinfo = proto_registrar_get_nth(hf_id);
792 name=hfinfo->name;
793 } else {
794 name="unnamed";
795 }
796 if(tvb_length_remaining(next_tvb,0)>3){
797 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));
798 }else{
799 printf("SEQUENCE dissect_ber_sequence(%s) calling subdissector\n",name);
800 }
801 }
802 #endif
803                 count=seq->func(pinfo, tree, next_tvb, 0);
804 #ifdef DEBUG_BER
805 {
806 char *name;
807 header_field_info *hfinfo;
808 if(hf_id>0){
809 hfinfo = proto_registrar_get_nth(hf_id);
810 name=hfinfo->name;
811 } else {
812 name="unnamed";
813 }
814 printf("SEQUENCE dissect_ber_sequence(%s) subdissector ate %d bytes\n",name,count);
815 }
816 #endif
817                 seq++;
818                 offset = hoffset+count;
819                 /* if it was optional  and no bytes were eaten,
820                    just try again.
821                 */
822                 if((count==0)&&(seq->flags&BER_FLAGS_OPTIONAL)){
823                                 goto ber_sequence_try_again;
824                 }
825         }
826
827         /* if we didnt end up at exactly offset, then we ate too many bytes */
828         if (offset != end_offset) {
829                 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Sequence ate %d too many bytes", offset-end_offset);
830         }
831
832         return end_offset;
833 }
834
835
836
837 /* this function dissects a BER choice 
838  * If we did not find a matching choice,  just return offset unchanged
839  * in case it was a CHOICE { } OPTIONAL
840  */
841 int
842 dissect_ber_choice(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_choice_t *choice, gint hf_id, gint ett_id)
843 {
844         gint8 class;
845         gboolean pc, ind;
846         gint32 tag;
847         guint32 len;
848         const ber_choice_t *ch;
849         proto_tree *tree=parent_tree;
850         proto_item *item=NULL;
851         int end_offset, start_offset, count;
852         int hoffset = offset;
853         header_field_info       *hfinfo;
854         gint reported_length, length;
855         tvbuff_t *next_tvb;
856
857 #ifdef DEBUG_BER
858 {
859 char *name;
860 header_field_info *hfinfo;
861 if(hf_id>0){
862 hfinfo = proto_registrar_get_nth(hf_id);
863 name=hfinfo->name;
864 } else {
865 name="unnamed";
866 }
867 if(tvb_length_remaining(tvb,offset)>3){
868 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));
869 }else{
870 printf("CHOICE dissect_ber_choice(%s) entered len:%d\n",name,tvb_length_remaining(tvb,offset));
871 }
872 }
873 #endif
874         start_offset=offset;
875
876         /* read header and len for choice field */
877         offset=get_ber_identifier(tvb, offset, &class, &pc, &tag);
878         offset=get_ber_length(tvb, offset, &len, &ind);
879         if(ind){
880           /* if the length is indefinite we dont really know (yet) where the
881            * object ends so assume it spans the rest of the tvb for now.
882            * XXX - what if it runs past the end of the tvb because we
883            * need to do reassembly?
884            */
885           end_offset = tvb_length(tvb);
886         } else {
887           end_offset = offset + len;
888         }
889
890         /* Some sanity checks.  
891          * The hf field passed to us MUST be an integer type 
892          */
893         if(hf_id!=-1){
894                 hfinfo=proto_registrar_get_nth(hf_id);
895                 switch(hfinfo->type) {
896                         case FT_UINT8:
897                         case FT_UINT16:
898                         case FT_UINT24:
899                         case FT_UINT32:
900                                 break;
901                 default:
902                         proto_tree_add_text(tree, tvb, offset, len,"dissect_ber_choice(): Was passed a HF field that was not integer type : %s",hfinfo->abbrev);
903                         fprintf(stderr,"dissect_ber_choice(): frame:%d offset:%d Was passed a HF field that was not integer type : %s\n",pinfo->fd->num,offset,hfinfo->abbrev);
904                         return end_offset;
905                 }
906         }
907
908         
909
910         /* loop over all entries until we find the right choice or 
911            run out of entries */
912         ch = choice;
913         while(ch->func){
914 choice_try_again:
915 #ifdef DEBUG_BER
916 printf("CHOICE testing potential subdissector class:%d:(expected)%d  tag:%d:(expected)%d flags:%d\n",class,ch->class,tag,ch->tag,ch->flags);
917 #endif
918                 if( ((ch->class==class)&&(ch->tag==tag))
919                 ||  ((ch->class==class)&&(ch->tag==-1)&&(ch->flags&BER_FLAGS_NOOWNTAG))
920                 ){
921                         if (!(ch->flags & BER_FLAGS_NOOWNTAG)){
922                                 /* dissect header and len for field */
923                                 hoffset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, NULL, NULL, NULL);
924                                 hoffset = dissect_ber_length(pinfo, tree, tvb, hoffset, NULL, NULL);
925                                 start_offset=hoffset;
926                         }
927                         /* create subtree */
928                         if(hf_id!=-1){
929                                 if(parent_tree){
930                                         item = proto_tree_add_uint(parent_tree, hf_id, tvb, hoffset, end_offset - hoffset, ch->value);
931                                         tree = proto_item_add_subtree(item, ett_id);
932                                 }
933                         }
934
935                         reported_length = end_offset-start_offset;
936                         length = tvb_length_remaining(tvb, hoffset);
937                         if (length > reported_length)
938                                 length = reported_length;
939                         next_tvb=tvb_new_subset(tvb, hoffset, length, reported_length);
940
941 #ifdef DEBUG_BER
942 {
943 char *name;
944 header_field_info *hfinfo;
945 if(hf_id>0){
946 hfinfo = proto_registrar_get_nth(hf_id);
947 name=hfinfo->name;
948 } else {
949 name="unnamed";
950 }
951 if(tvb_length_remaining(next_tvb,0)>3){
952 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));
953 }else{
954 printf("CHOICE dissect_ber_choice(%s) calling subdissector len:%d\n",name,tvb_length(next_tvb));
955 }
956 }
957 #endif
958                         count=ch->func(pinfo, tree, next_tvb, 0);
959 #ifdef DEBUG_BER
960 {
961 char *name;
962 header_field_info *hfinfo;
963 if(hf_id>0){
964 hfinfo = proto_registrar_get_nth(hf_id);
965 name=hfinfo->name;
966 } else {
967 name="unnamed";
968 }
969 printf("CHOICE dissect_ber_choice(%s) subdissector ate %d bytes\n",name,count);
970 }
971 #endif
972                         if((count==0)&&(ch->class==class)&&(ch->tag==-1)&&(ch->flags&BER_FLAGS_NOOWNTAG)){
973                                 /* wrong one, break and try again */
974                                 ch++;
975                                 goto choice_try_again;
976                         }
977
978                         offset=hoffset+count;
979                         if(ind){
980                                 /* this choice was of indefinite length so we 
981                                  * just have to trust what the subdissector 
982                                  * told us about the length consumed.
983                                  */
984                                 return offset;
985                         } else {
986                                 return end_offset;
987                         }
988                         break;
989                 }
990                 ch++;
991         }
992 #ifdef REMOVED
993         /*XXX here we should have another flag to the CHOICE to distinguish
994          * between teh case when we know it is a mandatory   or if the CHOICE is optional == no arm matched */
995
996         /* oops no more entries and we still havent found
997          * our guy :-(
998          */
999         proto_tree_add_text(tree, tvb, offset, len, "BER Error: This choice field was not found.");
1000
1001         return end_offset;
1002 #endif
1003
1004         return start_offset;
1005 }
1006
1007 #if 0
1008 /* this function dissects a BER GeneralString
1009  */
1010 int
1011 dissect_ber_GeneralString(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, int name_len)
1012 {
1013         gint8 class;
1014         gboolean pc;
1015         gint32 tag;
1016         guint32 len;
1017         int end_offset;
1018         char str_arr[256];
1019         guint32 max_len;
1020         char *str;
1021
1022         str=str_arr;
1023         max_len=255;
1024         if(name_string){
1025                 str=name_string;
1026                 max_len=name_len;
1027         }
1028
1029         /* first we must read the GeneralString header */
1030         offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
1031         offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
1032         end_offset=offset+len;
1033
1034         /* sanity check: we only handle Universal GeneralString*/
1035         if( (class!=BER_CLASS_UNI)
1036           ||(tag!=BER_UNI_TAG_GENSTR) ){
1037                 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: GeneralString expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
1038                 return end_offset;
1039         }
1040
1041         if(len>=(max_len-1)){
1042                 len=max_len-1;
1043         }
1044         
1045         tvb_memcpy(tvb, str, offset, len);
1046         str[len]=0;
1047
1048         if(hf_id!=-1){
1049                 proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
1050         }
1051
1052         return end_offset;
1053 }
1054 #endif
1055 int
1056 dissect_ber_restricted_string(gboolean implicit_tag, gint32 type, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb) {
1057         gint8 class;
1058         gboolean pc;
1059         gint32 tag;
1060         guint32 len;
1061         int eoffset;
1062         int hoffset = offset;
1063
1064 #ifdef DEBUG_BER
1065 {
1066 char *name;
1067 header_field_info *hfinfo;
1068 if(hf_id>0){
1069 hfinfo = proto_registrar_get_nth(hf_id);
1070 name=hfinfo->name;
1071 } else {
1072 name="unnamed";
1073 }
1074 if(tvb_length_remaining(tvb,offset)>3){
1075 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));
1076 }else{
1077 printf("RESTRICTED STRING dissect_ber_octet_string(%s) entered\n",name);
1078 }
1079 }
1080 #endif
1081
1082         if (!implicit_tag) {
1083                 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
1084                 offset = get_ber_length(tvb, offset, &len, NULL);
1085                 eoffset = offset + len;
1086
1087                 /* sanity check */
1088                 if( (class!=BER_CLASS_UNI)
1089                   ||(tag != type) ){
1090                     proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: String with tag=%d expected but Class:%d PC:%d Tag:%d was unexpected", type, class, pc, tag);
1091                         return eoffset;
1092                 }
1093         }
1094
1095         /* 8.21.3 */
1096         return dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, hoffset, hf_id, out_tvb);
1097 }
1098
1099 int
1100 dissect_ber_GeneralString(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, guint name_len)
1101 {
1102         tvbuff_t *out_tvb;
1103
1104         offset = dissect_ber_restricted_string(FALSE, BER_UNI_TAG_GeneralString, pinfo, tree, tvb, offset, hf_id, (name_string)?&out_tvb:NULL);
1105
1106         if (name_string) {
1107                 if (tvb_length(out_tvb) >= name_len) {
1108                         tvb_memcpy(out_tvb, name_string, 0, name_len-1);
1109                         name_string[name_len-1] = '\0';
1110                 } else {
1111                         tvb_memcpy(out_tvb, name_string, 0, -1);
1112                         name_string[tvb_length(out_tvb)] = '\0';
1113                 }
1114         }
1115
1116         return offset;
1117 }
1118
1119 /* 8.19 Encoding of an object identifier value */
1120 int dissect_ber_object_identifier(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *value_string) {
1121         gint8 class;
1122         gboolean pc;
1123         gint32 tag;
1124         guint32 i, len;
1125         int eoffset;
1126         guint8 byte;
1127         guint32 value;
1128         char str[256],*strp, *name;
1129         proto_item *item;
1130
1131 #ifdef DEBUG_BER
1132 {
1133 char *name;
1134 header_field_info *hfinfo;
1135 if(hf_id>0){
1136 hfinfo = proto_registrar_get_nth(hf_id);
1137 name=hfinfo->name;
1138 } else {
1139 name="unnamed";
1140 }
1141 if(tvb_length_remaining(tvb,offset)>3){
1142 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));
1143 }else{
1144 printf("OBJECT IDENTIFIER dissect_ber_object_identifier(%s) entered\n",name);
1145 }
1146 }
1147 #endif
1148
1149         if (value_string) {
1150                 value_string[0] = '\0';
1151         }
1152
1153         if (!implicit_tag) {
1154                 /* sanity check */
1155                 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
1156                 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
1157                 eoffset = offset + len;
1158                 if( (class!=BER_CLASS_UNI)
1159                   ||(tag != BER_UNI_TAG_OID) ){
1160                     proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Object Identifier expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
1161                         return eoffset;
1162                 }
1163         } else {
1164                 len=tvb_length_remaining(tvb,offset);
1165                 eoffset=offset+len;
1166         }
1167
1168         value=0;
1169         for (i=0,strp=str; i<len; i++){
1170                 byte = tvb_get_guint8(tvb, offset);
1171                 offset++;
1172
1173                 if((strp-str)>200){
1174             proto_tree_add_text(tree, tvb, offset, eoffset - offset, "BER Error: too long Object Identifier");
1175                         return offset;
1176                 }
1177
1178                 /* 8.19.4 */
1179                 if (i == 0) {
1180                         strp += sprintf(strp, "%d.%d", byte/40, byte%40);
1181                         continue;
1182                 }
1183
1184                 value = (value << 7) | (byte & 0x7F);
1185                 if (byte & 0x80) {
1186                         continue;
1187                 }
1188
1189                 strp += sprintf(strp, ".%d", value);
1190                 value = 0;
1191         }
1192         *strp = '\0';
1193
1194         if (hf_id != -1) {
1195                 item=proto_tree_add_string(tree, hf_id, tvb, offset - len, len, str);
1196                 /* see if we know the name of this oid */
1197                 if(item){
1198                         name=g_hash_table_lookup(oid_table, str);
1199                         if(name){
1200                                 proto_item_append_text(item, " (%s)", name);
1201                         }
1202                 }
1203         }
1204
1205         if (value_string) {
1206                 strcpy(value_string, str);
1207         }
1208
1209         return eoffset;
1210 }
1211
1212 static int dissect_ber_sq_of(gboolean implicit_tag, gint32 type, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
1213         gint8 class;
1214         gboolean pc, ind, ind_field;
1215         gint32 tag;
1216         guint32 len;
1217         proto_tree *tree = parent_tree;
1218         proto_item *item = NULL;
1219         int cnt, hoffset, end_offset;
1220         header_field_info *hfi;
1221
1222 #ifdef DEBUG_BER
1223 {
1224 char *name;
1225 header_field_info *hfinfo;
1226 if(hf_id>0){
1227 hfinfo = proto_registrar_get_nth(hf_id);
1228 name=hfinfo->name;
1229 } else {
1230 name="unnamed";
1231 }
1232 if(tvb_length_remaining(tvb,offset)>3){
1233 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));
1234 }else{
1235 printf("SQ OF dissect_ber_sq_of(%s) entered\n",name);
1236 }
1237 }
1238 #endif
1239
1240         if(!implicit_tag){
1241                 /* first we must read the sequence header */
1242                 offset = dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
1243                 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, &ind);
1244                 if(ind){
1245                   /* if the length is indefinite we dont really know (yet) where the
1246                    * object ends so assume it spans the rest of the tvb for now.
1247                    */
1248                   end_offset = tvb_length(tvb);
1249                 } else {
1250                   end_offset = offset + len;
1251                 }
1252
1253                 /* sanity check: we only handle Constructed Universal Sequences */
1254                 if (!pc
1255                         ||(!implicit_tag&&((class!=BER_CLASS_UNI)
1256                                                         ||(tag!=type)))) {
1257                         proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: %s Of expected but Class:%d PC:%d Tag:%d was unexpected", 
1258                                                         (type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence", class, pc, tag);
1259                         return end_offset;
1260                 }
1261         } else {
1262                 len=tvb_length_remaining(tvb,offset);
1263                 end_offset = offset + len;
1264         }
1265
1266         /* count number of items */
1267         cnt = 0;
1268         hoffset = offset;
1269         while (offset < end_offset){
1270                 guint32 len;
1271
1272                 if(ind){ /* this sequence of was of indefinite length, so check for EOC */
1273                         if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
1274                                 break;
1275                         }
1276                 }
1277
1278                 /* read header and len for next field */
1279                 offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
1280                 offset = get_ber_length(tvb, offset, &len, NULL);
1281                 offset += len;
1282                 cnt++;
1283         }
1284         offset = hoffset;
1285
1286         /* create subtree */
1287         if (hf_id != -1) {
1288                 hfi = proto_registrar_get_nth(hf_id);
1289                 if(parent_tree){
1290                         if (hfi->type == FT_NONE) {
1291                                 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, FALSE);
1292                                 proto_item_append_text(item, ":");
1293                         } else {
1294                                 item = proto_tree_add_uint(parent_tree, hf_id, tvb, offset, len, cnt);
1295                                 proto_item_append_text(item, (cnt==1)?" item":" items");
1296                         }
1297                         tree = proto_item_add_subtree(item, ett_id);
1298                 }
1299         }
1300
1301         /* loop over all entries until we reach the end of the sequence */
1302         while (offset < end_offset){
1303                 gint8 class;
1304                 gboolean pc;
1305                 gint32 tag;
1306                 guint32 len;
1307                 int eoffset;
1308                 int hoffset, count;
1309
1310                 if(ind){ /* this sequence of was of indefinite length, so check for EOC */
1311                         if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
1312                                 if(show_internal_ber_fields){
1313                                         proto_tree_add_text(tree, tvb, offset, 2, "EOC");
1314                                 }
1315                                 return offset+2;
1316                         }
1317                 }
1318                 hoffset = offset;
1319                 /* read header and len for next field */
1320                 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
1321                 offset = get_ber_length(tvb, offset, &len, &ind_field);
1322                 if(ind_field){
1323                         /* if the length is indefinite we dont really know (yet) where the
1324                          * object ends so assume it spans the rest of the tvb for now.
1325                          */
1326                         eoffset = tvb_length(tvb);
1327                 } else {
1328                         eoffset = offset + len;
1329                 }
1330
1331                 /* verify that this one is the one we want */
1332                 if(seq->class!=BER_CLASS_ANY){
1333                   if ((seq->class!=class)
1334                         ||(seq->tag!=tag) ){
1335                         if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
1336                                 proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in SQ OF");
1337                                 offset = eoffset;
1338                                 continue;
1339                         }
1340                   }
1341                 }
1342
1343                 if (!(seq->flags & BER_FLAGS_NOOWNTAG) && !(seq->flags & BER_FLAGS_IMPLTAG)) {
1344                         /* dissect header and len for field */
1345                         hoffset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
1346                         hoffset = dissect_ber_length(pinfo, tree, tvb, hoffset, NULL, NULL);
1347                 }
1348                 
1349                 /* call the dissector for this field */
1350                 count=seq->func(pinfo, tree, tvb, hoffset)-hoffset;
1351                 if(ind_field){
1352                         /* previous field was of indefinite length so we have
1353                          * no choice but use whatever the subdissector told us
1354                          * as size for the field.
1355                          */
1356                         cnt++;
1357                         offset = hoffset+count;
1358                 } else {
1359                         cnt++;
1360                         offset = eoffset;
1361                 }
1362         }
1363
1364         /* if we didnt end up at exactly offset, then we ate too many bytes */
1365         if (offset != end_offset) {
1366                 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: %s Of ate %d too many bytes", 
1367                                                         (type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence", offset-end_offset);
1368         }
1369
1370         return end_offset;
1371 }
1372
1373 int dissect_ber_sequence_of(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
1374         return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SEQUENCE, pinfo, parent_tree, tvb, offset, seq, hf_id, ett_id);
1375 }
1376
1377 int dissect_ber_set_of(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
1378         return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SET, pinfo, parent_tree, tvb, offset, seq, hf_id, ett_id);
1379 }
1380
1381 int 
1382 dissect_ber_GeneralizedTime(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
1383 {
1384         char str[32];
1385         const guint8 *tmpstr;
1386         gint8 class;
1387         gboolean pc;
1388         gint32 tag;
1389         guint32 len;
1390         int end_offset;
1391
1392         if(!implicit_tag){
1393           offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
1394           offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
1395           end_offset=offset+len;
1396
1397           /* sanity check. we only handle universal/generalized time */
1398           if( (class!=BER_CLASS_UNI)
1399           ||(tag!=BER_UNI_TAG_GeneralizedTime)){
1400                 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: GeneralizedTime expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
1401                 return end_offset;
1402                 end_offset=offset+len;
1403           }
1404         } else {
1405           len=tvb_length_remaining(tvb,offset);
1406           end_offset=offset+len;
1407         }
1408           
1409
1410         tmpstr=tvb_get_ptr(tvb, offset, len);
1411         snprintf(str, 31, "%.4s-%.2s-%.2s %.2s:%.2s:%.2s (%.1s)",
1412                 tmpstr, tmpstr+4, tmpstr+6, tmpstr+8,
1413                 tmpstr+10, tmpstr+12, tmpstr+14);
1414         str[31]=0; /* just in case ... */
1415                 
1416         if(hf_id!=-1){
1417                 proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
1418         }
1419
1420         offset+=len;
1421         return offset;
1422 }
1423
1424 /* 8.6 Encoding of a bitstring value */
1425 int dissect_ber_bitstring(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const asn_namedbit *named_bits, gint hf_id, gint ett_id, tvbuff_t **out_tvb) 
1426 {
1427         gint8 class;
1428         gboolean pc, ind;
1429         gint32 tag;
1430         guint32 len;
1431         guint8 pad=0, b0, b1, val;
1432         int end_offset;
1433         proto_item *item = NULL;
1434         proto_tree *tree = NULL;
1435         const asn_namedbit *nb;
1436         char *sep;
1437         gboolean term;
1438
1439         if(!implicit_tag){
1440           /* read header and len for the octet string */
1441           offset = dissect_ber_identifier(pinfo, parent_tree, tvb, offset, &class, &pc, &tag);
1442           offset = dissect_ber_length(pinfo, parent_tree, tvb, offset, &len, &ind);
1443           end_offset = offset + len;
1444
1445           /* sanity check: we only handle Universal BitSrings */
1446           if (!implicit_tag) {
1447                 if( (class!=BER_CLASS_UNI)
1448                   ||(tag!=BER_UNI_TAG_BITSTRING) ){
1449                     proto_tree_add_text(parent_tree, tvb, offset-2, 2, "BER Error: BitString expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
1450                         return end_offset;
1451                 }
1452           }
1453         } else {
1454           pc=0;
1455           len=tvb_length_remaining(tvb,offset);
1456           end_offset=offset+len;
1457         }
1458
1459         ber_last_created_item = NULL;
1460
1461         if (pc) {
1462                 /* constructed */
1463                 /* TO DO */
1464         } else {
1465                 /* primitive */
1466                 /* padding */
1467                 pad = tvb_get_guint8(tvb, offset);
1468                 proto_tree_add_item(parent_tree, hf_ber_bitstring_padding, tvb, offset, 1, FALSE);
1469                 offset++;
1470                 len--;
1471                 if ( hf_id != -1) {
1472                         item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, FALSE);
1473                         ber_last_created_item = item;
1474                         if (ett_id != -1) {
1475                                 tree = proto_item_add_subtree(item, ett_id);
1476                         }
1477                 }
1478                 if (out_tvb) {
1479                         if(len<=(guint32)tvb_length_remaining(tvb, offset)){
1480                                 *out_tvb = tvb_new_subset(tvb, offset, len, len);
1481                         } else {
1482                                 *out_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_length_remaining(tvb, offset));
1483                         }
1484                 }
1485         }
1486
1487         if (named_bits) {
1488                 sep = " (";
1489                 term = FALSE;
1490                 nb = named_bits;
1491                 while (nb->p_id) {
1492                         if (nb->bit < (8*len-pad)) {
1493                                 val = tvb_get_guint8(tvb, offset + nb->bit/8);
1494                                 val &= 0x80 >> (nb->bit%8);
1495                                 b0 = (nb->gb0 == -1) ? nb->bit/8 :
1496                                                        ((guint32)nb->gb0)/8;
1497                                 b1 = (nb->gb1 == -1) ? nb->bit/8 :
1498                                                        ((guint32)nb->gb1)/8;
1499                                 proto_tree_add_item(tree, *(nb->p_id), tvb, offset + b0, b1 - b0 + 1, FALSE);
1500                         } else {  /* 8.6.2.4 */
1501                                 val = 0;
1502                                 proto_tree_add_boolean(tree, *(nb->p_id), tvb, offset + len, 0, 0x00);
1503                         }
1504                         if (val) {
1505                                 if (item && nb->tstr)
1506                                         proto_item_append_text(item, "%s%s", sep, nb->tstr);
1507                         } else {
1508                                 if (item && nb->fstr)
1509                                         proto_item_append_text(item, "%s%s", sep, nb->fstr);
1510                         }
1511                         nb++;
1512                         sep = ", ";
1513                         term = TRUE;
1514                 }
1515                 if (term)
1516                         proto_item_append_text(item, ")");
1517         }
1518
1519         return end_offset;
1520 }
1521
1522 int dissect_ber_bitstring32(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, int **bit_fields, gint hf_id, gint ett_id, tvbuff_t **out_tvb) 
1523 {
1524         tvbuff_t *tmp_tvb;
1525         proto_tree *tree;
1526         guint32 val;
1527         int **bf;
1528         header_field_info *hfi;
1529         char *sep;
1530         gboolean term;
1531         unsigned int i, tvb_len;
1532
1533         offset = dissect_ber_bitstring(implicit_tag, pinfo, parent_tree, tvb, offset, NULL, hf_id, ett_id, &tmp_tvb);
1534         
1535         tree = proto_item_get_subtree(ber_last_created_item);
1536         if (bit_fields && tree) {
1537                 /* tmp_tvb points to the actual bitstring (including any pad bits at the end.
1538                  * note that this bitstring is not neccessarily always encoded as 4 bytes
1539                  * so we have to read it byte by byte.
1540                  */
1541                 val=0;
1542                 tvb_len=tvb_length(tmp_tvb);
1543                 for(i=0;i<4;i++){
1544                         val<<=8;
1545                         if(i<tvb_len){
1546                                 val|=tvb_get_guint8(tmp_tvb,i);
1547                         }
1548                 }
1549                 bf = bit_fields;
1550                 sep = " (";
1551                 term = FALSE;
1552                 while (*bf) {
1553                         proto_tree_add_boolean(tree, **bf, tmp_tvb, 0, tvb_len, val);
1554                         hfi = proto_registrar_get_nth(**bf);
1555                         if (val & hfi->bitmask) {
1556                                 proto_item_append_text(ber_last_created_item, "%s%s", sep, hfi->name);
1557                                 sep = ", ";
1558                                 term = TRUE;
1559                         }
1560                         bf++;
1561                 }
1562                 if (term)
1563                         proto_item_append_text(ber_last_created_item, ")");
1564         }
1565
1566         if (out_tvb)
1567                 *out_tvb = tmp_tvb;
1568
1569         return offset;
1570 }
1571
1572 void
1573 proto_register_ber(void)
1574 {
1575     static hf_register_info hf[] = {
1576         { &hf_ber_id_class, {
1577             "Class", "ber.id.class", FT_UINT8, BASE_DEC,
1578             VALS(ber_class_codes), 0xc0, "Class of BER TLV Identifier", HFILL }},
1579         { &hf_ber_bitstring_padding, {
1580             "Padding", "ber.bitstring.padding", FT_UINT8, BASE_DEC,
1581             NULL, 0x0, "Number of unsused bits in the last octet of the bitstring", HFILL }},
1582         { &hf_ber_id_pc, {
1583             "P/C", "ber.id.pc", FT_BOOLEAN, 8,
1584             TFS(&ber_pc_codes), 0x20, "Primitive or Constructed BER encoding", HFILL }},
1585         { &hf_ber_id_uni_tag, {
1586             "Tag", "ber.id.uni_tag", FT_UINT8, BASE_DEC,
1587             VALS(ber_uni_tag_codes), 0x1f, "Universal tag type", HFILL }},
1588         { &hf_ber_id_tag, {
1589             "Tag", "ber.id.tag", FT_UINT32, BASE_DEC,
1590             NULL, 0, "Tag value for non-Universal classes", HFILL }},
1591         { &hf_ber_length, {
1592             "Length", "ber.length", FT_UINT32, BASE_DEC,
1593             NULL, 0, "Length of contents", HFILL }},
1594         { &hf_ber_unknown_OCTETSTRING, {
1595             "OCTETSTRING", "ber.unknown.OCTETSTRING", FT_BYTES, BASE_HEX,
1596             NULL, 0, "This is an unknown OCTETSTRING", HFILL }},
1597         { &hf_ber_unknown_OID, {
1598             "OID", "ber.unknown.OID", FT_STRING, BASE_NONE,
1599             NULL, 0, "This is an unknown Object Identifier", HFILL }},
1600         { &hf_ber_unknown_NumericString, {
1601             "NumericString", "ber.unknown.NumericString", FT_STRING, BASE_NONE,
1602             NULL, 0, "This is an unknown NumericString", HFILL }},
1603         { &hf_ber_unknown_PrintableString, {
1604             "PrintableString", "ber.unknown.PrintableString", FT_STRING, BASE_NONE,
1605             NULL, 0, "This is an unknown PrintableString", HFILL }},
1606         { &hf_ber_unknown_IA5String, {
1607             "IA5String", "ber.unknown.IA5String", FT_STRING, BASE_NONE,
1608             NULL, 0, "This is an unknown IA5String", HFILL }},
1609         { &hf_ber_unknown_INTEGER, {
1610             "INTEGER", "ber.unknown.INTEGER", FT_UINT32, BASE_DEC,
1611             NULL, 0, "This is an unknown INTEGER", HFILL }},
1612         { &hf_ber_unknown_ENUMERATED, {
1613             "ENUMERATED", "ber.unknown.ENUMERATED", FT_UINT32, BASE_DEC,
1614             NULL, 0, "This is an unknown ENUMERATED", HFILL }},
1615
1616     };
1617
1618     static gint *ett[] = {
1619         &ett_ber_octet_string,
1620         &ett_ber_unknown,
1621         &ett_ber_SEQUENCE,
1622     };
1623     module_t *ber_module;
1624
1625     proto_ber = proto_register_protocol("Basic Encoding Rules (ASN.1 X.690)", "BER", "ber");
1626     proto_register_field_array(proto_ber, hf, array_length(hf));
1627     proto_register_subtree_array(ett, array_length(ett));
1628
1629         proto_set_cant_toggle(proto_ber);
1630
1631     /* Register preferences */
1632     ber_module = prefs_register_protocol(proto_ber, NULL);
1633     prefs_register_bool_preference(ber_module, "show_internals",
1634         "Show internal BER encapsulation tokens",
1635         "Whether the dissector should also display internal"
1636         " ASN.1 BER details such as Identifier and Length fields", &show_internal_ber_fields);
1637
1638     ber_oid_dissector_table = register_dissector_table("ber.oid", "BER OID Dissectors", FT_STRING, BASE_NONE);
1639     oid_table=g_hash_table_new(g_str_hash, g_str_equal);
1640 }
1641
1642 void
1643 proto_reg_handoff_ber(void)
1644 {
1645 }