wiretap: add support for ruby marshal object files.
authorDario Lombardo <lomato@gmail.com>
Wed, 23 May 2018 11:39:51 +0000 (13:39 +0200)
committerAnders Broman <a.broman58@gmail.com>
Thu, 7 Jun 2018 04:54:49 +0000 (04:54 +0000)
Change-Id: Iefba3b15c907966bb0b8d5c0ff9b6bb7097d326e
Reviewed-on: https://code.wireshark.org/review/27763
Petri-Dish: Jaap Keuter <jaap.keuter@xs4all.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
wiretap/CMakeLists.txt
wiretap/file_access.c
wiretap/ruby_marshal.c [new file with mode: 0644]
wiretap/ruby_marshal.h [new file with mode: 0644]
wiretap/wtap.h

index b0aebf04e810fe37dd23ec6b23dc630b5788d21a..0f59f444b8576bc500297a8f7a440ed8ad1b0e49 100644 (file)
@@ -71,6 +71,7 @@ set(WIRETAP_NONGENERATED_FILES
        pem.c
        pppdump.c
        radcom.c
+       ruby_marshal.c
        snoop.c
        stanag4607.c
        tnef.c
index 4fbfde4de6bd3c61bc21d1f241d0877e80051b75..cc29ed8eb7c5ea1aaa7f0ef8fa2a1189dd6d320c 100644 (file)
@@ -74,6 +74,7 @@
 #include "mplog.h"
 #include "dpa400.h"
 #include "pem.h"
+#include "ruby_marshal.h"
 
 /*
  * Add an extension, and all compressed versions thereof, to a GSList
@@ -143,7 +144,8 @@ static const struct file_extension_info file_type_extensions_base[] = {
        { "MPEG files", FALSE, "mpg;mp3" },
        { "Transport-Neutral Encapsulation Format", FALSE, "tnef" },
        { "JPEG/JFIF files", FALSE, "jpg;jpeg;jfif" },
-       { "JavaScript Object Notation file", FALSE, "json" }
+       { "JavaScript Object Notation file", FALSE, "json" },
+       { "Ruby Marshal Object", FALSE, "" }
 };
 
 #define        N_FILE_TYPE_EXTENSIONS  (sizeof file_type_extensions_base / sizeof file_type_extensions_base[0])
@@ -402,7 +404,8 @@ static const struct open_info open_info_base[] = {
        /* Extremely weak heuristics - put them at the end. */
        { "Ixia IxVeriWave .vwr Raw Capture",       OPEN_INFO_HEURISTIC, vwr_open,                 "vwr",      NULL, NULL },
        { "CAM Inspector file",                     OPEN_INFO_HEURISTIC, camins_open,              "camins",   NULL, NULL },
-       { "JavaScript Object Notation",             OPEN_INFO_HEURISTIC, json_open,                "json",     NULL, NULL }
+       { "JavaScript Object Notation",             OPEN_INFO_HEURISTIC, json_open,                "json",     NULL, NULL },
+       { "Ruby Marshal Object",                    OPEN_INFO_HEURISTIC, ruby_marshal_open,        "",      NULL, NULL }
 };
 
 /* this is only used to build the dynamic array on load, do NOT use this
diff --git a/wiretap/ruby_marshal.c b/wiretap/ruby_marshal.c
new file mode 100644 (file)
index 0000000..1cff7cc
--- /dev/null
@@ -0,0 +1,183 @@
+/* ruby_marshal.c
+ *
+ * Routines for reading a binary file containing a ruby marshal object
+ *
+ * Copyright 2018, Dario Lombardo <lomato@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "wtap-int.h"
+#include "file_wrappers.h"
+
+#include "ruby_marshal.h"
+
+/*
+ * Impose a not-too-large limit on the maximum file size, to avoid eating
+ * up 99% of the (address space, swap partition, disk space for swap/page
+ * files); if we were to return smaller chunks and let the dissector do
+ * reassembly, it would *still* have to allocate a buffer the size of
+ * the file, so it's not as if we'd neve try to allocate a buffer the
+ * size of the file.
+ *
+ * For now, go for 50MB.
+ */
+#define MAX_FILE_SIZE (50*1024*1024)
+
+static gboolean ruby_marshal_read_file(wtap *wth, FILE_T fh, wtap_rec *rec,
+    Buffer *buf, int *err, gchar **err_info)
+{
+    gint64 file_size;
+    int packet_size;
+
+    if ((file_size = wtap_file_size(wth, err)) == -1)
+        return FALSE;
+
+    if (file_size > MAX_FILE_SIZE) {
+        /*
+         * Don't blow up trying to allocate space for an
+         * immensely-large file.
+         */
+        *err = WTAP_ERR_BAD_FILE;
+        *err_info = g_strdup_printf("ruby_marshal: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
+            file_size, MAX_FILE_SIZE);
+        return FALSE;
+    }
+    packet_size = (int)file_size;
+
+    rec->rec_type = REC_TYPE_PACKET;
+    rec->presence_flags = 0;
+
+    rec->rec_header.packet_header.caplen = packet_size;
+    rec->rec_header.packet_header.len = packet_size;
+
+    rec->ts.secs = 0;
+    rec->ts.nsecs = 0;
+
+    return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
+}
+
+static gboolean ruby_marshal_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf,
+    int *err, gchar **err_info)
+{
+    /* there is only one packet */
+    if (seek_off > 0) {
+        *err = 0;
+        return FALSE;
+    }
+
+    if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
+        return FALSE;
+
+    return ruby_marshal_read_file(wth, wth->random_fh, rec, buf, err, err_info);
+}
+
+static gboolean ruby_marshal_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
+{
+    gint64 offset;
+
+    *err = 0;
+
+    offset = file_tell(wth->fh);
+
+    /* there is only ever one packet */
+    if (offset != 0)
+        return FALSE;
+
+    *data_offset = offset;
+
+    return ruby_marshal_read_file(wth, wth->fh, &wth->rec, wth->rec_data, err, err_info);
+}
+
+static gboolean is_ruby_marshal(const guint8* filebuf)
+{
+    if (filebuf[0] != RUBY_MARSHAL_MAJOR)
+        return FALSE;
+    if (filebuf[1] != RUBY_MARSHAL_MINOR)
+        return FALSE;
+    switch (filebuf[2]) {
+        case '0':
+        case 'T':
+        case 'F':
+        case 'i':
+        case ':':
+        case '"':
+        case 'I':
+        case '[':
+        case '{':
+        case 'f':
+        case 'c':
+        case 'm':
+        case 'S':
+        case '/':
+        case 'o':
+        case 'C':
+        case 'e':
+        case ';':
+        case '@':
+            return TRUE;
+            break;
+        default:
+            return FALSE;
+    }
+}
+
+wtap_open_return_val ruby_marshal_open(wtap *wth, int *err, gchar **err_info)
+{
+    guint8* filebuf;
+    int bytes_read;
+
+    filebuf = (guint8*)g_malloc0(MAX_FILE_SIZE);
+    if (!filebuf)
+        return WTAP_OPEN_ERROR;
+
+    bytes_read = file_read(filebuf, MAX_FILE_SIZE, wth->fh);
+    if (bytes_read < 0) {
+        /* Read error. */
+        *err = file_error(wth->fh, err_info);
+        g_free(filebuf);
+        return WTAP_OPEN_ERROR;
+    }
+    if (bytes_read == 0) {
+        /* empty file, not *anybody's* */
+        g_free(filebuf);
+        return WTAP_OPEN_NOT_MINE;
+    }
+
+    if (!is_ruby_marshal(filebuf)) {
+        g_free(filebuf);
+        return WTAP_OPEN_NOT_MINE;
+    }
+
+    if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
+        g_free(filebuf);
+        return WTAP_OPEN_ERROR;
+    }
+
+    wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_RUBY_MARSHAL;
+    wth->file_encap = WTAP_ENCAP_RUBY_MARSHAL;
+    wth->file_tsprec = WTAP_TSPREC_SEC;
+    wth->subtype_read = ruby_marshal_read;
+    wth->subtype_seek_read = ruby_marshal_seek_read;
+    wth->snapshot_length = 0;
+
+    g_free(filebuf);
+    return WTAP_OPEN_MINE;
+}
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/wiretap/ruby_marshal.h b/wiretap/ruby_marshal.h
new file mode 100644 (file)
index 0000000..277bc46
--- /dev/null
@@ -0,0 +1,35 @@
+/* ruby_marshal.h
+ *
+ * Copyright 2018, Dario Lombardo <lomato@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ */
+
+#ifndef __RUBY_MARSHAL_H__
+#define __RUBY_MARSHAL_H__
+
+#include <glib.h>
+
+#include "wtap.h"
+
+// Current Ruby Marshal library version
+#define RUBY_MARSHAL_MAJOR 4
+#define RUBY_MARSHAL_MINOR 8
+
+wtap_open_return_val ruby_marshal_open(wtap *wth, int *err, gchar **err_info);
+
+#endif
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
index 8f3c235990f9ff5ec5f1f45a9412f2ca17a3e48e..4ea94b686db7b43337685fe0a7b0936f643feeb9 100644 (file)
@@ -281,6 +281,7 @@ extern "C" {
 #define WTAP_ENCAP_ETHERNET_MPACKET             198
 #define WTAP_ENCAP_DOCSIS31_XRA31               199
 #define WTAP_ENCAP_DPAUXMON                     200
+#define WTAP_ENCAP_RUBY_MARSHAL                 201
 
 /* After adding new item here, please also add new item to encap_table_base array */
 
@@ -374,6 +375,7 @@ extern "C" {
 #define WTAP_FILE_TYPE_SUBTYPE_MPLOG                         80
 #define WTAP_FILE_TYPE_SUBTYPE_DPA400                        81
 #define WTAP_FILE_TYPE_SUBTYPE_PEM                           82
+#define WTAP_FILE_TYPE_SUBTYPE_RUBY_MARSHAL                  83
 
 #define WTAP_NUM_FILE_TYPES_SUBTYPES  wtap_get_num_file_types_subtypes()