The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / wiretap / ber.c @ master

History | View | Annotate | Download (4.76 KB)

1
/* ber.c
2
 *
3
 * Basic Encoding Rules (BER) file reading
4
 *
5
 * $Id$
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License
9
 * as published by the Free Software Foundation; either version 2
10
 * of the License, or (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
 */
21

    
22
#include "config.h"
23

    
24
#include <errno.h>
25

    
26
#ifdef HAVE_SYS_STAT_H
27
#include <sys/stat.h>
28
#endif
29

    
30
#include "wtap-int.h"
31
#include "file_wrappers.h"
32
#include "buffer.h"
33
#include "ber.h"
34

    
35

    
36
#define BER_CLASS_UNI        0
37
#define BER_CLASS_APP        1
38
#define BER_CLASS_CON        2
39

    
40
#define BER_UNI_TAG_SEQ        16        /* SEQUENCE, SEQUENCE OF */
41
#define BER_UNI_TAG_SET        17        /* SET, SET OF */
42

    
43
static gboolean ber_read_file(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
44
                              Buffer *buf, int *err, gchar **err_info)
45
{
46
  gint64 file_size;
47
  int packet_size;
48

    
49
  if ((file_size = wtap_file_size(wth, err)) == -1)
50
    return FALSE;
51

    
52
  if (file_size > WTAP_MAX_PACKET_SIZE) {
53
    /*
54
     * Probably a corrupt capture file; don't blow up trying
55
     * to allocate space for an immensely-large packet.
56
     */
57
    *err = WTAP_ERR_BAD_FILE;
58
    *err_info = g_strdup_printf("ber: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
59
                                file_size, WTAP_MAX_PACKET_SIZE);
60
    return FALSE;
61
  }
62
  packet_size = (int)file_size;
63

    
64
  phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
65

    
66
  phdr->caplen = packet_size;
67
  phdr->len = packet_size;
68

    
69
  phdr->ts.secs = 0;
70
  phdr->ts.nsecs = 0;
71

    
72
  return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
73
}
74

    
75
static gboolean ber_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
76
{
77
  gint64 offset;
78

    
79
  *err = 0;
80

    
81
  offset = file_tell(wth->fh);
82

    
83
  /* there is only ever one packet */
84
  if (offset != 0)
85
    return FALSE;
86

    
87
  *data_offset = offset;
88

    
89
  return ber_read_file(wth, wth->fh, &wth->phdr, wth->frame_buffer, err, err_info);
90
}
91

    
92
static gboolean ber_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr _U_,
93
                              Buffer *buf, int length _U_, int *err, gchar **err_info)
94
{
95
  /* there is only one packet */
96
  if(seek_off > 0) {
97
    *err = 0;
98
    return FALSE;
99
  }
100

    
101
  if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
102
    return FALSE;
103

    
104
  return ber_read_file(wth, wth->random_fh, phdr, buf, err, err_info);
105
}
106

    
107
int ber_open(wtap *wth, int *err, gchar **err_info)
108
{
109
#define BER_BYTES_TO_CHECK 8
110
  guint8 bytes[BER_BYTES_TO_CHECK];
111
  int bytes_read;
112
  guint8 ber_id;
113
  gint8 ber_class;
114
  gint8 ber_tag;
115
  gboolean ber_pc;
116
  guint8 oct, nlb = 0;
117
  int len = 0;
118
  gint64 file_size;
119
  int offset = 0, i;
120

    
121
  bytes_read = file_read(&bytes, BER_BYTES_TO_CHECK, wth->fh);
122
  if (bytes_read != BER_BYTES_TO_CHECK) {
123
    *err = file_error(wth->fh, err_info);
124
    if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
125
      return -1;
126
    return 0;
127
  }
128

    
129
  ber_id = bytes[offset++];
130

    
131
  ber_class = (ber_id>>6) & 0x03;
132
  ber_pc = (ber_id>>5) & 0x01;
133
  ber_tag = ber_id & 0x1F;
134

    
135
  /* it must be constructed and either a SET or a SEQUENCE */
136
  /* or a CONTEXT less than 32 (arbitrary) */
137
  /* XXX: do we also want to allow APPLICATION */
138
  if(!(ber_pc &&
139
       (((ber_class == BER_CLASS_UNI) && ((ber_tag == BER_UNI_TAG_SET) || (ber_tag == BER_UNI_TAG_SEQ))) ||
140
        ((ber_class == BER_CLASS_CON) && (ber_tag < 32)))))
141
    return 0;
142

    
143
  /* now check the length */
144
  oct = bytes[offset++];
145

    
146
  if(oct != 0x80) {
147
    /* not indefinite length encoded */
148

    
149
    if(!(oct & 0x80))
150
      /* length fits into a single byte */
151
      len = oct;
152
    else {
153
      nlb = oct & 0x7F; /* number of length bytes */
154

    
155
      if((nlb > 0) && (nlb <= (BER_BYTES_TO_CHECK - 2))) {
156
        /* not indefinite length and we have read enough bytes to compute the length */
157
        i = nlb;
158
        while(i--) {
159
          oct = bytes[offset++];
160
          len = (len<<8) + oct;
161
        }
162
      }
163
    }
164

    
165
    len += (2 + nlb); /* add back Tag and Length bytes */
166
    file_size = wtap_file_size(wth, err);
167

    
168
    if(len != file_size) {
169
      return 0; /* not ASN.1 */
170
    }
171
  } else {
172
    /* Indefinite length encoded - assume it is BER */
173
  }
174

    
175
  /* seek back to the start of the file  */
176
  if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
177
    return -1;
178

    
179
  wth->file_type = WTAP_FILE_BER;
180
  wth->file_encap = WTAP_ENCAP_BER;
181
  wth->snapshot_length = 0;
182

    
183
  wth->subtype_read = ber_read;
184
  wth->subtype_seek_read = ber_seek_read;
185
  wth->tsprecision = WTAP_FILE_TSPREC_SEC;
186

    
187
  return 1;
188
}