[Libguestfs] [PATCH v3 4/6] New API: internal_yara_scan

Matteo Cafasso
2016-12-18T10:47:09Z

The internal_yara_scan runs the Yara engine with the previously loaded
rules against the given file.

For each rule matching against the scanned file, a struct containing
the file name and the rule identifier is returned.

The gathered list of yara_detection structs is serialised into XDR format
and written to a file.

Signed-off-by: Matteo Cafasso <noxdafox@gmail.com>
---
 daemon/yara.c                            | 86 ++++++++++++++++++++++++++++++++
 generator/actions.ml                     | 10 ++++
 generator/structs.ml                     |  9 ++++
 gobject/Makefile.inc                     |  2 +
 java/Makefile.inc                        |  1 +
 java/com/redhat/et/libguestfs/.gitignore |  1 +
 src/MAX_PROC_NR                          |  2 +-
 7 files changed, 110 insertions(+), 1 deletion(-)

diff --git a/daemon/yara.c b/daemon/yara.c
index cb49593..4715473 100644
--- a/daemon/yara.c
+++ b/daemon/yara.c
@@ -54,6 +54,8 @@ static bool initialized = false;
 static int compile_rules_file (const char *, const char *);
 static void compile_error_callback (int, const char *, int, const char *, void
*);
 static void cleanup_destroy_yara_compiler (void *ptr);
+static int yara_rules_callback (int , void *, void *);
+static int send_detection_info (const char *, YR_RULE *);

 /* Has one FileIn parameter.
  * Takes optional arguments, consult optargs_bitmask.
@@ -119,6 +121,38 @@ do_yara_destroy (void)
   return 0;
 }

+/* Has one FileOut parameter. */
+int
+do_internal_yara_scan (const char *path)
+{
+  int ret = 0;
+  CLEANUP_CLOSE int fd = -1;
+
+  if (rules == NULL) {
+    reply_with_error ("no yara rules loaded");
+    return -1;
+  }
+
+  CHROOT_IN;
+  fd = open (path, O_RDONLY|O_CLOEXEC);
+  CHROOT_OUT;
+
+  if (fd < 0) {
+    reply_with_perror ("%s", path);
+    return -1;
+  }
+
+  reply (NULL, NULL);  /* Reply message. */
+
+  ret = yr_rules_scan_fd (rules, fd, 0, yara_rules_callback, (void *) path, 0);
+  if (ret == ERROR_SUCCESS)
+    ret = send_file_end (0);  /* File transfer end. */
+  else
+    send_file_end (1);  /* Cancel file transfer. */
+
+  return 0;
+}
+
 /* Compile source code rules and load them.
  * Return ERROR_SUCCESS on success, Yara error code type on error.
  */
@@ -170,6 +204,58 @@ compile_error_callback(int level, const char *name, int
line,
     fprintf (stderr, "Yara warning (line %d): %s\n", line, message);
 }

+/* Yara scan callback, called by yr_rules_scan_file.
+ * Return 0 on success, -1 on error.
+ */
+static int
+yara_rules_callback (int code, void *message, void *data)
+{
+  int ret = 0;
+
+  if (code == CALLBACK_MSG_RULE_MATCHING)
+    ret = send_detection_info ((const char *)data, (YR_RULE *) message);
+
+  return (ret == 0) ? CALLBACK_CONTINUE : CALLBACK_ERROR;
+}
+
+/* Serialize file path and rule name and send it out.
+ * Return 0 on success, -1 on error.
+ */
+static int
+send_detection_info (const char *name, YR_RULE *rule)
+{
+  XDR xdr;
+  int ret = 0;
+  size_t len = 0;
+  CLEANUP_FREE char *buf = NULL;
+  struct guestfs_int_yara_detection detection;
+
+  detection.name = (char *) name;
+  detection.rule = (char *) rule->identifier;
+
+  /* Serialize detection struct. */
+  buf = malloc (GUESTFS_MAX_CHUNK_SIZE);
+  if (buf == NULL) {
+    perror ("malloc");
+    return -1;
+  }
+
+  xdrmem_create (&xdr, buf, GUESTFS_MAX_CHUNK_SIZE, XDR_ENCODE);
+
+  ret = xdr_guestfs_int_yara_detection (&xdr, &detection);
+  if (ret == 0) {
+    perror ("xdr_guestfs_int_yara_detection");
+    return -1;
+  }
+
+  len = xdr_getpos (&xdr);
+
+  xdr_destroy (&xdr);
+
+  /* Send serialised yara_detection out. */
+  return send_file_write (buf, len);
+}
+
 /* Clean up yara handle on daemon exit. */
 void yara_finalize (void) __attribute__((destructor));

diff --git a/generator/actions.ml b/generator/actions.ml
index b9055c4..75da607 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -13295,4 +13295,14 @@ but belonging to different files." };
     shortdesc = "destroy previously loaded yara rules";
     longdesc = "\
 Destroy previously loaded Yara rules in order to free libguestfs
resources." };
+
+  { defaults with
+    name = "internal_yara_scan"; added = (1, 35, 19);
+    style = RErr, [Pathname "path"; FileOut "filename";],
[];
+    proc_nr = Some 473;
+    visibility = VInternal;
+    optional = Some "libyara";
+    shortdesc = "scan a file with the loaded yara rules";
+    longdesc = "Internal function for yara_scan." };
+
 ]

 (* Non-API meta-commands available only in guestfish.
diff --git a/generator/structs.ml b/generator/structs.ml
index 029bc3a..3fa2ebc 100644
--- a/generator/structs.ml
+++ b/generator/structs.ml
@@ -468,6 +468,15 @@ let structs = [
     ];
     s_camel_name = "TSKDirent" };

+  (* Yara detection information. *)
+  { defaults with
+    s_name = "yara_detection";
+    s_cols = [
+    "name", FString;
+    "rule", FString;
+    ];
+    s_camel_name = "YaraDetection" };
+
 ] (* end of structs *)

 let lookup_struct name diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc
index a41a552..26a63d9 100644
--- a/gobject/Makefile.inc
+++ b/gobject/Makefile.inc
@@ -49,6 +49,7 @@ guestfs_gobject_headers= \
   include/guestfs-gobject/struct-version.h \
   include/guestfs-gobject/struct-xattr.h \
   include/guestfs-gobject/struct-xfsinfo.h \
+  include/guestfs-gobject/struct-yara_detection.h \
   include/guestfs-gobject/optargs-add_domain.h \
   include/guestfs-gobject/optargs-add_drive.h \
   include/guestfs-gobject/optargs-add_drive_scratch.h \
@@ -141,6 +142,7 @@ guestfs_gobject_sources= \
   src/struct-version.c \
   src/struct-xattr.c \
   src/struct-xfsinfo.c \
+  src/struct-yara_detection.c \
   src/optargs-add_domain.c \
   src/optargs-add_drive.c \
   src/optargs-add_drive_scratch.c \
diff --git a/java/Makefile.inc b/java/Makefile.inc
index 59b55eb..acf2a2f 100644
--- a/java/Makefile.inc
+++ b/java/Makefile.inc
@@ -46,4 +46,5 @@ java_built_sources = \
 	com/redhat/et/libguestfs/Version.java \
 	com/redhat/et/libguestfs/XAttr.java \
 	com/redhat/et/libguestfs/XFSInfo.java \
+	com/redhat/et/libguestfs/YaraDetection.java \
 	com/redhat/et/libguestfs/GuestFS.java
diff --git a/java/com/redhat/et/libguestfs/.gitignore
b/java/com/redhat/et/libguestfs/.gitignore
index 89d9239..bc03cb9 100644
--- a/java/com/redhat/et/libguestfs/.gitignore
+++ b/java/com/redhat/et/libguestfs/.gitignore
@@ -23,3 +23,4 @@ VG.java
 Version.java
 XAttr.java
 XFSInfo.java
+YaraDetection.java
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 68cfb10..8410b8b 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-472
+473
--
2.10.2