From Harald Welte:
[obnox/wireshark/wip.git] / wiretap / dct3trace.c
index 26976096961e5d53502a651e71aaeff8b57ac35f..12910bebacb0cc2b2b68f0ddcedab5b5e8724c05 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for reading signalling traces generated by Gammu (www.gammu.org)
  * from Nokia DCT3 phones in Netmonitor mode.
  *
- * gammu --nokiadebug nhm5_587.txt v20-25,v18-19
+ * gammu --nokiadebug nhm5_587.txt v18-19
  *
  * Duncan Salerno <duncan.salerno@googlemail.com>
  *
@@ -73,6 +73,7 @@ static const char dct3trace_magic_l2_start[]  = "<l2 ";
 static const char dct3trace_magic_l2_end[]  = "</l2>";
 static const char dct3trace_magic_end[]  = "</dump>";
 
+#define MAX_PACKET_LEN 23
 
 static gboolean dct3trace_read(wtap *wth, int *err, gchar **err_info,
        gint64 *data_offset);
@@ -103,6 +104,10 @@ hex2bin(unsigned char *out, unsigned char *in)
        int is_low = 0;
        int c;
 
+       /* Clamp to maximum packet size */
+       if (end - in > MAX_PACKET_LEN*2) /* As we're reading nibbles */
+               end = in + MAX_PACKET_LEN*2;
+
        while (in < end)
        {
                c = hc2b(in[0]);
@@ -123,17 +128,17 @@ hex2bin(unsigned char *out, unsigned char *in)
                in++;
        }
 
-       return out - out_start;
+       return (int)(out - out_start);
 }
 
 static int
 xml_get_int(int *val, const unsigned char *str, const unsigned char *pattern)
 {
-       char *ptr;
+       const char *ptr;
        char *start, *end;
        char buf[32];
 
-       ptr = strstr((char *)str, (char *)pattern);
+       ptr = strstr((const char *)str, (const char *)pattern);
        if (ptr == NULL)
                return -1;
        start = strchr(ptr, '"');
@@ -143,6 +148,8 @@ xml_get_int(int *val, const unsigned char *str, const unsigned char *pattern)
        end = strchr(start, '"');
        if (end == NULL)
                return -3;
+       if (end - start > 31)
+               return -4;
 
        memcpy(buf, start, end - start);
        buf[end - start] = '\0';
@@ -155,9 +162,10 @@ xml_get_int(int *val, const unsigned char *str, const unsigned char *pattern)
  * a DCT3 trace file.
  *
  * Returns TRUE if it is, FALSE if it isn't or if we get an I/O error;
- * if we get an I/O error, "*err" will be set to a non-zero value.
+ * if we get an I/O error, "*err" will be set to a non-zero value
+ * and "*err_info" will be set to null or an additional error string.
  */
-static gboolean dct3trace_check_file_type(wtap *wth, int *err)
+static gboolean dct3trace_check_file_type(wtap *wth, int *err, gchar **err_info)
 {
        char line1[64], line2[64];
 
@@ -177,17 +185,17 @@ static gboolean dct3trace_check_file_type(wtap *wth, int *err)
                if (file_eof(wth->fh))
                        *err = 0;
                else
-                       *err = file_error(wth->fh);
+                       *err = file_error(wth->fh, err_info);
        }
 
        return FALSE;
 }
 
 
-int dct3trace_open(wtap *wth, int *err, gchar **err_info _U_)
+int dct3trace_open(wtap *wth, int *err, gchar **err_info)
 {
        /* Look for Gammu DCT3 trace header */
-       if (!dct3trace_check_file_type(wth, err))
+       if (!dct3trace_check_file_type(wth, err, err_info))
        {
                if (*err == 0)
                        return 0;
@@ -207,7 +215,7 @@ int dct3trace_open(wtap *wth, int *err, gchar **err_info _U_)
 }
 
 
-static gboolean dct3trace_get_packet(FILE *fh, union wtap_pseudo_header *pseudo_header,
+static gboolean dct3trace_get_packet(FILE_T fh, union wtap_pseudo_header *pseudo_header,
        unsigned char *buf, int *len, int *err, gchar **err_info)
 {
        unsigned char line[1024];
@@ -232,7 +240,7 @@ static gboolean dct3trace_get_packet(FILE *fh, union wtap_pseudo_header *pseudo_
                        else
                        {
                                /* If not got any data return error */
-                               *err = WTAP_ERR_BAD_RECORD;
+                               *err = WTAP_ERR_BAD_FILE;
                                *err_info = g_strdup_printf("dct3trace: record without data");
                                return FALSE;
                        }
@@ -263,7 +271,7 @@ static gboolean dct3trace_get_packet(FILE *fh, union wtap_pseudo_header *pseudo_
 
                        if( ret != 0 )
                        {
-                               *err = WTAP_ERR_BAD_RECORD;
+                               *err = WTAP_ERR_BAD_FILE;
                                *err_info = g_strdup_printf("dct3trace: record missing mandatory attributes");
                                return FALSE;
                        }
@@ -288,7 +296,7 @@ static gboolean dct3trace_get_packet(FILE *fh, union wtap_pseudo_header *pseudo_
                }
                else if( !have_data && memcmp(dct3trace_magic_l2_start, line, strlen(dct3trace_magic_l2_start)) == 0 )
                {
-                       /* For uplink packets we don't get the raw L1, so have to recreate it from the L2 */
+                       /* For uplink packets we might not get the raw L1, so have to recreate it from the L2 */
                        /* Parse L2 header if didn't get data from L1 <l2 ...> */
                        int data_len = 0;
                        char *ptr = strstr(line, "data=\"");
@@ -321,7 +329,7 @@ static gboolean dct3trace_get_packet(FILE *fh, union wtap_pseudo_header *pseudo_
                }
        }
 
-       *err = file_error(fh);
+       *err = file_error(fh, err_info);
        if (*err == 0)
        {
                *err = WTAP_ERR_SHORT_READ;
@@ -336,7 +344,7 @@ static gboolean dct3trace_read(wtap *wth, int *err, gchar **err_info,
 {
        guint64 offset = file_tell(wth->fh);
        int buf_len;
-       char buf[23];
+       unsigned char buf[MAX_PACKET_LEN];
 
        if( !dct3trace_get_packet(wth->fh, &wth->pseudo_header, buf, &buf_len, err, err_info) )
        {
@@ -365,7 +373,7 @@ static gboolean dct3trace_seek_read (wtap *wth, gint64 seek_off,
        int *err, gchar **err_info)
 {
        int buf_len;
-       char buf[23];
+       unsigned char buf[MAX_PACKET_LEN];
 
        if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
        {
@@ -379,12 +387,19 @@ static gboolean dct3trace_seek_read (wtap *wth, gint64 seek_off,
 
        if( len != buf_len && len != -1 )
        {
-               *err = WTAP_ERR_BAD_RECORD;
+               *err = WTAP_ERR_BAD_FILE;
                *err_info = g_strdup_printf("dct3trace: requested length %d doesn't match record length %d",
                    len, buf_len);
                return FALSE;
        }
 
+       if( buf_len > MAX_PACKET_LEN)
+       {
+               *err = WTAP_ERR_BAD_FILE;
+               *err_info = g_strdup_printf("dct3trace: record length %d too long", buf_len);
+               return FALSE;
+       }
+
        memcpy( pd, buf, buf_len );
        return TRUE;
 }