Matteo Cafasso
2016-Mar-07 19:22 UTC
[Libguestfs] [PATCH 0/3] added The Sleuth Kit and icat API for downloading inaccessible files
The Sleuth Kit is a filesystem forensic tool for accessing disk volumes and extracting digital evidence from. http://www.sleuthkit.org/ The icat API allows to download a file from a device given its metadata number (inode). It supports multiple filesystem types. The icat command allows to access to otherwise unreachable files such as filesystem data structures and deleted files which content is still partially or totally stored on the device. Matteo Cafasso (3): added The Sleuth Kit package to the appliance added icat API to retrieve deleted or inaccessible files added icat API tests Makefile.am | 1 + appliance/packagelist.in | 3 ++ configure.ac | 1 + daemon/Makefile.am | 1 + daemon/tsk.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 13 ++++++ po/POTFILES | 1 + src/MAX_PROC_NR | 2 +- tests/tsk/Makefile.am | 26 +++++++++++ tests/tsk/test-icat.sh | 53 ++++++++++++++++++++++ 10 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 daemon/tsk.c create mode 100644 tests/tsk/Makefile.am create mode 100755 tests/tsk/test-icat.sh -- 2.7.0
Matteo Cafasso
2016-Mar-07 19:22 UTC
[Libguestfs] [PATCH 1/3] added The Sleuth Kit package to the appliance
Signed-off-by: Matteo Cafasso <noxdafox@gmail.com> --- appliance/packagelist.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appliance/packagelist.in b/appliance/packagelist.in index aa5e07e..0951417 100644 --- a/appliance/packagelist.in +++ b/appliance/packagelist.in @@ -46,6 +46,7 @@ ifelse(REDHAT,1, pcre reiserfs-utils libselinux + sleuthkit syslinux-extlinux systemd dnl for /sbin/reboot and udevd vim-minimal @@ -89,6 +90,7 @@ dnl iproute has been renamed to iproute2 ntfs-3g openssh-client reiserfsprogs + sleuthkit sysvinit dnl for /sbin/reboot systemd dnl alternative for /sbin/reboot ufsutils @@ -120,6 +122,7 @@ ifelse(ARCHLINUX,1, ntfs-3g pcre reiserfsprogs + sleuthkit systemd vim xz -- 2.7.0
Matteo Cafasso
2016-Mar-07 19:22 UTC
[Libguestfs] [PATCH 2/3] added icat API to retrieve deleted or inaccessible files
Signed-off-by: Matteo Cafasso <noxdafox@gmail.com> --- daemon/Makefile.am | 1 + daemon/tsk.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 13 ++++++ po/POTFILES | 1 + src/MAX_PROC_NR | 2 +- 5 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 daemon/tsk.c diff --git a/daemon/Makefile.am b/daemon/Makefile.am index caba83e..4e2051b 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -179,6 +179,7 @@ guestfsd_SOURCES = \ syslinux.c \ tar.c \ truncate.c \ + tsk.c \ umask.c \ upload.c \ utimens.c \ diff --git a/daemon/tsk.c b/daemon/tsk.c new file mode 100644 index 0000000..647d1e7 --- /dev/null +++ b/daemon/tsk.c @@ -0,0 +1,114 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2016 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <unistd.h> + +#include "guestfs_protocol.h" +#include "daemon.h" +#include "actions.h" +#include "optgroups.h" + +static int file_out (const char *cmd); + +GUESTFSD_EXT_CMD(str_tsk_probe, icat); + +int +optgroup_icat_available (void) +{ + return prog_exists (str_tsk_probe); +} + +int +do_icat (const mountable_t *mountable, int64_t inode) +{ + CLEANUP_FREE char *cmd = NULL; + + /* Inode must be greater than 0 */ + if (inode < 0) { + reply_with_error ("inode must be >= 0"); + return -1; + } + + /* Construct the command. */ + if (asprintf (&cmd, "icat -r %s %" PRIi64, mountable->device, inode) == -1) { + reply_with_perror ("asprintf"); + return -1; + } + + return file_out (cmd); +} + +static int +file_out (const char *cmd) +{ + int r; + FILE *fp; + CLEANUP_FREE char *buffer = NULL; + + if (verbose) + fprintf (stderr, "%s\n", cmd); + + buffer = malloc (GUESTFS_MAX_CHUNK_SIZE); + if (buffer == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + fp = popen (cmd, "r"); + if (fp == NULL) { + reply_with_perror ("%s", cmd); + return -1; + } + + /* Now we must send the reply message, before the file contents. After + * this there is no opportunity in the protocol to send any error + * message back. Instead we can only cancel the transfer. + */ + reply (NULL, NULL); + + while ((r = fread (buffer, 1, sizeof buffer, fp)) > 0) { + if (send_file_write (buffer, r) < 0) { + pclose (fp); + return -1; + } + } + + if (ferror (fp)) { + fprintf (stderr, "fread: %m"); + send_file_end (1); /* Cancel. */ + pclose (fp); + return -1; + } + + if (pclose (fp) != 0) { + fprintf (stderr, "pclose: %m"); + send_file_end (1); /* Cancel. */ + return -1; + } + + if (send_file_end (0)) /* Normal end of file. */ + return -1; + + return 0; +} diff --git a/generator/actions.ml b/generator/actions.ml index 287d7f5..36d08ad 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12919,6 +12919,19 @@ within the C<$Extend> folder. The filesystem from which to extract the file must be unmounted, otherwise the call will fail." }; + { defaults with + name = "icat"; added = (1, 33, 14); + style = RErr, [Mountable "device"; Int64 "inode"; FileOut "filename"], []; + proc_nr = Some 464; + optional = Some "icat"; + progress = true; cancellable = true; + shortdesc = "download a file to the local machine given its inode"; + longdesc = "\ +Download a file given its inode from the disk partition (eg. F</dev/sda1>) +and save it as F<filename> on the local machine. + +This allows to download deleted or inaccessible files." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/po/POTFILES b/po/POTFILES index 0fb99b0..4fbc551 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -108,6 +108,7 @@ daemon/sync.c daemon/syslinux.c daemon/tar.c daemon/truncate.c +daemon/tsk.c daemon/umask.c daemon/upload.c daemon/utimens.c diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 26551cf..3bb8a49 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -463 +464 -- 2.7.0
Signed-off-by: Matteo Cafasso <noxdafox@gmail.com> --- Makefile.am | 1 + configure.ac | 1 + tests/tsk/Makefile.am | 26 +++++++++++++++++++++++++ tests/tsk/test-icat.sh | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 tests/tsk/Makefile.am create mode 100755 tests/tsk/test-icat.sh diff --git a/Makefile.am b/Makefile.am index fe92630..42ff072 100644 --- a/Makefile.am +++ b/Makefile.am @@ -83,6 +83,7 @@ SUBDIRS += tests/journal SUBDIRS += tests/relative-paths SUBDIRS += tests/gdisk SUBDIRS += tests/regressions +SUBDIRS += tests/tsk endif # libguestfs-test-tool diff --git a/configure.ac b/configure.ac index fd8e534..c031707 100644 --- a/configure.ac +++ b/configure.ac @@ -281,6 +281,7 @@ AC_CONFIG_FILES([Makefile tests/selinux/Makefile tests/syslinux/Makefile tests/tmpdirs/Makefile + tests/tsk/Makefile tests/xfs/Makefile tests/xml/Makefile tools/Makefile diff --git a/tests/tsk/Makefile.am b/tests/tsk/Makefile.am new file mode 100644 index 0000000..e060e58 --- /dev/null +++ b/tests/tsk/Makefile.am @@ -0,0 +1,26 @@ +# libguestfs +# Copyright (C) 2016 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +include $(top_srcdir)/subdir-rules.mk + +TESTS = \ + test-icat.sh + +TESTS_ENVIRONMENT = $(top_builddir)/run --test + +EXTRA_DIST = \ + $(TESTS) diff --git a/tests/tsk/test-icat.sh b/tests/tsk/test-icat.sh new file mode 100755 index 0000000..e1fdc5a --- /dev/null +++ b/tests/tsk/test-icat.sh @@ -0,0 +1,53 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2016 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Test the icat command. + +set -e + +if [ -n "$SKIP_TEST_ICAT_SH" ]; then + echo "$0: test skipped because environment variable is set." + exit 77 +fi + +rm -f test-mft.bin + +# Skip if TSK is not supported by the appliance. +if ! guestfish add /dev/null : run : available "icat"; then + echo "$0: skipped because TSK is not available in the appliance" + exit 77 +fi + +if [ ! -s ../../test-data/phony-guests/windows.img ]; then + echo "$0: skipped because windows.img is zero-sized" + exit 77 +fi + +# download Master File Table ($MFT). +guestfish --ro -a ../../test-data/phony-guests/windows.img <<EOF +run +icat /dev/sda2 0 test-mft.bin +EOF + +# test extracted file is the Master File Table +if [ `head -c 5 test-mft.bin` != "FILE0" ]; then + echo "$0: wrong file extracted." + exit 1 +fi + +rm -f test-mft.bin -- 2.7.0
Richard W.M. Jones
2016-Mar-07 19:45 UTC
Re: [Libguestfs] [PATCH 2/3] added icat API to retrieve deleted or inaccessible files
Thanks, I have pushed this patch series. Could you consider changing:> + optional = Some "icat";I think it would be nice to have a single feature, and to call the feature "sleuthkit" or "forensics" or something like that. We don't need to have one feature per API since installation of a single package (sleuthkit) is sufficient to make all the APIs available. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into KVM guests. http://libguestfs.org/virt-v2v