[Forensics-changes] [SCM] debian-forensics/md5deep branch, upstream, updated. upstream/3.9.2-2-g864876c
Michael Prokop
mika at debian.org
Thu Jun 14 15:56:58 UTC 2012
The following commit has been merged in the upstream branch:
commit 864876c9158b35e468dc3c62f6f9320252ff2a80
Author: Michael Prokop <mika at debian.org>
Date: Thu Jun 14 17:54:26 2012 +0200
Importing upstream version 4.2
diff --git a/COPYING b/COPYING
index 4bff23a..1f9bbd1 100644
--- a/COPYING
+++ b/COPYING
@@ -1,20 +1,18 @@
+This program is divided into two parts, the Tiger code and everything
+else. Let's start with everything else:
-This program is divided into two parts, the Tiger+strsep ccode and
-everything else. Let's start with everything else:
-
-This program is a work of the US Government. In accordance with 17 USC
-105, copyright protection is not available for any work of the US
-Government. As such this code is considered public domain. There is NO
-warranty for this program; not even for MERCHANTABILITY or FITNESS FOR A
+This program is a work of the US Government. In accordance with 17 USC
+105, copyright protection is not available for any work of the US
+Government. As such this code is considered public domain. There is NO
+warranty for this program; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
-The code for Tiger comes from the GnuPG project and is licensed under
-the General Public License (GPL). The code from strsep comes from the
-gnulib library and is also GPL'ed.
+The code for Tiger comes from the libgcrypt project and is licensed
+under the General Public License (GPL).
-Because the vast majority of this program is public domain, the license
-of this project as whole remains public domain. The Tiger code itself is
-still licensed under the GPL. Note that this dual licensing scheme does
+Because the vast majority of this program is public domain, the license
+of this project as whole remains public domain. The Tiger code itself is
+still licensed under the GPL. Note that this dual licensing scheme does
not violate the terms of the GPL. Please see the GPL FAQ, specifically:
http://www.fsf.org/licensing/licenses/gpl-faq.html#CombinePublicDomainWithGPL
diff --git a/ChangeLog b/ChangeLog
index 51d051e..534b331 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,48 @@
+2012-06-09 Jesse Kornblum <research at jessekornblum.com>:
+
+ * src/tiger.h tiger.c: Replaced with newer code from libgcrypt.
+ * configure.ac: Version bump to 4.2
+
+2012-06-05 Jesse Kornblum <research at jessekornblum.com>:
+
+ * src/dig.cpp: Cosmetic formatting. Fixed Win32 stat function.
+ * src/display.cpp: Commented out vasprintf, which is now present on mingw
+ * src/hashlist.cpp: Formatting. Revised to handle case where filename is a hash.
+ * src/sha1_version.c: Removed vestigial code
+
+2012-06-04 Jesse Kornblum <research at jessekornblum.com>:
+
+ * src/hashlist.cpp: Formatting. Addressed bug with filenames with commas in them.
+
+2012-05-20 Jesse Kornblum <research at jessekornblum.com>:
+
+ * man/md5deep1,hashdeep.1: Fixed typo in -j mode
+
+2012-02-27 Simson Garfinkel <simsong at Mucha.local>
+
+ * src/dig.cpp (state::decode_file_type): removed from state, since it didn't use any of the instance variables.
+
+2012-02-27 Jesse Kornblum <research at jessekornblum.com>:
+
+ * main.cpp: Removed -B command line flag from all programs
+
+2012-02-27 Jesse Kornblum <research at jessekornblum.com>:
+
+ * man/md5deep.1: Added Simson to the AUTHORS section
+ * src/main.cpp: Formatted usage messages
+ * configure.ac: Version bump to 4.1.1
+ * Makefile.am: Added doc to directories cleaned with make nice
+
+2012-02-26 Simson Garfinkel <simsong at FC15>
+
+ * src/main.h (d): fixed THREAD typo.
+ * src/display.cpp: changed #if so that it checks for MINGW and not __MINGW_H
+ * configure.ac (MINGW): now explicitly sets MINGW if we are compiling under mingw.
+
+2012-02-10 Jesse Kornblum <research at jessekornblum.com>:
+
+ * doc/start-hashdeep.html: Clarified how to run the programs.
+
2012-02-10 Jesse Kornblum <research at jessekornblum.com>:
* sample-hashes/sample.{c,jpg}: Added Windows executable with non-executable extension
@@ -9,7 +54,7 @@
* src/dig.cpp, winpe.h, winpe.cpp, main.cpp: Added check for Windows PE files to expert mode.
-2012-01-30 Jesse Kornblum <research at jessekornblum.com:>
+2012-01-30 Jesse Kornblum <research at jessekornblum.com>:
* src/display.cpp: Reverted previous change, but updated test for presence of vasprintf.
diff --git a/Makefile.am b/Makefile.am
index 78d6d30..ae3c9db 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,7 +10,7 @@ CROSS64_PREFIX = x86_64-w64-mingw32
EXTRA_DIST = FILEFORMAT config.guess config.sub m4/ax_pthread.m4 CONFIGURE_FC.sh
nice:
- rm -f *~ man/*~ src/*~
+ rm -f *~ man/*~ src/*~ doc/*~
preflight:
grep RBF */*.{c,cpp,h,1} doc/* AUTHORS README NEWS TODO ChangeLog
diff --git a/Makefile.in b/Makefile.in
index e8b3f6c..46fe940 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -703,7 +703,7 @@ uninstall-am:
nice:
- rm -f *~ man/*~ src/*~
+ rm -f *~ man/*~ src/*~ doc/*~
preflight:
grep RBF */*.{c,cpp,h,1} doc/* AUTHORS README NEWS TODO ChangeLog
diff --git a/NEWS b/NEWS
index 768a09d..0027ddf 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,19 @@
+** Changes in version 4.2 (11 Jun 2012)
+
+* Bug Fixes
+
+ Fixed padding in Tiger hashes for large files
+
+
+
+** Changes in version 4.1.1 (5 Jun 2012)
+
+* Bug Fixes
+
+ Fixed hashdeep bug for known files with commas in their names.
+ Cleaned up usage message
+
+
** Changes in version 4.1.0 (14 Feb 2012)
* New Features
diff --git a/config.h.in b/config.h.in
index 5cdcf12..9622fe4 100644
--- a/config.h.in
+++ b/config.h.in
@@ -210,6 +210,9 @@
slash. */
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+/* We are cross-compiling with MINGW */
+#undef MINGW
+
/* Name of package */
#undef PACKAGE
diff --git a/configure b/configure
index 807725e..f86ff7d 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for MD5DEEP 4.1.
+# Generated by GNU Autoconf 2.68 for MD5DEEP 4.2.
#
# Report bugs to <research at jessekornblum.com>.
#
@@ -560,8 +560,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='MD5DEEP'
PACKAGE_TARNAME='md5deep'
-PACKAGE_VERSION='4.1'
-PACKAGE_STRING='MD5DEEP 4.1'
+PACKAGE_VERSION='4.2'
+PACKAGE_STRING='MD5DEEP 4.2'
PACKAGE_BUGREPORT='research at jessekornblum.com'
PACKAGE_URL=''
@@ -1264,7 +1264,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures MD5DEEP 4.1 to adapt to many kinds of systems.
+\`configure' configures MD5DEEP 4.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1334,7 +1334,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of MD5DEEP 4.1:";;
+ short | recursive ) echo "Configuration of MD5DEEP 4.2:";;
esac
cat <<\_ACEOF
@@ -1429,7 +1429,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-MD5DEEP configure 4.1
+MD5DEEP configure 4.2
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -1947,7 +1947,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by MD5DEEP $as_me 4.1, which was
+It was created by MD5DEEP $as_me 4.2, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -2764,7 +2764,7 @@ fi
# Define the identity of the package.
PACKAGE='md5deep'
- VERSION='4.1'
+ VERSION='4.2'
cat >>confdefs.h <<_ACEOF
@@ -4201,6 +4201,9 @@ $as_echo "#define __LINUX__ 1" >>confdefs.h
CPPFLAGS="-DUNICODE -D_UNICODE -D__MSVCRT_VERSION__=0x0601 -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -DHAVE_STRUCT_TIMESPEC $CPPFLAGS"
CXXFLAGS="$CXXFLAGS -Wno-format " # compiler mingw-4.3.0 is broken on I64u formats
CXXFLAGS="$CXXFLAGS --static"
+
+$as_echo "#define MINGW 1" >>confdefs.h
+
mingw="yes"
;;
esac
@@ -7253,7 +7256,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by MD5DEEP $as_me 4.1, which was
+This file was extended by MD5DEEP $as_me 4.2, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -7319,7 +7322,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-MD5DEEP config.status 4.1
+MD5DEEP config.status 4.2
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 639c223..f624edf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
#
AC_PREREQ(2.57)
-AC_INIT([MD5DEEP],[4.1],[research at jessekornblum.com])
+AC_INIT([MD5DEEP],[4.2],[research at jessekornblum.com])
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile tests/Makefile tests/testfiles/Makefile ])
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([config.h])
@@ -37,6 +37,7 @@ case $host in
CPPFLAGS="-DUNICODE -D_UNICODE -D__MSVCRT_VERSION__=0x0601 -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -DHAVE_STRUCT_TIMESPEC $CPPFLAGS"
CXXFLAGS="$CXXFLAGS -Wno-format " # compiler mingw-4.3.0 is broken on I64u formats
CXXFLAGS="$CXXFLAGS --static"
+ AC_DEFINE([MINGW],1,[We are cross-compiling with MINGW])
mingw="yes"
;;
esac
diff --git a/man/hashdeep.1 b/man/hashdeep.1
index 95ae363..e4f92a2 100644
--- a/man/hashdeep.1
+++ b/man/hashdeep.1
@@ -1,4 +1,4 @@
-.TH HASHDEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force"
+.TH HASHDEEP "1" "v4.2 \- 11 Jun 2012" "AFOSI" "United States Air Force"
.SH NAME
hashdeep \- Compute, compare, or audit multiple message digests
@@ -9,7 +9,7 @@ hashdeep \- Compute, compare, or audit multiple message digests
.br
.B hashdeep
[-c <alg1>[,<alg2>]] [-k <file>] [-i <size>] [\-f <file>]
-[\-o <fbcplsde>] [-amxwMXrespblvv] [\-F<bum>] [\-jnn] [\fBFILES\fR]
+[\-o <fbcplsde>] [-amxwMXrespblvv] [\-F<bum>] [\-j <num>] [\fBFILES\fR]
.SH DESCRIPTION
@@ -197,7 +197,7 @@ This mostly changes the behvaior of the audit mode, \-a.
.TP
\fB-jnn\fR
Controls multi-threading. By default the program will create one
-producer thread to scna the file system and one hashing thread per CPU
+producer thread to scan the file system and one hashing thread per CPU
core. Multi-threading causes output filenames to be in
non-deterministic order, as files that take longer to hash will be
delayed while they are hashed. If a deterministic order is required,
@@ -261,7 +261,8 @@ only one file with a .txt extension).
Returns zero on success, one on error.
.SH AUTHOR
-hashdeep was written by Jesse Kornblum, research at jessekornblum.com.
+hashdeep was written by Jesse Kornblum, research at jessekornblum.com,
+and Simson Garfinkel.
.SH KNOWN ISSUES
Using the \-r flag cannot be used to recursively process all files
diff --git a/man/md5deep.1 b/man/md5deep.1
index fc4bcbe..4cf3f31 100644
--- a/man/md5deep.1
+++ b/man/md5deep.1
@@ -1,4 +1,4 @@
-.TH MD5DEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force"
+.TH MD5DEEP "1" "v4.2 \- 11 Jun 2012" "AFOSI" "United States Air Force"
.SH NAME
md5deep \- Compute and compare MD5 message digests
@@ -17,8 +17,8 @@ whirlpooldeep \- Compute and compare Whirlpool message digests
.br
.B md5deep
[\-m|\-M|\-x|\-X <file>] [-a|-A <hash>] [\-f <file>]
-[\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F<bum>]
-[\-o <fbcplsde>] [\-jnn] [[\fBFILES\fR]
+[\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F <bum>]
+[\-o <fbcplsde>] [\-j <num>] [[\fBFILES\fR]
.SH DESCRIPTION
.PP
@@ -225,7 +225,7 @@ e \- Windows PE executables
.TP
\fB-jnn\fR
Controls multi-threading. By default the program will create one
-producer thread to scna the file system and one hashing thread per CPU
+producer thread to scan the file system and one hashing thread per CPU
core. Multi-threading causes output filenames to be in
non-deterministic order, as files that take longer to hash will be
delayed while they are hashed. If a deterministic order is required,
@@ -315,7 +315,8 @@ be reported to the developer! See the section "Reporting Bugs" below.
.SH AUTHOR
-md5deep was written by Jesse Kornblum, research at jessekornblum.com.
+md5deep was written by Jesse Kornblum, research at jessekornblum.com
+and Simson Garfinkel.
.SH KNOWN ISSUES
Using the \-r flag cannot be used to recursively process all files
diff --git a/man/sha1deep.1 b/man/sha1deep.1
index fc4bcbe..4cf3f31 100644
--- a/man/sha1deep.1
+++ b/man/sha1deep.1
@@ -1,4 +1,4 @@
-.TH MD5DEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force"
+.TH MD5DEEP "1" "v4.2 \- 11 Jun 2012" "AFOSI" "United States Air Force"
.SH NAME
md5deep \- Compute and compare MD5 message digests
@@ -17,8 +17,8 @@ whirlpooldeep \- Compute and compare Whirlpool message digests
.br
.B md5deep
[\-m|\-M|\-x|\-X <file>] [-a|-A <hash>] [\-f <file>]
-[\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F<bum>]
-[\-o <fbcplsde>] [\-jnn] [[\fBFILES\fR]
+[\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F <bum>]
+[\-o <fbcplsde>] [\-j <num>] [[\fBFILES\fR]
.SH DESCRIPTION
.PP
@@ -225,7 +225,7 @@ e \- Windows PE executables
.TP
\fB-jnn\fR
Controls multi-threading. By default the program will create one
-producer thread to scna the file system and one hashing thread per CPU
+producer thread to scan the file system and one hashing thread per CPU
core. Multi-threading causes output filenames to be in
non-deterministic order, as files that take longer to hash will be
delayed while they are hashed. If a deterministic order is required,
@@ -315,7 +315,8 @@ be reported to the developer! See the section "Reporting Bugs" below.
.SH AUTHOR
-md5deep was written by Jesse Kornblum, research at jessekornblum.com.
+md5deep was written by Jesse Kornblum, research at jessekornblum.com
+and Simson Garfinkel.
.SH KNOWN ISSUES
Using the \-r flag cannot be used to recursively process all files
diff --git a/man/sha256deep.1 b/man/sha256deep.1
index fc4bcbe..4cf3f31 100644
--- a/man/sha256deep.1
+++ b/man/sha256deep.1
@@ -1,4 +1,4 @@
-.TH MD5DEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force"
+.TH MD5DEEP "1" "v4.2 \- 11 Jun 2012" "AFOSI" "United States Air Force"
.SH NAME
md5deep \- Compute and compare MD5 message digests
@@ -17,8 +17,8 @@ whirlpooldeep \- Compute and compare Whirlpool message digests
.br
.B md5deep
[\-m|\-M|\-x|\-X <file>] [-a|-A <hash>] [\-f <file>]
-[\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F<bum>]
-[\-o <fbcplsde>] [\-jnn] [[\fBFILES\fR]
+[\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F <bum>]
+[\-o <fbcplsde>] [\-j <num>] [[\fBFILES\fR]
.SH DESCRIPTION
.PP
@@ -225,7 +225,7 @@ e \- Windows PE executables
.TP
\fB-jnn\fR
Controls multi-threading. By default the program will create one
-producer thread to scna the file system and one hashing thread per CPU
+producer thread to scan the file system and one hashing thread per CPU
core. Multi-threading causes output filenames to be in
non-deterministic order, as files that take longer to hash will be
delayed while they are hashed. If a deterministic order is required,
@@ -315,7 +315,8 @@ be reported to the developer! See the section "Reporting Bugs" below.
.SH AUTHOR
-md5deep was written by Jesse Kornblum, research at jessekornblum.com.
+md5deep was written by Jesse Kornblum, research at jessekornblum.com
+and Simson Garfinkel.
.SH KNOWN ISSUES
Using the \-r flag cannot be used to recursively process all files
diff --git a/man/tigerdeep.1 b/man/tigerdeep.1
index fc4bcbe..4cf3f31 100644
--- a/man/tigerdeep.1
+++ b/man/tigerdeep.1
@@ -1,4 +1,4 @@
-.TH MD5DEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force"
+.TH MD5DEEP "1" "v4.2 \- 11 Jun 2012" "AFOSI" "United States Air Force"
.SH NAME
md5deep \- Compute and compare MD5 message digests
@@ -17,8 +17,8 @@ whirlpooldeep \- Compute and compare Whirlpool message digests
.br
.B md5deep
[\-m|\-M|\-x|\-X <file>] [-a|-A <hash>] [\-f <file>]
-[\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F<bum>]
-[\-o <fbcplsde>] [\-jnn] [[\fBFILES\fR]
+[\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F <bum>]
+[\-o <fbcplsde>] [\-j <num>] [[\fBFILES\fR]
.SH DESCRIPTION
.PP
@@ -225,7 +225,7 @@ e \- Windows PE executables
.TP
\fB-jnn\fR
Controls multi-threading. By default the program will create one
-producer thread to scna the file system and one hashing thread per CPU
+producer thread to scan the file system and one hashing thread per CPU
core. Multi-threading causes output filenames to be in
non-deterministic order, as files that take longer to hash will be
delayed while they are hashed. If a deterministic order is required,
@@ -315,7 +315,8 @@ be reported to the developer! See the section "Reporting Bugs" below.
.SH AUTHOR
-md5deep was written by Jesse Kornblum, research at jessekornblum.com.
+md5deep was written by Jesse Kornblum, research at jessekornblum.com
+and Simson Garfinkel.
.SH KNOWN ISSUES
Using the \-r flag cannot be used to recursively process all files
diff --git a/man/whirlpooldeep.1 b/man/whirlpooldeep.1
index fc4bcbe..4cf3f31 100644
--- a/man/whirlpooldeep.1
+++ b/man/whirlpooldeep.1
@@ -1,4 +1,4 @@
-.TH MD5DEEP "1" "v4.1.0 \- 14 Feb 2012" "AFOSI" "United States Air Force"
+.TH MD5DEEP "1" "v4.2 \- 11 Jun 2012" "AFOSI" "United States Air Force"
.SH NAME
md5deep \- Compute and compare MD5 message digests
@@ -17,8 +17,8 @@ whirlpooldeep \- Compute and compare Whirlpool message digests
.br
.B md5deep
[\-m|\-M|\-x|\-X <file>] [-a|-A <hash>] [\-f <file>]
-[\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F<bum>]
-[\-o <fbcplsde>] [\-jnn] [[\fBFILES\fR]
+[\-p <size>] [\-i <size>] [\-tnwzresS0lbkqZud] [\-F <bum>]
+[\-o <fbcplsde>] [\-j <num>] [[\fBFILES\fR]
.SH DESCRIPTION
.PP
@@ -225,7 +225,7 @@ e \- Windows PE executables
.TP
\fB-jnn\fR
Controls multi-threading. By default the program will create one
-producer thread to scna the file system and one hashing thread per CPU
+producer thread to scan the file system and one hashing thread per CPU
core. Multi-threading causes output filenames to be in
non-deterministic order, as files that take longer to hash will be
delayed while they are hashed. If a deterministic order is required,
@@ -315,7 +315,8 @@ be reported to the developer! See the section "Reporting Bugs" below.
.SH AUTHOR
-md5deep was written by Jesse Kornblum, research at jessekornblum.com.
+md5deep was written by Jesse Kornblum, research at jessekornblum.com
+and Simson Garfinkel.
.SH KNOWN ISSUES
Using the \-r flag cannot be used to recursively process all files
diff --git a/src/dig.cpp b/src/dig.cpp
index 89e5a3f..bf485af 100644
--- a/src/dig.cpp
+++ b/src/dig.cpp
@@ -1,6 +1,6 @@
// MD5DEEP - dig.c
//
-// By Jesse Kornblum
+// By Jesse Kornblum and Simson Garfinkel
//
// This is a work of the US Government. In accordance with 17 USC 105,
// copyright protection is not available for any work of the US Government.
@@ -9,18 +9,146 @@
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
-//
+
/* The functions in this file will recurse through a directory
* and call hash_file(fn) for every file that needs to be hashes.
*/
-// $Id: dig.cpp 618 2012-02-10 12:12:38Z jessekornblum $
+// $Id: dig.cpp 632 2012-06-05 11:00:58Z jessekornblum $
#include "main.h"
#include "winpe.h"
#include <iostream>
+/*
+ * file stat system
+ */
+
+// Use a stat function to look up while kind of file this is
+// and determine its size if possible
+#ifdef _WIN32
+#define TSTAT(path,buf) _wstat64(path,buf)
+#define TLSTAT(path,buf) _wstat64(path,buf) // no lstat on windows
+#else
+#define TSTAT(path,buf) stat(path,buf)
+#define TLSTAT(path,buf) lstat(path,buf)
+#endif
+
+// Returns TRUE if the directory is '.' or '..', otherwise FALSE
+static bool is_special_dir(const tstring &d)
+{
+ return global::make_utf8(d)=="." || global::make_utf8(d)=="..";
+}
+
+/* Determine the file type of a structure
+ * called by file_type() and should_hash_symlink()
+ */
+
+file_types file_metadata_t::decode_file_type(const struct __stat64 &sb)
+{
+ if (S_ISREG(sb.st_mode)) return stat_regular;
+ if (S_ISDIR(sb.st_mode)) return stat_directory;
+ if (S_ISBLK(sb.st_mode)) return stat_block;
+ if (S_ISCHR(sb.st_mode)) return stat_character;
+ if (S_ISFIFO(sb.st_mode)) return stat_pipe;
+
+#ifdef S_ISSOCK
+ if (S_ISSOCK(sb.st_mode)) return stat_socket; // not present on WIN32
+#endif
+
+#ifdef S_ISLNK
+ if (S_ISLNK(sb.st_mode)) return stat_symlink; // not present on WIN32
+#endif
+
+#ifdef S_ISDOOR
+ // Solaris doors are an inter-process communications facility present in Solaris 2.6
+ // http://en.wikipedia.org/wiki/Doors_(computing)
+ if (S_ISDOOR(sb.st_mode)) return stat_door;
+#endif
+ return stat_unknown;
+}
+
+/**
+ * stat a file and return the appropriate object
+ * This would better be done on an open file handle
+ */
+int file_metadata_t::stat(const tstring &fn,
+ file_metadata_t *m,
+ class display &ocb)
+{
+ struct __stat64 sb;
+ if (::TSTAT(fn.c_str(),&sb))
+ {
+ ocb.error_filename(fn,"%s",strerror(errno));
+ return -1;
+ }
+ m->fileid.dev = sb.st_dev;
+#ifdef _WIN32
+ BY_HANDLE_FILE_INFORMATION fileinfo;
+ HANDLE filehandle = CreateFile(fn.c_str(),
+ 0, // desired access
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ (FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS),
+ NULL);
+ // RBF - Error check CreateFile
+ (void)GetFileInformationByHandle(filehandle, &fileinfo);
+ CloseHandle(filehandle);
+ m->fileid.ino = (((uint64_t)fileinfo.nFileIndexHigh)<<32) | (fileinfo.nFileIndexLow);
+#else
+ m->fileid.ino = sb.st_ino;
+#endif
+ m->nlink = sb.st_nlink;
+ m->size = sb.st_size;
+ m->ctime = sb.st_ctime;
+ m->mtime = sb.st_mtime;
+ m->atime = sb.st_atime;
+
+ return 0;
+}
+
+
+/* Return the 'decoded' file type of a file.
+ * If an error is found and ocb is provided, send the error to ocb.
+ * If filesize and ctime are provided, give them.
+ * Also return the file size and modification time (may be used elsewhere).
+ */
+
+file_types state::file_type(const tstring &fn,display *ocb,uint64_t *filesize,
+ timestamp_t *ctime,timestamp_t *mtime,timestamp_t *atime)
+{
+ struct __stat64 sb;
+ memset(&sb,0,sizeof(sb));
+ if (TLSTAT(fn.c_str(),&sb)) {
+ if(ocb) ocb->error_filename(fn,"%s", strerror(errno));
+ return stat_unknown;
+ }
+ if(ctime) *ctime = sb.st_ctime;
+ if(mtime) *mtime = sb.st_mtime;
+ if(atime) *atime = sb.st_atime;
+ if(filesize){
+ if(sb.st_size!=0){
+ *filesize = sb.st_size;
+ } else {
+ /*
+ * The stat() function does not return file size for raw devices.
+ * If we have no file size, try to use the find_file_size function,
+ * which calls ioctl.
+ */
+ FILE *f = _tfopen(fn.c_str(),_TEXT("rb"));
+ if(f){
+ *filesize = find_file_size(f,ocb);
+ fclose(f); f = 0;
+ }
+ }
+ }
+ return file_metadata_t::decode_file_type(sb);
+}
+
+
+
/****************************************************************
*** database of directories we've seen.
*** originally in cycles.c.
@@ -28,7 +156,6 @@
****************************************************************/
-
void state::done_processing_dir(const tstring &fn_)
{
tstring fn = global::get_realpath(fn_);
@@ -330,12 +457,6 @@ void state::clean_name_posix(std::string &fn)
}
#endif
-// Returns TRUE if the directory is '.' or '..', otherwise FALSE
-static bool is_special_dir(const tstring &d)
-{
- return global::make_utf8(d)=="." || global::make_utf8(d)=="..";
-}
-
void state::process_dir(const tstring &fn)
{
_TDIR *current_dir;
@@ -360,8 +481,7 @@ void state::process_dir(const tstring &fn)
* 4. Process them.
*/
std::vector<tstring> dir_entries;
- while ((entry = _treaddir(current_dir)) != NULL)
- {
+ while ((entry = _treaddir(current_dir)) != NULL) {
// ignore . and ..
if (is_special_dir(entry->d_name))
continue;
@@ -397,89 +517,6 @@ void state::process_dir(const tstring &fn)
}
-/* Determine the file type of a structure
- * called by file_type() and should_hash_symlink()
- */
-
-state::file_types state::decode_file_type(const struct __stat64 &sb)
-{
- if (S_ISREG(sb.st_mode)) return stat_regular;
- if (S_ISDIR(sb.st_mode)) return stat_directory;
- if (S_ISBLK(sb.st_mode)) return stat_block;
- if (S_ISCHR(sb.st_mode)) return stat_character;
- if (S_ISFIFO(sb.st_mode)) return stat_pipe;
-
-#ifdef S_ISSOCK
- if (S_ISSOCK(sb.st_mode)) return stat_socket; // not present on WIN32
-#endif
-
-#ifdef S_ISLNK
- if (S_ISLNK(sb.st_mode)) return stat_symlink; // not present on WIN32
-#endif
-
-#ifdef S_ISDOOR
- // Solaris doors are an inter-process communications facility present in Solaris 2.6
- // http://en.wikipedia.org/wiki/Doors_(computing)
- if (S_ISDOOR(sb.st_mode)) return stat_door;
-#endif
- return stat_unknown;
-}
-
-// Use a stat function to look up while kind of file this is
-// and determine its size if possible
-#ifdef _WIN32
-#define TSTAT(path,buf) _wstat64(path,buf)
-#define TLSTAT(path,buf) _wstat64(path,buf) // no lstat on windows
-#else
-#define TSTAT(path,buf) stat(path,buf)
-#define TLSTAT(path,buf) lstat(path,buf)
-#endif
-
-/* This is coming... */
-#if 0
-HFILE filehandle;
-(void)GetFileInformationByHandle((HANDLE)filehandle, &fileinfo);
-file->fileindexhi = fileinfo.nFileIndexHigh;
-file->fileindexlo = fileinfo.nFileIndexLow;
-#endif
-
-/* Return the 'decoded' file type of a file.
- * If an error is found and ocb is provided, send the error to ocb.
- * If filesize and ctime are provided, give them.
- * Also return the file size and modification time (may be used elsewhere).
- */
-state::file_types state::file_type(const tstring &fn,display *ocb,uint64_t *filesize,
- timestamp_t *ctime,timestamp_t *mtime,timestamp_t *atime)
-{
- struct __stat64 sb;
- memset(&sb,0,sizeof(sb));
- if (TLSTAT(fn.c_str(),&sb)) {
- if(ocb) ocb->error_filename(fn,"%s", strerror(errno));
- return stat_unknown;
- }
- if(ctime) *ctime = sb.st_ctime;
- if(mtime) *mtime = sb.st_mtime;
- if(atime) *atime = sb.st_atime;
- if(filesize){
- if(sb.st_size!=0){
- *filesize = sb.st_size;
- } else {
- /*
- * The stat() function does not return file size for raw devices.
- * If we have no file size, try to use the find_file_size function,
- * which calls ioctl.
- */
- FILE *f = _tfopen(fn.c_str(),_TEXT("rb"));
- if(f){
- *filesize = find_file_size(f,ocb);
- fclose(f); f = 0;
- }
- }
- }
- return decode_file_type(sb);
-}
-
-
/* Deterine if a symlink should be hashed or not.
* Returns TRUE if a symlink should be hashed.
*/
@@ -498,7 +535,7 @@ bool state::should_hash_symlink(const tstring &fn, file_types *link_type)
return false;
}
- state::file_types type = decode_file_type(sb);
+ file_types type = file_metadata_t::decode_file_type(sb);
if (type == stat_directory) {
if (mode_recursive){
@@ -526,8 +563,7 @@ bool state::should_hash_winpe(const tstring &fn)
bool executable_extension = has_executable_extension(fn);
FILE * handle = _tfopen(fn.c_str(),_TEXT("rb"));
- if (NULL == handle)
- {
+ if (NULL == handle) {
ocb.error_filename(fn,"%s", strerror(errno));
return false;
}
@@ -552,66 +588,62 @@ bool state::should_hash_winpe(const tstring &fn)
*/
bool state::should_hash_expert(const tstring &fn, file_types type)
{
- file_types link_type=stat_unknown;
- if (stat_directory == type)
- {
- if (mode_recursive)
- process_dir(fn);
- else
- ocb.error_filename(fn,"Is a directory");
-
- return false;
- }
+ file_types link_type=stat_unknown;
+ if (stat_directory == type) {
+ if (mode_recursive){
+ process_dir(fn);
+ }
+ else {
+ ocb.error_filename(fn,"Is a directory");
+ }
+ return false;
+ }
- if (mode_winpe)
- {
- // The user could have requested PE files *and* something else
- // therefore we don't return false here if the file is not a PE.
- // Note that we have to check for directories first!
- if (should_hash_winpe(fn))
- return true;
- }
+ if (mode_winpe) {
+ // The user could have requested PE files *and* something else
+ // therefore we don't return false here if the file is not a PE.
+ // Note that we have to check for directories first!
+ if (should_hash_winpe(fn)){
+ return true;
+ }
+ }
- switch(type)
- {
- // We can't just return s->mode & mode_X because mode_X is
- // a 64-bit value. When that value gets converted back to int,
- // the high part of it is lost.
-
+ switch(type) {
+ // We can't just return s->mode & mode_X because mode_X is
+ // a 64-bit value. When that value gets converted back to int,
+ // the high part of it is lost.
+
#define RETURN_IF_MODE(A) if (A) return true; break;
- case stat_directory:
- // This case should be handled above. This statement is
- // here to avoid compiler warnings
- ocb.internal_error("Did not handle directory entry in should_hash_expert()");
-
- case stat_regular: RETURN_IF_MODE(mode_regular);
- case stat_block: RETURN_IF_MODE(mode_block);
- case stat_character: RETURN_IF_MODE(mode_character);
- case stat_pipe: RETURN_IF_MODE(mode_pipe);
- case stat_socket: RETURN_IF_MODE(mode_socket);
- case stat_door: RETURN_IF_MODE(mode_door);
- case stat_symlink:
-
- // Although it might appear that we need nothing more than
- // return (s->mode & mode_symlink);
- // that doesn't work. That logic gets into trouble when we're
- // running in recursive mode on a symlink to a directory.
- // The program attempts to open the directory entry itself
- // and gets into an infinite loop.
-
- if (!(mode_symlink))
- return false;
- if (should_hash_symlink(fn,&link_type))
- {
- return should_hash_expert(fn,link_type);
+ case stat_directory:
+ // This case should be handled above. This statement is
+ // here to avoid compiler warnings
+ ocb.internal_error("Did not handle directory entry in should_hash_expert()");
+
+ case stat_regular: RETURN_IF_MODE(mode_regular);
+ case stat_block: RETURN_IF_MODE(mode_block);
+ case stat_character: RETURN_IF_MODE(mode_character);
+ case stat_pipe: RETURN_IF_MODE(mode_pipe);
+ case stat_socket: RETURN_IF_MODE(mode_socket);
+ case stat_door: RETURN_IF_MODE(mode_door);
+ case stat_symlink:
+
+ // Although it might appear that we need nothing more than
+ // return (s->mode & mode_symlink);
+ // that doesn't work. That logic gets into trouble when we're
+ // running in recursive mode on a symlink to a directory.
+ // The program attempts to open the directory entry itself
+ // and gets into an infinite loop.
+
+ if (!(mode_symlink)) return false;
+ if (should_hash_symlink(fn,&link_type)) {
+ return should_hash_expert(fn,link_type);
+ }
+ return false;
+ case stat_unknown:
+ ocb.error_filename(fn,"unknown file type");
+ return false;
}
return false;
- case stat_unknown:
- ocb.error_filename(fn,"unknown file type");
- return false;
- }
-
- return false;
}
@@ -648,20 +680,22 @@ bool state::should_hash(const tstring &fn)
return true;
}
-/* Search through a directory and its subdirectory for files to hash */
+// Search through a directory and its subdirectory for files to hash
void state::dig_normal(const tstring &fn_)
{
- tstring fn(fn_); // local copy will be modified
- if (opt_debug) ocb.status("*** state::dig_normal(%s)",global::make_utf8(fn).c_str());
+ // local copy will be modified
+ tstring fn(fn_);
+ if (opt_debug)
+ ocb.status("*** state::dig_normal(%s)",global::make_utf8(fn).c_str());
#ifdef _WIN32
- clean_name_win32(fn);
+ clean_name_win32(fn);
#else
- clean_name_posix(fn);
+ clean_name_posix(fn);
#endif
- if (opt_debug) ocb.status("*** cleaned:%s",global::make_utf8(fn).c_str());
- if (should_hash(fn)){
- ocb.hash_file(fn);
- }
+ if (opt_debug)
+ ocb.status("*** cleaned:%s",global::make_utf8(fn).c_str());
+ if (should_hash(fn))
+ ocb.hash_file(fn);
}
diff --git a/src/display.cpp b/src/display.cpp
index 28a3192..f0bc76a 100644
--- a/src/display.cpp
+++ b/src/display.cpp
@@ -2,7 +2,7 @@
#include "utf8.h"
#include <stdarg.h>
-// $Id: display.cpp 618 2012-02-10 12:12:38Z jessekornblum $
+// $Id: display.cpp 632 2012-06-05 11:00:58Z jessekornblum $
/**
*
@@ -47,37 +47,39 @@ void display::writeln(std::ostream *os,const std::string &str)
unlock();
}
-#if defined(HAVE_VASPRINTF) && defined(__MINGW_H)
-/* prototype missing under mingw */
+/* special handling for vasprintf under mingw.
+ * Sometimes the function prototype is missing. Sometimes the entire function is missing!
+ */
+#if defined(HAVE_VASPRINTF) && defined(MINGW)
extern "C" {
int vasprintf(char **ret,const char *fmt,va_list ap);
}
#endif
-
/*
- * on mingw the have_vasprintf check succedes, but it really isn't there
+ * If we don't have vasprintf, bring it in.
*/
-#if defined(HAVE_VASPRINTF) && defined(__MINGW_H)
+/*
+#if !defined(HAVE_VASPRINTF)
extern "C" {
- /**
- * We do not have vasprintf.
- * We have determined that vsnprintf() does not perform properly on windows.
- * So we just allocate a huge buffer and then strdup() and hope!
- */
+ //
+ // We do not have vasprintf.
+ // We have determined that vsnprintf() does not perform properly on windows.
+ // So we just allocate a huge buffer and then strdup() and hope!
+ //
int vasprintf(char **ret,const char *fmt,va_list ap)
{
- /* Figure out how long the result will be */
+ // Figure out how long the result will be
char buf[65536];
int size = vsnprintf(buf,sizeof(buf),fmt,ap);
if(size<0) return size;
- /* Now allocate the memory */
+ // Now allocate the memory
*ret = (char *)strdup(buf);
return size;
}
}
#endif
-
+*/
void display::status(const char *fmt,...)
{
diff --git a/src/hash.cpp b/src/hash.cpp
index e78dad4..f62dc96 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -8,7 +8,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: hash.cpp 595 2012-01-22 00:28:03Z xchatty $
+ * $Id: hash.cpp 627 2012-02-28 04:31:29Z xchatty $
*
* 2011 JUN 1 - SLG - Removed #ifdef MD5DEEP, since we now have a single binary for both MD5DEEP and HASHDEEP
*/
@@ -195,6 +195,7 @@ bool file_data_hasher_t::compute_hash(uint64_t request_start,uint64_t request_le
#define O_BINARY 0
#endif
mutex_t file_data_hasher_t::fdh_lock;
+
void file_data_hasher_t::hash()
{
file_data_hasher_t *fdht = this;
@@ -206,8 +207,14 @@ void file_data_hasher_t::hash()
if(fdht->handle==0){
/* Open the file and print an error if we can't */
// stat the file to get the bytes and ctime
- state::file_type(fdht->file_name_to_hash,ocb,&fdht->stat_bytes,
- &fdht->ctime,&fdht->mtime,&fdht->atime);
+ //state::file_type(fdht->file_name_to_hash,ocb,&fdht->stat_bytes,
+ //&fdht->ctime,&fdht->mtime,&fdht->atime);
+ file_metadata_t m;
+ file_metadata_t::stat(fdht->file_name_to_hash,&m,*ocb);
+ fdht->stat_bytes = m.size;
+ fdht->ctime = m.ctime;
+ fdht->mtime = m.mtime;
+ fdht->atime = m.atime;
if(ocb->opt_verbose>=MORE_VERBOSE){
errno = 0; // no error
@@ -404,7 +411,6 @@ void file_data_hasher_t::hash()
}
}
-
/**
* If we had an additional hash context for the file,
* then we must be in DFXML mode and doing piecewise hashing.
diff --git a/src/hashlist.cpp b/src/hashlist.cpp
index 5cbb542..3fc2fc6 100644
--- a/src/hashlist.cpp
+++ b/src/hashlist.cpp
@@ -1,4 +1,4 @@
-// $Id: hashlist.cpp 578 2012-01-06 12:25:14Z jessekornblum $
+// $Id: hashlist.cpp 631 2012-06-05 10:26:56Z jessekornblum $
/** hashlist.cpp
* Implements a list of hashes for local database, searching, etc.
@@ -218,7 +218,12 @@ void hashlist::enable_hashing_algorithms_from_hashdeep_file(class display *ocb,c
for(std::vector<std::string>::iterator it = algs.begin(); it!=algs.end(); it++){
std::string name = *it;
lowercase(name);
- if(name=="filename") continue;
+ if(name=="filename")
+ {
+ // Special value to denote the filename
+ filename_column = num_columns;
+ continue;
+ }
hashid_t id = algorithm_t::get_hashid_for_name(name);
if(id==alg_unknown){
if(ocb){
@@ -256,101 +261,128 @@ uint64_t hashlist::total_matched()
}
-/**
- * Loads a file of known hashes.
- * First identifies the file type, then reads the file.
- */
-hashlist::loadstatus_t hashlist::load_hash_file(display *ocb,const std::string &fn)
+//
+// Loads a file of known hashes.
+// First identifies the file type, then reads the file.
+ //
+hashlist::loadstatus_t
+hashlist::load_hash_file(display *ocb,const std::string &fn)
{
- loadstatus_t status = loadstatus_ok;
- hashfile_format type;
+ loadstatus_t status = loadstatus_ok;
+ hashfile_format type;
- FILE *hl_handle = fopen(fn.c_str(),"rb");
- if (NULL == hl_handle) {
- if(ocb) ocb->error("%s: %s", fn.c_str(), strerror(errno));
- return status_file_error;
- }
+ FILE *hl_handle = fopen(fn.c_str(),"rb");
+ if (NULL == hl_handle)
+ {
+ if (ocb)
+ ocb->error("%s: %s", fn.c_str(), strerror(errno));
+ return status_file_error;
+ }
- type = identify_format(ocb,fn,hl_handle);
- if (file_unknown == type) {
- if(ocb) ocb->error("%s: Unable to identify file format", fn.c_str());
- fclose(hl_handle);
- hl_handle = 0;
- return status_unknown_filetype;
- }
+ type = identify_format(ocb,fn,hl_handle);
+ if (file_unknown == type)
+ {
+ if (ocb)
+ ocb->error("%s: Unable to identify file format", fn.c_str());
+ fclose(hl_handle);
+ hl_handle = 0;
+ return status_unknown_filetype;
+ }
- int contains_bad_lines = FALSE;
- int record_valid=0;
+ bool contains_bad_lines = false;
+ bool record_valid;
- // We start our counter at line number two for the two lines
- // of header we've already read
- uint64_t line_number = 2;
+ // We start our counter at line number two for the two lines
+ // of header we've already read
+ uint64_t line_number = 2;
- /* Redo this to use std::string everywhere */
- char line[MAX_STRING_LENGTH]; // holds the line we are reading
+ // TODO: Read the line directly into a std::string
+ char line[MAX_STRING_LENGTH];
+ while (fgets(line,MAX_STRING_LENGTH,hl_handle))
+ {
+ line_number++;
+
+ // Lines starting with a pound sign are comments and can be ignored
+ if ('#' == line[0])
+ continue;
- while (fgets(line,MAX_STRING_LENGTH,hl_handle)) {
- line_number++; // count where we are
+ // C++ typically fails with a bad_alloc, but you can make it return null
+ // http://www.cplusplus.com/reference/std/new/bad_alloc/
+ // http://www.cplusplus.com/reference/std/new/nothrow/
+ file_data_t *t = new (std::nothrow) file_data_t();
+ if (NULL == t)
+ {
+ ocb->fatal_error("%s: Out of memory in line %"PRIu64,
+ fn.c_str(), line_number);
+ }
+
+ chop_line(line);
+ record_valid = true;
- // Lines starting with a pound sign are comments and can be ignored
- if ('#' == line[0]){
- continue;
- }
+ // Convert the input line to a string for easier manipulations
+ std::string line_as_string(line);
+ std::vector<std::string> fields = split(line_as_string,',');
- // C++ typically fails with a bad_alloc, but you can make it return null
- // http://www.cplusplus.com/reference/std/new/bad_alloc/
- // http://www.cplusplus.com/reference/std/new/nothrow/
- file_data_t *t = new (std::nothrow) file_data_t(); // C++ new fails with a bad_a
- if (NULL == t){
- ocb->fatal_error("%s: Out of memory in line %"PRIu64,
- fn.c_str(), line_number);
- }
-
- chop_line(line);
- record_valid = TRUE;
-
- // completely rewritten to use STL strings
- std::vector<std::string> fields = split(std::string(line),',');
- for(size_t column_number=0;column_number<fields.size();column_number++){
- // The first column should always be the file size
- std::string word = fields[column_number];
- if (column_number==0) {
- t->file_bytes = (uint64_t)strtoll(word.c_str(),NULL,10);
- continue;
- }
- if (column_number==fields.size()-1){
- t->file_name = word;
- continue;
- }
+ size_t column_number;
+ for (column_number=0 ; column_number<fields.size() ; column_number++)
+ {
+ std::string word = fields[column_number];
+ // The first column should always be the file size
+ if (0 == column_number)
+ {
+ t->file_bytes = (uint64_t)strtoll(word.c_str(),NULL,10);
+ continue;
+ }
- // All other columns should contain a valid hash in hex
- if ( !algorithm_t::valid_hash(hash_column[column_number],word)){
- if(ocb) ocb->error("%s: Invalid %s hash in line %"PRIu64,fn.c_str(),
- hashes[hash_column[column_number]].name.c_str(),
- line_number);
- contains_bad_lines = TRUE;
- record_valid = FALSE;
- // Break out (done = true) and then process the next line
- break;
- }
+ if (column_number == filename_column)
+ {
+ // If the filename contained commas, it was split
+ // incorrectly by the 'split' statememt above. The filename
+ // will be split across more than one column.
+ // As such we need to 'find' everything
+ // in the string starting with the current location.
+ // The result should be closer to the end of the string than
+ // the start, so we can use rfind. (This also avoids a problem
+ // when the filename is the same as one of the hashes, which
+ // happens now and again.)
+ size_t start = line_as_string.rfind(word);
+ t->file_name = line_as_string.substr(start,std::string::npos);
+
+ // This should be the last column, so we break out now.
+ break;
+ }
- // Convert the hash to a std::string and save it
- lowercase(word);
- t->hash_hex[hash_column[column_number]] = word;
- }
- if ( record_valid) {
- add_fdt(t); /* add the file to the database*/
- }
+ // All other columns should contain a valid hash in hex
+ if ( !algorithm_t::valid_hash(hash_column[column_number],word))
+ {
+ if (ocb)
+ ocb->error("%s: Invalid %s hash in line %"PRIu64,
+ fn.c_str(),
+ hashes[hash_column[column_number]].name.c_str(),
+ line_number);
+ contains_bad_lines = true;
+ record_valid = false;
+ // Break out (done = true) and then process the next line
+ break;
+ }
+
+ // Convert the hash to a std::string and save it
+ lowercase(word);
+ t->hash_hex[hash_column[column_number]] = word;
}
- fclose(hl_handle);
- hl_handle = 0;
- if (contains_bad_lines){
- return status_contains_bad_hashes;
- }
+ if (record_valid)
+ add_fdt(t);
+ }
+
+ fclose(hl_handle);
+ hl_handle = 0;
+
+ if (contains_bad_lines)
+ return status_contains_bad_hashes;
- return status;
+ return status;
}
diff --git a/src/main.cpp b/src/main.cpp
index 7697c13..eb4897c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,6 +1,6 @@
/*
*
- * $Id: main.cpp 618 2012-02-10 12:12:38Z jessekornblum $
+ * $Id: main.cpp 626 2012-02-28 02:50:32Z jessekornblum $
*
* This is the main() function and support functions for hashdeep and md5deep.
*
@@ -130,65 +130,72 @@ tstring state::generate_filename(const tstring &input)
// function should produce no more than 22 lines of text.
void state::usage()
{
- if(usage_count==1){
- ocb.status("%s version %s by %s.",progname.c_str(),VERSION,AUTHOR);
- ocb.status("%s %s [-c <alg>] [-k <file>] [-amxwMXrespblvv] [-jnn] [-V|-h] [-o <mode>] [FILES]",
- CMD_PROMPT,progname.c_str());
-
- /* Make a list of the hashes */
- ocb.status("-c <alg1,[alg2]> - Compute hashes only. Defaults are MD5 and SHA-256");
- fprintf(stdout," legal values: ");
- for (int i = 0 ; i < NUM_ALGORITHMS ; i++){
- fprintf(stdout,"%s%s",hashes[i].name.c_str(),(i+1<NUM_ALGORITHMS) ? "," : NEWLINE);
- }
+ if (1 == usage_count)
+ {
+ ocb.status("%s version %s by %s.",progname.c_str(),VERSION,AUTHOR);
+ ocb.status("%s %s [OPTION]... [FILES]...",CMD_PROMPT,progname.c_str());
+
+ // Make a list of the hashes
+ ocb.status("-c <alg1,[alg2]> - Compute hashes only. Defaults are MD5 and SHA-256");
+ fprintf(stdout," legal values: ");
+ for (int i = 0 ; i < NUM_ALGORITHMS ; i++)
+ {
+ fprintf(stdout,"%s%s",hashes[i].name.c_str(),(i+1<NUM_ALGORITHMS) ? "," : NEWLINE);
+ }
- ocb.status("-p <size> - piecewise mode. Files are broken into blocks for hashing");
- ocb.status("-r - recursive mode. All subdirectories are traversed");
- ocb.status("-d - output in DFXML (Digital Forensics XML)");
- ocb.status("-k <FN> - add a file of known hashes");
- ocb.status("-a - audit mode. Validates FILES against known hashes. Requires -k");
- ocb.status("-m - matching mode. Requires -k");
- ocb.status("-x - negative matching mode. Requires -k");
- ocb.status("-w - in -m mode, displays which known file was matched");
- ocb.status("-M and -X act like -m and -x, but display hashes of matching files");
- ocb.status("-e - compute estimated time remaining for each file");
- ocb.status("-s - silent mode. Suppress all error messages");
- ocb.status("-b - prints only the bare name of files; all path information is omitted");
- ocb.status("-l - print relative paths for filenames");
- ocb.status("-i - only process files smaller than the given threshold");
- ocb.status("-o - only process certain types of files. See README/manpage");
- ocb.status("-v - verbose mode. Use again to be more verbose; -V display version & exit.");
- ocb.status("-d - output in DFXML; -W FILE - write to FILE.");
+ ocb.status("-p <size> - piecewise mode. Files are broken into blocks for hashing");
+ ocb.status("-r - recursive mode. All subdirectories are traversed");
+ ocb.status("-d - output in DFXML (Digital Forensics XML)");
+ ocb.status("-k <file> - add a file of known hashes");
+ ocb.status("-a - audit mode. Validates FILES against known hashes. Requires -k");
+ ocb.status("-m - matching mode. Requires -k");
+ ocb.status("-x - negative matching mode. Requires -k");
+ ocb.status("-w - in -m mode, displays which known file was matched");
+ ocb.status("-M and -X act like -m and -x, but display hashes of matching files");
+ ocb.status("-e - compute estimated time remaining for each file");
+ ocb.status("-s - silent mode. Suppress all error messages");
+ ocb.status("-b - prints only the bare name of files; all path information is omitted");
+ ocb.status("-l - print relative paths for filenames");
+ ocb.status("-i - only process files smaller than the given threshold");
+ ocb.status("-o - only process certain types of files. See README/manpage");
+ ocb.status("-v - verbose mode. Use again to be more verbose");
+ ocb.status("-d - output in DFXML; -W FILE - write to FILE.");
#ifdef HAVE_PTHREAD
- ocb.status("-jnn run nn threads (default %d)",threadpool::numCPU());
+ ocb.status("-j <num> - use num threads (default %d)",threadpool::numCPU());
#else
- ocb.status("-jnn ignored (compiled without pthreads)");
+ ocb.status("-j <num> - ignored (compiled without pthreads)");
#endif
+ }
- }
- if(usage_count==2){ // -hh
- ocb.status("-0 - use a NULL for newline.");
- ocb.status("-u - escape Unicode");
- ocb.status("-B - verbose mode; repeat for more verbosity");
- ocb.status("-C - Macintosh only --- use Common Crypto hash functions");
- ocb.status("-Fb - I/O mode buffered; -Fu unbuffered; -Fm memory-mapped");
- ocb.status("-o[bcpflsde] - only process certain types of files:");
- ocb.status(" b=block dev; c=character dev; p=named pipe");
- ocb.status(" f=regular file; l=symlink; s=socket; d=door e=Windows PE");
- ocb.status("-Dnn - set debug level to nn");
- }
- if(usage_count==3){ // -hhh - adds debugging information
- ocb.status("sizeof(off_t)= %d",sizeof(off_t));
+ // -hh makes us more verbose
+ if (2 == usage_count)
+ {
+ ocb.status("-V - display version number and exit");
+ ocb.status("-0 - use a NUL (\\0) for newline.");
+ ocb.status("-u - escape Unicode");
+ ocb.status("-B - verbose mode; repeat for more verbosity");
+ ocb.status("-C - OS X only --- use Common Crypto hash functions");
+ ocb.status("-Fb - I/O mode buffered; -Fu unbuffered; -Fm memory-mapped");
+ ocb.status("-o[bcpflsde] - Expert mode. only process certain types of files:");
+ ocb.status(" b=block dev; c=character dev; p=named pipe");
+ ocb.status(" f=regular file; l=symlink; s=socket; d=door e=Windows PE");
+ ocb.status("-D <num> - set debug level");
+ }
+
+ /// -hhh mode includes debugging information.
+ if (3 == usage_count)
+ {
+ ocb.status("sizeof(off_t)= %d",sizeof(off_t));
#ifdef HAVE_PTHREAD
- ocb.status("HAVE_PTHREAD");
+ ocb.status("HAVE_PTHREAD");
#endif
#ifdef HAVE_PTHREAD_H
- ocb.status("HAVE_PTHREAD_H");
+ ocb.status("HAVE_PTHREAD_H");
#endif
#ifdef HAVE_PTHREAD_WIN32_PROCESS_ATTACH_NP
- ocb.status("HAVE_PTHREAD_WIN32_PROCESS_ATTACH_NP");
+ ocb.status("HAVE_PTHREAD_WIN32_PROCESS_ATTACH_NP");
#endif
- }
+ }
}
@@ -198,45 +205,45 @@ void state::md5deep_usage(void)
{
if(usage_count==1){
ocb.status("%s version %s by %s.",progname.c_str(),VERSION,AUTHOR);
- ocb.status("%s %s [OPTION]... [FILE]...",CMD_PROMPT,progname.c_str());
+ ocb.status("%s %s [OPTION]... [FILES]...",CMD_PROMPT,progname.c_str());
ocb.status("See the man page or README.txt file or use -hh for the full list of options");
ocb.status("-p <size> - piecewise mode. Files are broken into blocks for hashing");
- ocb.status("-r - recursive mode. All subdirectories are traversed");
- ocb.status("-e - show estimated time remaining for each file");
- ocb.status("-s - silent mode. Suppress all error messages");
- ocb.status("-z - display file size before hash");
+ ocb.status("-r - recursive mode. All subdirectories are traversed");
+ ocb.status("-e - show estimated time remaining for each file");
+ ocb.status("-s - silent mode. Suppress all error messages");
+ ocb.status("-z - display file size before hash");
ocb.status("-m <file> - enables matching mode. See README/man page");
ocb.status("-x <file> - enables negative matching mode. See README/man page");
ocb.status("-M and -X are the same as -m and -x but also print hashes of each file");
- ocb.status("-w - displays which known file generated a match");
- ocb.status("-n - displays known hashes that did not match any input files");
+ ocb.status("-w - displays which known file generated a match");
+ ocb.status("-n - displays known hashes that did not match any input files");
ocb.status("-a and -A add a single hash to the positive or negative matching set");
- ocb.status("-b - prints only the bare name of files; all path information is omitted");
- ocb.status("-l - print relative paths for filenames");
- ocb.status("-t - print GMT timestamp (ctime)");
- ocb.status("-iSIZE/-ISIZE - only process files smaller/larger than SIZE");
- ocb.status("-v - display version number and exit");
- ocb.status("-d - output in DFXML; -u - Escape Unicode; -W FILE - write to FILE.");
+ ocb.status("-b - prints only the bare name of files; all path information is omitted");
+ ocb.status("-l - print relative paths for filenames");
+ ocb.status("-t - print GMT timestamp (ctime)");
+ ocb.status("-i/I <size> - only process files smaller/larger than SIZE");
+ ocb.status("-v - display version number and exit");
+ ocb.status("-d - output in DFXML; -u - Escape Unicode; -W FILE - write to FILE.");
#ifdef HAVE_PTHREAD
- ocb.status("-jnn run nn threads (default %d)",threadpool::numCPU());
+ ocb.status("-j <num> - use num threads (default %d)",threadpool::numCPU());
#else
- ocb.status("-jnn ignored (compiled without pthreads)");
+ ocb.status("-j <num> - ignored (compiled without pthreads)");
#endif
- ocb.status("-Z - traige mode; -h - help; -hh - full help");
+ ocb.status("-Z - triage mode; -h - help; -hh - full help");
}
if(usage_count==2){ // -hh
- ocb.status("-S - Silent mode, but warn on bad hashes");
- ocb.status("-0 - use a NULL for newline.");
- ocb.status("-k - print asterisk before filename");
- ocb.status("-u - escape Unicode");
- ocb.status("-B - verbose mode; repeat for more verbosity");
- ocb.status("-C - Macintosh only --- use Common Crypto hash functions");
- ocb.status("-Fb - I/O mode buffered; -Fu unbuffered; -Fm memory-mapped");
- ocb.status("-ffilename - take list of files to hash from filename");
- ocb.status("-o[bcpflsde] - only process certain types of files:");
- ocb.status(" b=block dev; c=character dev; p=named pipe");
- ocb.status(" f=regular file; l=symlink; s=socket; d=door e=Windows PE");
- ocb.status("-Dnn - set debug level to nn");
+ ocb.status("-S - Silent mode, but warn on bad hashes");
+ ocb.status("-0 - use a NUL (\\0) for newline.");
+ ocb.status("-k - print asterisk before filename");
+ ocb.status("-u - escape Unicode characters in filenames");
+ ocb.status("-B - verbose mode; repeat for more verbosity");
+ ocb.status("-C - OS X only --- use Common Crypto hash functions");
+ ocb.status("-Fb - I/O mode buffered; -Fu unbuffered; -Fm memory-mapped");
+ ocb.status("-f <file> - take list of files to hash from filename");
+ ocb.status("-o[bcpflsde] - expert mode. Only process certain types of files:");
+ ocb.status(" b=block dev; c=character dev; p=named pipe");
+ ocb.status(" f=regular file; l=symlink; s=socket; d=door e=Windows PE");
+ ocb.status("-D <num> - set debug level to nn");
}
if(usage_count==3){ // -hhh
ocb.status("sizeof(off_t)= %d",sizeof(off_t));
@@ -586,7 +593,7 @@ int state::hashdeep_process_command_line(int argc_, char **argv_)
bool did_usage = false;
int i;
- while ((i=getopt(argc_,argv_,"abBc:CdeF:f:o:I:i:MmXxtlk:rsp:wvVhW:0D:uj:")) != -1) {
+ while ((i=getopt(argc_,argv_,"abc:CdeF:f:o:I:i:MmXxtlk:rsp:wvVhW:0D:uj:")) != -1) {
switch (i) {
case 'a': ocb.primary_function = primary_audit; break;
case 'C': opt_enable_mac_cc = true; break;
@@ -628,11 +635,11 @@ int state::hashdeep_process_command_line(int argc_, char **argv_)
// TODO: Add -t mode to hashdeep
// case 't': mode |= mode_timestamp; break;
- case 'b': ocb.mode_barename=true; break;
- case 'l': ocb.opt_relative=true; break;
- case 'e': ocb.opt_estimate = true; break;
- case 'r': mode_recursive=true; break;
- case 's': ocb.opt_silent = true; break;
+ case 'b': ocb.mode_barename=true; break;
+ case 'l': ocb.opt_relative=true; break;
+ case 'e': ocb.opt_estimate = true; break;
+ case 'r': mode_recursive=true; break;
+ case 's': ocb.opt_silent = true; break;
case 'p':
ocb.piecewise_size = find_block_size(optarg);
@@ -672,12 +679,11 @@ int state::hashdeep_process_command_line(int argc_, char **argv_)
}
break;
- case 'B': /* Intentional Fall-Through */
case 'v':
- if(++ocb.opt_verbose > INSANELY_VERBOSE){
- ocb.error("User request for insane verbosity denied");
- }
- break;
+ ++ocb.opt_verbose;
+ if (ocb.opt_verbose > INSANELY_VERBOSE)
+ ocb.error("User request for insane verbosity denied");
+ break;
case 'V':
ocb.status("%s", VERSION);
@@ -975,13 +981,8 @@ int state::md5deep_process_command_line(int argc_, char **argv_)
while ((i = getopt(argc_,
argv_,
- "A:a:bBcCdeF:f:I:i:M:X:x:m:o:tnwzsSp:rhvV0lkqZW:D:uj:")) != -1) {
+ "A:a:bcCdeF:f:I:i:M:X:x:m:o:tnwzsSp:rhvV0lkqZW:D:uj:")) != -1) {
switch (i) {
- case 'B': /* Intentional Fall-Through */
- if(++ocb.opt_verbose > INSANELY_VERBOSE){
- ocb.error("User request for insane verbosity denied");
- }
- break;
case 'C': opt_enable_mac_cc = true; break;
case 'D': opt_debug = atoi(optarg); break;
case 'd': ocb.xml_open(stdout); break;
@@ -1224,6 +1225,7 @@ int state::main(int _argc,char **_argv)
#endif
#ifdef HAVE_PTHREAD
+ threadpool::win32_init(); //
ocb.opt_threadcount = threadpool::numCPU(); // be sure it's set
#endif
diff --git a/src/main.h b/src/main.h
index fd43d96..ae0360b 100644
--- a/src/main.h
+++ b/src/main.h
@@ -12,7 +12,7 @@
*
* It then creates all the C++ classes and structures used.
*
- * $Id: main.h 612 2012-02-08 15:01:56Z jessekornblum $
+ * $Id: main.h 630 2012-06-05 00:32:45Z jessekornblum $
*/
@@ -186,6 +186,54 @@ typedef time_t timestamp_t;
typedef std::string filename_t;
#endif
+/**
+ * file_metadata_t contains metadata information about a file.
+ * It also includes a stat call that returns the inode information
+ * and link count even on windows, where the API is different than stat.
+ * Note that we only include information we care about in this program
+ *
+ * this is in dig.cpp.
+ */
+
+
+/* strangely, we define our own file types */
+typedef enum {
+ stat_regular=0,
+ stat_directory,
+ stat_door,
+ stat_block,
+ stat_character,
+ stat_pipe,
+ stat_socket,
+ stat_symlink,
+ stat_unknown=254
+} file_types;
+
+class file_metadata_t {
+public:
+ static file_types decode_file_type(const struct __stat64 &sb);
+
+ // stat a file, print an error and return -1 if it fails, otherwise return 0
+ static int stat(const filename_t &path,file_metadata_t *m,class display &ocb);
+ class fileid_t { // uniquely defines a file on this system
+ public:
+ fileid_t():dev(0),ino(0){};
+ fileid_t(uint64_t dev_,uint64_t ino_):dev(dev_),ino(ino_){};
+ uint64_t dev; // device number
+ uint64_t ino; // inode number
+ };
+ file_metadata_t():fileid(),nlink(0),size(0),ctime(0),mtime(0),atime(0){};
+ file_metadata_t(fileid_t fileid_,uint64_t nlink_,uint64_t size_,timestamp_t ctime_,timestamp_t mtime_,
+ timestamp_t atime_):fileid(fileid_),nlink(nlink_),size(size_),ctime(ctime_),mtime(mtime_),atime(atime_){};
+ fileid_t fileid;
+ uint64_t nlink;
+ uint64_t size;
+ timestamp_t ctime;
+ timestamp_t mtime;
+ timestamp_t atime;
+
+};
+
/** file_data_t contains information about a file.
* It can be created by hashing an actual file, or by reading a hash file a file of hashes.
* The object is simple so that the built in C++ shallow copy will make a proper copy of it.
@@ -418,6 +466,7 @@ public:;
std::string last_enabled_algorithms; // a string with the algorithms that were enabled last
hashid_t hash_column[NUM_ALGORITHMS]; // maps a column number to a hashid;
// the order columns appear in the file being loaded.
+ uint8_t filename_column; // Column number which should contain the filename
hashfile_format identify_format(class display *ocb,const std::string &fn,FILE *handle);
loadstatus_t load_hash_file(class display *ocb,const std::string &fn); // not tstring! always ASCII
@@ -530,7 +579,7 @@ public:
opt_display_hash(false),
opt_show_matched(false),
opt_iomode(iomode::buffered), // by default, use buffered
-#ifdef HAVE_PTRHEAD
+#ifdef HAVE_PTHREAD
opt_threadcount(threadpool::numCPU()),
tp(0),
#else
@@ -734,17 +783,6 @@ inline std::ostream & operator <<(std::ostream &os,const std::wstring &wstr) {
class state {
public:;
- typedef enum {
- stat_regular=0,
- stat_directory,
- stat_door,
- stat_block,
- stat_character,
- stat_pipe,
- stat_socket,
- stat_symlink,
- stat_unknown=254
- } file_types;
state():mode_recursive(false), // do we recurse?
mode_warn_only(false), // for loading hash files
@@ -863,7 +901,6 @@ public:;
* If an error is found and ocb is provided, send the error to ocb.
* If filesize and timestamp are provided, give them.
*/
- static file_types decode_file_type(const struct __stat64 &sb);
static file_types file_type(const filename_t &fn,class display *ocb,uint64_t *filesize,
timestamp_t *ctime,timestamp_t *mtime,timestamp_t *atime);
#ifdef _WIN32
diff --git a/src/threadpool.cpp b/src/threadpool.cpp
index aa344c2..bf40bcd 100644
--- a/src/threadpool.cpp
+++ b/src/threadpool.cpp
@@ -2,7 +2,7 @@
*** THREADING SUPPORT
****************************************************************/
-// $Id: threadpool.cpp 618 2012-02-10 12:12:38Z jessekornblum $
+// $Id: threadpool.cpp 623 2012-02-26 13:56:12Z xchatty $
#include "main.h"
@@ -95,6 +95,20 @@ void ERR(int val,const char *msg)
}
+/* Run non-portable pthread win32 startup */
+void threadpool::win32_init()
+{
+#ifdef WIN32
+ static bool initialized = false;
+ if(initialized==false){
+ pthread_win32_process_attach_np();
+ pthread_win32_thread_attach_np();
+ initialized=true;
+ }
+#endif
+}
+
+
/**
* Create the thread pool.
* Each thread has its own feature_recorder_set.
@@ -115,12 +129,6 @@ void ERR(int val,const char *msg)
threadpool::threadpool(int numworkers_)
{
-#ifdef WIN32
- /* Run non-portable pthread win32 startup */
- pthread_win32_process_attach_np();
- pthread_win32_thread_attach_np();
-#endif
-
numworkers = numworkers_;
freethreads = numworkers;
if(pthread_cond_init(&TOMAIN,NULL)) ERR(1,"pthread_cond_init #1 failed");
diff --git a/src/threadpool.h b/src/threadpool.h
index 393b3fa..3966e2d 100644
--- a/src/threadpool.h
+++ b/src/threadpool.h
@@ -47,6 +47,7 @@ public:
class threadpool: public std::vector<class worker *> {
public:
+ static void win32_init(); // must be called under win32 to initialize posix threads
mutex_t M; // protects the following variables
volatile unsigned int numworkers;
volatile unsigned int freethreads;
diff --git a/src/tiger.c b/src/tiger.c
index 3c96028..2d3a181 100644
--- a/src/tiger.c
+++ b/src/tiger.c
@@ -1,77 +1,55 @@
-
-/* MD5DEEP - tiger.c
+/* tiger.c - The TIGER hash function
+ * Copyright (C) 1998, 2001, 2002, 2003, 2010 Free Software Foundation, Inc.
*
- * This code was adapted from GnuPG and is licensed under 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.
- * Please see COPYING for the license regarding this file
+ * This file is part of Libgcrypt.
*
- * Some functions have been changed or removed from the GnuPG version.
- * See comments for details.
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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.
+ * Libgcrypt 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 Lesser General Public License for more details.
*
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
-/* $Id: tiger.c 501 2011-09-25 17:12:27Z xchatty $ */
+/* See http://www.cs.technion.ac.il/~biham/Reports/Tiger/ */
-//#include "main.h"
+#include "common.h"
#include "tiger.h"
-
-/* Test vectors from the NESSIE Project:
- Note that the original version of this code included test vectors
- in big endian format. These test vectors are in little endian format.
- More of them are available at
- http://www.cs.technion.ac.il/~biham/Reports/Tiger/test-vectors-nessie-format.dat
-
- message="" (empty string)
- hash=3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3
-
- message="a"
- hash=77BEFBEF2E7EF8AB2EC8F93BF587A7FC613E247F5F247809
-
- message="abc"
- hash=2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93
-
- message="message digest"
- hash=D981F8CB78201A950DCF3048751E441C517FCA1AA55A29F6
-
- message="abcdefghijklmnopqrstuvwxyz"
- hash=1714A472EEE57D30040412BFCC55032A0B11602FF37BEEE9
-
- message="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- hash=0F7BF9A19B9C58F2B7610DF7E84F0AC3A71C631E7B53F78E
-
- message="A...Za...z0...9"
- hash=8DCEA680A17583EE502BA38A3C368651890FFBCCDC49A8CC
-
- message=8 times "1234567890"
- hash=1C14795529FD9F207A958F84C52F11E887FA0CABDFD91BFD
-
- message=1 million times "a"
- hash=6DB0E2729CBEAD93D715C6A7D36302E9B3CEE0D2BC314B41
-*/
-
-
-void hash_init_tiger(void * ctx)
-{
- tiger_init((TIGER_CONTEXT *)ctx);
-}
-
-void hash_update_tiger(void * ctx, const unsigned char *buf, size_t len)
-{
- tiger_update((TIGER_CONTEXT *)ctx,buf,(size_t)len);
-}
-
-void hash_final_tiger(void * ctx, unsigned char *sum)
-{
- tiger_final(sum,(TIGER_CONTEXT *)ctx);
-}
-
-
+// Code copied from libgcrypt, version 1.5.0
+// http://directory.fsf.org/wiki/Libgcrypt
+// http://www.gnupg.org/download/#libgcrypt
+
+// Test vectors for the "Fixed" Tiger algorithm
+// Source: http://www.cs.technion.ac.il/~biham/Reports/Tiger/test-vectors-nessie-format.dat
+// Inserted by Jesse Kornblum
+//
+// Set 1, vector# 0:
+// message="" (empty string)
+// hash=3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3
+//
+// Set 1, vector# 1:
+// message="a"
+// hash=77BEFBEF2E7EF8AB2EC8F93BF587A7FC613E247F5F247809
+//
+// Set 1, vector# 2:
+// message="abc"
+// hash=2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93
+//
+// Set 1, vector# 3:
+// message="message digest"
+// hash=D981F8CB78201A950DCF3048751E441C517FCA1AA55A29F6
+//
+// Set 1, vector# 4:
+// message="abcdefghijklmnopqrstuvwxyz"
+// hash=1714A472EEE57D30040412BFCC55032A0B11602FF37BEEE9
static uint64_t sbox1[256] = {
@@ -596,72 +574,136 @@ static uint64_t sbox4[256] = {
};
-// print functions are unnessary and have been removed (jk)
+// Inserted code
+// From libgcrypt, g10lib.h
+#define wipememory2(_ptr,_set,_len) do { \
+ volatile char *_vptr=(volatile char *)(_ptr); \
+ size_t _vlen=(_len); \
+ while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
+ } while(0)
+#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
+
+void _gcry_burn_stack(int bytes);
+
+
+// Inserted code
+// From libgcrypt, misc.c
+void
+_gcry_burn_stack (int bytes)
+{
+ char buf[64];
+
+ wipememory (buf, sizeof buf);
+ bytes -= sizeof buf;
+ if (bytes > 0)
+ _gcry_burn_stack (bytes);
+}
+
+
+// libgcrypt, tiger.c
+typedef struct
+{
+ uint64_t a, b, c;
+ unsigned char buf[64];
+ int count;
+ uint32_t nblocks;
+ int variant; /* 0 = old code, 1 = fixed code, 2 - TIGER2. */
+} TIGER_CONTEXT;
+
+
+static void
+do_init (void *context, int variant)
+{
+ TIGER_CONTEXT *hd = (TIGER_CONTEXT *)context;
+
+ hd->a = 0x0123456789abcdefLL;
+ hd->b = 0xfedcba9876543210LL;
+ hd->c = 0xf096a5b4c3b2e187LL;
+ hd->nblocks = 0;
+ hd->count = 0;
+ hd->variant = variant;
+}
+
+static void
+tiger_init (void *context)
+{
+ do_init (context, 0);
+}
+
+static void
+tiger1_init (void *context)
+{
+ do_init (context, 1);
+}
+
+static void
+tiger2_init (void *context)
+{
+ do_init (context, 2);
+}
-/* I was getting compiler errors for "conflicting types for 'round'
- from including math.h, so I renamed this function tiger_round (jk) */
-static void
+static void
tiger_round( uint64_t *ra, uint64_t *rb, uint64_t *rc, uint64_t x, int mul )
{
- uint64_t a = *ra;
- uint64_t b = *rb;
- uint64_t c = *rc;
-
- c ^= x;
- a -= sbox1[ c & 0xff ] ^ sbox2[ (c >> 16) & 0xff ]
- ^ sbox3[ (c >> 32) & 0xff ] ^ sbox4[ (c >> 48) & 0xff ];
- b += sbox4[ (c >> 8) & 0xff ] ^ sbox3[ (c >> 24) & 0xff ]
- ^ sbox2[ (c >> 40) & 0xff ] ^ sbox1[ (c >> 56) & 0xff ];
- b *= mul;
-
- *ra = a;
- *rb = b;
- *rc = c;
+ uint64_t a = *ra;
+ uint64_t b = *rb;
+ uint64_t c = *rc;
+
+ c ^= x;
+ a -= ( sbox1[ c & 0xff ] ^ sbox2[ (c >> 16) & 0xff ]
+ ^ sbox3[ (c >> 32) & 0xff ] ^ sbox4[ (c >> 48) & 0xff ]);
+ b += ( sbox4[ (c >> 8) & 0xff ] ^ sbox3[ (c >> 24) & 0xff ]
+ ^ sbox2[ (c >> 40) & 0xff ] ^ sbox1[ (c >> 56) & 0xff ]);
+ b *= mul;
+
+ *ra = a;
+ *rb = b;
+ *rc = c;
}
static void
pass( uint64_t *ra, uint64_t *rb, uint64_t *rc, uint64_t *x, int mul )
{
- uint64_t a = *ra;
- uint64_t b = *rb;
- uint64_t c = *rc;
-
- tiger_round( &a, &b, &c, x[0], mul );
- tiger_round( &b, &c, &a, x[1], mul );
- tiger_round( &c, &a, &b, x[2], mul );
- tiger_round( &a, &b, &c, x[3], mul );
- tiger_round( &b, &c, &a, x[4], mul );
- tiger_round( &c, &a, &b, x[5], mul );
- tiger_round( &a, &b, &c, x[6], mul );
- tiger_round( &b, &c, &a, x[7], mul );
-
- *ra = a;
- *rb = b;
- *rc = c;
+ uint64_t a = *ra;
+ uint64_t b = *rb;
+ uint64_t c = *rc;
+
+ tiger_round( &a, &b, &c, x[0], mul );
+ tiger_round( &b, &c, &a, x[1], mul );
+ tiger_round( &c, &a, &b, x[2], mul );
+ tiger_round( &a, &b, &c, x[3], mul );
+ tiger_round( &b, &c, &a, x[4], mul );
+ tiger_round( &c, &a, &b, x[5], mul );
+ tiger_round( &a, &b, &c, x[6], mul );
+ tiger_round( &b, &c, &a, x[7], mul );
+
+ *ra = a;
+ *rb = b;
+ *rc = c;
}
static void
key_schedule( uint64_t *x )
{
- x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5LL;
- x[1] ^= x[0];
- x[2] += x[1];
- x[3] -= x[2] ^ ((~x[1]) << 19 );
- x[4] ^= x[3];
- x[5] += x[4];
- x[6] -= x[5] ^ ((~x[4]) >> 23 );
- x[7] ^= x[6];
- x[0] += x[7];
- x[1] -= x[0] ^ ((~x[7]) << 19 );
- x[2] ^= x[1];
- x[3] += x[2];
- x[4] -= x[3] ^ ((~x[2]) >> 23 );
- x[5] ^= x[4];
- x[6] += x[5];
- x[7] -= x[6] ^ 0x0123456789abcdefLL;
+ x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5LL;
+ x[1] ^= x[0];
+ x[2] += x[1];
+ x[3] -= x[2] ^ ((~x[1]) << 19 );
+ x[4] ^= x[3];
+ x[5] += x[4];
+ x[6] -= x[5] ^ ((~x[4]) >> 23 );
+ x[7] ^= x[6];
+ x[0] += x[7];
+ x[1] -= x[0] ^ ((~x[7]) << 19 );
+ x[2] ^= x[1];
+ x[3] += x[2];
+ x[4] -= x[3] ^ ((~x[2]) >> 23 );
+ x[5] ^= x[4];
+ x[6] += x[5];
+ x[7] -= x[6] ^ 0x0123456789abcdefLL;
}
@@ -669,187 +711,214 @@ key_schedule( uint64_t *x )
* Transform the message DATA which consists of 512 bytes (8 words)
*/
static void
-transform( TIGER_CONTEXT *hd, const unsigned char *data )
+transform ( TIGER_CONTEXT *hd, const unsigned char *data )
{
- uint64_t a,b,c,aa,bb,cc;
- uint64_t x[8];
- #ifdef WORDS_BIGENDIAN
- #define MKWORD(d,n) \
+ uint64_t a,b,c,aa,bb,cc;
+ uint64_t x[8];
+#ifdef WORDS_BIGENDIAN
+#define MKWORD(d,n) \
( ((uint64_t)(d)[8*(n)+7]) << 56 | ((uint64_t)(d)[8*(n)+6]) << 48 \
| ((uint64_t)(d)[8*(n)+5]) << 40 | ((uint64_t)(d)[8*(n)+4]) << 32 \
| ((uint64_t)(d)[8*(n)+3]) << 24 | ((uint64_t)(d)[8*(n)+2]) << 16 \
| ((uint64_t)(d)[8*(n)+1]) << 8 | ((uint64_t)(d)[8*(n) ]) )
- x[0] = MKWORD(data, 0);
- x[1] = MKWORD(data, 1);
- x[2] = MKWORD(data, 2);
- x[3] = MKWORD(data, 3);
- x[4] = MKWORD(data, 4);
- x[5] = MKWORD(data, 5);
- x[6] = MKWORD(data, 6);
- x[7] = MKWORD(data, 7);
- #undef MKWORD
- #else
- memcpy( &x[0], data, 64 );
- #endif
-
- /* save */
- a = aa = hd->a;
- b = bb = hd->b;
- c = cc = hd->c;
-
- // print functions have been removed (jk)
- pass( &a, &b, &c, x, 5);
- key_schedule( x );
- pass( &c, &a, &b, x, 7);
- key_schedule( x );
- pass( &b, &c, &a, x, 9);
-
- /* feedforward */
- a ^= aa;
- b -= bb;
- c += cc;
- /* store */
- hd->a = a;
- hd->b = b;
- hd->c = c;
+ x[0] = MKWORD(data, 0);
+ x[1] = MKWORD(data, 1);
+ x[2] = MKWORD(data, 2);
+ x[3] = MKWORD(data, 3);
+ x[4] = MKWORD(data, 4);
+ x[5] = MKWORD(data, 5);
+ x[6] = MKWORD(data, 6);
+ x[7] = MKWORD(data, 7);
+#undef MKWORD
+#else
+ memcpy( &x[0], data, 64 );
+#endif
+
+ /* save */
+ a = aa = hd->a;
+ b = bb = hd->b;
+ c = cc = hd->c;
+
+ pass( &a, &b, &c, x, 5);
+ key_schedule( x );
+ pass( &c, &a, &b, x, 7);
+ key_schedule( x );
+ pass( &b, &c, &a, x, 9);
+
+ /* feedforward */
+ a ^= aa;
+ b -= bb;
+ c += cc;
+ /* store */
+ hd->a = a;
+ hd->b = b;
+ hd->c = c;
}
-void
-tiger_init( TIGER_CONTEXT *hd )
-{
- hd->a = 0x0123456789abcdefLL;
- hd->b = 0xfedcba9876543210LL;
- hd->c = 0xf096a5b4c3b2e187LL;
- hd->nblocks = 0;
- hd->count = 0;
-}
+
/* Update the message digest with the contents
- * of INBUF with length INLEN. */
-void
-tiger_update(TIGER_CONTEXT *hd, const unsigned char *inbuf, size_t inlen)
+ * of INBUF with length INLEN.
+ */
+static void
+tiger_write ( void *context, const void *inbuf_arg, size_t inlen)
{
- if( hd->count == 64 ) { /* flush the buffer */
- transform( hd, hd->buf );
- hd->count = 0;
- hd->nblocks++;
- }
- if( !inbuf )
- return;
- if( hd->count ) {
- for( ; inlen && hd->count < 64; inlen-- )
- hd->buf[hd->count++] = *inbuf++;
- tiger_update( hd, NULL, 0 );
- if( !inlen ) {
- return;
- }
+ const unsigned char *inbuf = (const unsigned char *)inbuf_arg;
+ TIGER_CONTEXT *hd = (TIGER_CONTEXT *)context;
+ if( hd->count == 64) /* flush the buffer */
+ {
+ transform( hd, hd->buf );
+ _gcry_burn_stack (21*8+11*sizeof(void*));
+ hd->count = 0;
+ hd->nblocks++;
+ }
+ if( !inbuf )
+ return;
+ if( hd->count )
+ {
+ for( ; inlen && hd->count < 64; inlen-- )
+ hd->buf[hd->count++] = *inbuf++;
+ tiger_write( hd, NULL, 0 );
+ if( !inlen )
+ return;
}
- while( inlen >= 64 ) {
+ while( inlen >= 64 )
+ {
transform( hd, inbuf );
hd->count = 0;
hd->nblocks++;
inlen -= 64;
inbuf += 64;
}
- for( ; inlen && hd->count < 64; inlen-- )
- hd->buf[hd->count++] = *inbuf++;
+ _gcry_burn_stack (21*8+11*sizeof(void*));
+ for( ; inlen && hd->count < 64; inlen-- )
+ hd->buf[hd->count++] = *inbuf++;
}
-/* The routine terminates the computation */
-void
-tiger_final(unsigned char hash[24], TIGER_CONTEXT *hd)
+
+
+/* The routine terminates the computation
+ */
+static void
+tiger_final( void *context )
{
- uint32_t t, msb, lsb;
- unsigned char *p;
- int i, j;
-
- tiger_update(hd, NULL, 0); /* flush */;
-
- msb = 0;
- t = hd->nblocks;
- if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */
- msb++;
- msb += t >> 26;
- t = lsb;
- if( (lsb = t + hd->count) < t ) /* add the count */
- msb++;
- t = lsb;
- if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
- msb++;
- msb += t >> 29;
-
- if( hd->count < 56 ) { /* enough room */
- hd->buf[hd->count++] = 0x01; /* pad */
- while( hd->count < 56 )
- hd->buf[hd->count++] = 0; /* pad */
+ TIGER_CONTEXT *hd = (TIGER_CONTEXT *)context;
+ uint32_t t, msb, lsb;
+ unsigned char *p;
+ unsigned char pad = hd->variant == 2? 0x80 : 0x01;
+
+ tiger_write(hd, NULL, 0); /* flush */;
+
+ t = hd->nblocks;
+ /* multiply by 64 to make a byte count */
+ lsb = t << 6;
+ msb = t >> 26;
+ /* add the count */
+ t = lsb;
+ if( (lsb += hd->count) < t )
+ msb++;
+ /* multiply by 8 to make a bit count */
+ t = lsb;
+ lsb <<= 3;
+ msb <<= 3;
+ msb |= t >> 29;
+
+ if( hd->count < 56 ) /* enough room */
+ {
+ hd->buf[hd->count++] = pad;
+ while( hd->count < 56 )
+ hd->buf[hd->count++] = 0; /* pad */
+ }
+ else /* need one extra block */
+ {
+ hd->buf[hd->count++] = pad; /* pad character */
+ while( hd->count < 64 )
+ hd->buf[hd->count++] = 0;
+ tiger_write(hd, NULL, 0); /* flush */;
+ memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+ }
+ /* append the 64 bit count */
+ hd->buf[56] = lsb ;
+ hd->buf[57] = lsb >> 8;
+ hd->buf[58] = lsb >> 16;
+ hd->buf[59] = lsb >> 24;
+ hd->buf[60] = msb ;
+ hd->buf[61] = msb >> 8;
+ hd->buf[62] = msb >> 16;
+ hd->buf[63] = msb >> 24;
+ transform( hd, hd->buf );
+ _gcry_burn_stack (21*8+11*sizeof(void*));
+
+ p = hd->buf;
+#ifdef WORDS_BIGENDIAN
+#define X(a) do { *(uint64_t*)p = hd->a ; p += 8; } while(0)
+#else /* little endian */
+#define X(a) do { *p++ = hd->a >> 56; *p++ = hd->a >> 48; \
+ *p++ = hd->a >> 40; *p++ = hd->a >> 32; \
+ *p++ = hd->a >> 24; *p++ = hd->a >> 16; \
+ *p++ = hd->a >> 8; *p++ = hd->a; } while(0)
+#endif
+#define Y(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \
+ *p++ = hd->a >> 16; *p++ = hd->a >> 24; \
+ *p++ = hd->a >> 32; *p++ = hd->a >> 40; \
+ *p++ = hd->a >> 48; *p++ = hd->a >> 56; } while(0)
+ if (hd->variant == 0)
+ {
+ X(a);
+ X(b);
+ X(c);
}
- else { /* need one extra block */
- hd->buf[hd->count++] = 0x01; /* pad character */
- while( hd->count < 64 )
- hd->buf[hd->count++] = 0;
- tiger_update(hd, NULL, 0); /* flush */;
- memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+ else
+ {
+ Y(a);
+ Y(b);
+ Y(c);
}
- /* append the 64 bit count */
- hd->buf[56] = lsb ;
- hd->buf[57] = lsb >> 8;
- hd->buf[58] = lsb >> 16;
- hd->buf[59] = lsb >> 24;
- hd->buf[60] = msb ;
- hd->buf[61] = msb >> 8;
- hd->buf[62] = msb >> 16;
- hd->buf[63] = msb >> 24;
- transform( hd, hd->buf );
-
- p = hd->buf;
- #ifdef WORDS_BIGENDIAN
- #define X(a) do { *(uint64_t *)p = hd->a ; p += 8; } while(0)
- // Original code - modified by jk to deal with gcc changes
- // #define X(a) do { *(u64*)p = hd->##a ; p += 8; } while(0)
- #else /* little endian */
- #define X(a) do { *p++ = hd->a >> 56; *p++ = hd->a >> 48; \
- *p++ = hd->a >> 40; *p++ = hd->a >> 32; \
- *p++ = hd->a >> 24; *p++ = hd->a >> 16; \
- *p++ = hd->a >> 8; *p++ = hd->a; } while(0)
-
- /* Original code - modified by jk to deal with gcc changes
- #define X(a) do { *p++ = hd->##a >> 56; *p++ = hd->##a >> 48; \
- *p++ = hd->##a >> 40; *p++ = hd->##a >> 32; \
- *p++ = hd->##a >> 24; *p++ = hd->##a >> 16; \
- *p++ = hd->##a >> 8; *p++ = hd->##a; } while(0)
- */
-
- #endif
- X(a);
- X(b);
- X(c);
- #undef X
-
- /* unpack the hash */
- // Modified by jk to produce little endian output like MD5 or SHA-1
- j=0;
- for (i=0; i<8; i++)
- hash[j++] = (hd->a >> 8*i) & 0xff;
- j=8;
- for (i=0; i<8; i++)
- hash[j++] = (hd->b >> 8*i) & 0xff;
- j=16;
- for (i=0; i<8; i++)
- hash[j++] = (hd->c >> 8*i) & 0xff;
-
-
- /* Original code, produces output in big endian
- j=7;
- for (i=0; i<8; i++)
- hash[j--] = (hd->a >> 8*i) & 0xff;
- j=15;
- for (i=0; i<8; i++)
- hash[j--] = (hd->b >> 8*i) & 0xff;
- j=23;
- for (i=0; i<8; i++)
- hash[j--] = (hd->c >> 8*i) & 0xff;
- */
+#undef X
+#undef Y
}
+static unsigned char *
+tiger_read( void *context )
+{
+ TIGER_CONTEXT *hd = (TIGER_CONTEXT *)context;
+
+ return hd->buf;
+}
+
+
+
+
+
+// ------------------------------------------------------------------
+// End Libgcrypt code
+// ------------------------------------------------------------------
+
+void hash_init_tiger(void * ctx)
+{
+ // Variant 0, Unknown
+ // tiger_init(ctx)
+
+ // Variant 1, Tiger
+ tiger1_init(ctx);
+
+ // Variant 2, The Tiger2 Hash
+ // http://www.cs.technion.ac.il/~biham/Reports/Tiger/tiger2-test-vectors-nessie-format.dat
+ // tiger2_init(ctx);
+}
+
+
+void hash_update_tiger(void * ctx, const unsigned char *buf, size_t len)
+{
+ tiger_write(ctx,buf,len);
+}
+
+
+void hash_final_tiger(void * ctx, unsigned char *sum)
+{
+ tiger_final(ctx);
+ unsigned char * tmp = tiger_read(ctx);
+ memcpy(sum,tmp,64);
+}
diff --git a/src/tiger.h b/src/tiger.h
index 854cc14..75f7fb1 100644
--- a/src/tiger.h
+++ b/src/tiger.h
@@ -12,29 +12,14 @@
*
*/
-/* $Id: tiger.h 501 2011-09-25 17:12:27Z xchatty $ */
+/* $Id: tiger.h 636 2012-06-09 13:16:59Z jessekornblum $ */
#ifndef __TIGER_H
#define __TIGER_H
-#include "common.h"
-__BEGIN_DECLS
-
-
-#define TIGER_BLOCKSIZE 64
-#define TIGER_HASHSIZE 24
-typedef struct {
- uint64_t a, b, c;
- unsigned char buf[64];
- int count;
- uint32_t nblocks;
-} TIGER_CONTEXT;
-
-extern void tiger_init(TIGER_CONTEXT *hd);
-extern void tiger_update(TIGER_CONTEXT *hd, const unsigned char *inbuf, size_t inlen);
-extern void tiger_final(unsigned char hash[24], TIGER_CONTEXT *hd);
+__BEGIN_DECLS
void hash_init_tiger(void * ctx);
void hash_update_tiger(void * ctx, const unsigned char *buf, size_t len);
--
debian-forensics/md5deep
More information about the forensics-changes
mailing list