Permalink
Browse files

Case insensitive option in audit mode

1 parent 964fec8 commit a64917a2bd9fec99b0693f0781c396886ee6f0ad jessekornblum committed Nov 13, 2012
Showing with 91 additions and 63 deletions.
  1. +6 −1 man/hashdeep.1
  2. +12 −8 src/display.cpp
  3. +34 −20 src/hash.cpp
  4. +34 −27 src/hashlist.cpp
  5. +4 −5 src/main.cpp
  6. +1 −2 src/main.h
View
@@ -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>] [\-j <num>] [\fBFILES\fR]
+[\-o <fbcplsde>] [-amxwMXreEspblvv] [\-F<bum>] [\-j <num>] [\fBFILES\fR]
.SH DESCRIPTION
@@ -134,6 +134,11 @@ remaining for each file being processed. Time estimates for files
larger than 4GB are not available on Windows. This mode may not be
used with th \-p mode.
+.TP
+\fB\-E\fR
+When in audit mode, performs case insensitive matching of filenames.
+For example, \\foo\\bar will match to \\Foo\\BAR. This can be important
+on Windows systems, where filenames are case insensitive.
.TP
\fB\-i <size> \fR
View
@@ -738,11 +738,13 @@ void display::md5deep_display_hash(file_data_hasher_t *fdht,const hash_context_
/*
* Externally called to display a simple hash
*/
-void display::display_hash_simple(file_data_hasher_t *fdht,const hash_context_obj *hc)
+void display::display_hash_simple(file_data_hasher_t *fdht,
+ const hash_context_obj *hc)
{
- if(this->dfxml){
- fdht->compute_dfxml(opt_show_matched,hc);
- return;
+ if (this->dfxml)
+ {
+ fdht->compute_dfxml(opt_show_matched,hc);
+ return;
}
/* Old comment:
@@ -766,10 +768,12 @@ void display::display_hash_simple(file_data_hasher_t *fdht,const hash_context_ob
line << hc->read_len << ",";
- for (int i = 0 ; i < NUM_ALGORITHMS ; ++i) {
- if (hashes[i].inuse){
- line << fdht->hash_hex[i] << ",";
- }
+ for (int i = 0 ; i < NUM_ALGORITHMS ; ++i)
+ {
+ if (hashes[i].inuse)
+ {
+ line << fdht->hash_hex[i] << ",";
+ }
}
line << fmt_filename(fdht);
if(fdht->ocb->piecewise_size > 0){
View
@@ -42,11 +42,12 @@ static int file_fatal_error()
return FALSE;
}
-static std::string make_stars(int count)
+static std::string make_stars(size_t count)
{
std::string ret;
- for(int i=0;i<count;i++){
- ret.push_back('*');
+ for (size_t i = 0 ; i < count ; i++)
+ {
+ ret.push_back('*');
}
return ret;
}
@@ -286,24 +287,37 @@ void file_data_hasher_t::hash()
ocb->fatal_error("hash.cpp: iomode setting invalid (%d)",ocb->opt_iomode);
}
- /*
- * If this file is above the size threshold set by the user, skip it
- * and set the hash to be stars
- */
- if ((ocb->mode_size) && (fdht->stat_bytes > ocb->size_threshold)) {
- if (ocb->mode_size_all) {
- for (int i = 0 ; i < NUM_ALGORITHMS ; ++i) {
- if (hashes[i].inuse){
- fdht->hash_hex[i] = make_stars(hashes[i].bit_length/4);
- }
- }
- if(md5deep_mode){
- fdht->ocb->md5deep_display_hash(fdht,0); // no hash
- } else {
- fdht->ocb->display_hash(fdht,0);
- }
+ // If this file is above the size threshold set by the user, skip it
+ // and set the hash to be stars
+ if ((ocb->mode_size) and (fdht->stat_bytes > ocb->size_threshold))
+ {
+ if (ocb->mode_size_all)
+ {
+ for (int i = 0 ; i < NUM_ALGORITHMS ; ++i)
+ {
+ if (hashes[i].inuse)
+ {
+ fdht->hash_hex[i] = make_stars(hashes[i].bit_length/4);
+ }
}
- return ; // close will happend when the fdht is killed
+
+ if (md5deep_mode)
+ {
+ fdht->ocb->md5deep_display_hash(fdht,0); // no hash
+ }
+ else
+ {
+ // RBF - This line causes a CRASH. The function display_hash
+ // RBF - accesses fields in the second argument, which is supposed
+ // RBF - to be a pointer, without checking whether the pointer
+ // RBF - is valid or not.
+ // RBF - Replicate with ./hashdeep -I 1 *
+ fdht->ocb->display_hash(fdht,0);
+ }
+ }
+
+ // close will happend when the fdht is killed
+ return ;
}
}
View
@@ -11,9 +11,10 @@
#include <new>
#include <iostream>
-/* Add a fi to the hash list.
- * Be sure that the hash is all lower case, because that's what we use internally.
- */
+/// Add a fi to the hash list.
+///
+/// Be sure that the hash is all lower case, because that's what we
+/// use internally.
void hashlist::hashmap::add_file(file_data_t *fi,int alg_num)
{
if (fi->hash_hex[alg_num].size())
@@ -110,9 +111,10 @@ hashlist::searchstatus_t hashlist::search(const file_data_hasher_t *fdht,
fdht->file_name,
fdht->file_number);
- if (!matched)
+ if (not matched)
{
- continue; // no match
+ // No match
+ continue;
}
if (matched_)
@@ -121,16 +123,18 @@ hashlist::searchstatus_t hashlist::search(const file_data_hasher_t *fdht,
// Verify that all of the other hash functions for *it match fdt as well,
// but only for the cases when we have a hash for both the master file
// and the target file.
- for (int j=0;j<NUM_ALGORITHMS;j++)
+ for (int j=0 ; j<NUM_ALGORITHMS ; j++)
{
- if (hashes[j].inuse && j!=alg and
+ if (hashes[j].inuse and
+ j != alg and
fdht->hash_hex[j].size() and
matched->hash_hex[j].size())
{
if (fdht->hash_hex[j] != matched->hash_hex[j])
{
// We have found a hash collision for one algorithm, but not all
- // of them. That is, MD5(A) == MD5(B), but SHA1(A) != SHA1(B).
+ // of them. For example, MD5(A) == MD5(B), but SHA1(A) != SHA1(B).
+ // See http://www.win.tue.nl/hashclash/ for a program to create these.
return status_partial_match;
}
}
@@ -155,7 +159,6 @@ hashlist::searchstatus_t hashlist::search(const file_data_hasher_t *fdht,
}
else
{
- // RBF - Expand case insentitivity to regular matching modes?
if (strcasecmp(fdht->file_name.c_str(), matched->file_name.c_str()))
return status_file_name_mismatch;
}
@@ -171,11 +174,13 @@ hashlist::searchstatus_t hashlist::search(const file_data_hasher_t *fdht,
-/**
- * Returns the file type of a given input file.
- * fn is provided so that error messages can be printed.
- */
-hashlist::hashfile_format hashlist::identify_format(class display *ocb,const std::string &fn,FILE *handle)
+///
+/// Returns the file type of a given input file.
+/// fn is provided so that error messages can be printed.
+///
+hashlist::hashfile_format hashlist::identify_format(class display *ocb,
+ const std::string &fn,
+ FILE *handle)
{
char buf[MAX_STRING_LENGTH];
@@ -265,17 +270,18 @@ void hashlist::enable_hashing_algorithms_from_hashdeep_file(class display *ocb,c
void hashlist::dump_hashlist()
{
std::cout << "md5,sha1,bytes,filename matched\n";
- for(hashlist::const_iterator it = begin(); it!=end(); it++){
- std::cout << (*it)->hash_hex[alg_md5] << "," << (*it)->hash_hex[alg_sha1] << ","
- << (*it)->file_bytes << "," << (*it)->file_name
- << "\tmatched=" << (*it)->matched_file_number << "\n";
+ for (hashlist::const_iterator it = begin(); it!=end(); it++)
+ {
+ std::cout << (*it)->hash_hex[alg_md5] << "," << (*it)->hash_hex[alg_sha1] << ","
+ << (*it)->file_bytes << "," << (*it)->file_name
+ << "\tmatched=" << (*it)->matched_file_number << "\n";
}
}
uint64_t hashlist::total_matched()
{
uint64_t total = 0;
- for(hashlist::const_iterator it = begin(); it!=end(); it++)
+ for (hashlist::const_iterator it = begin(); it!=end(); it++)
{
if ( (*it)->matched_file_number > 0)
total++;
@@ -415,15 +421,16 @@ hashlist::load_hash_file(display *ocb,const std::string &fn)
*/
const char *hashlist::searchstatus_to_str(searchstatus_t val)
{
- switch (val) {
- case searchstatus_ok: return "ok";
- case status_match: return "complete match";
- case status_partial_match: return "partial match";
- case status_file_size_mismatch: return "file size mismatch";
- case status_file_name_mismatch: return "file name mismatch";
- case status_no_match: return "no match";
+ switch (val)
+ {
+ case searchstatus_ok: return "ok";
+ case status_match: return "complete match";
+ case status_partial_match: return "partial match";
+ case status_file_size_mismatch: return "file size mismatch";
+ case status_file_name_mismatch: return "file name mismatch";
+ case status_no_match: return "no match";
- default:
+ default:
return "unknown";
}
}
View
@@ -157,7 +157,7 @@ void state::hashdeep_usage()
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("-i/-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.");
@@ -174,6 +174,7 @@ void state::hashdeep_usage()
ocb.status("-V - display version number and exit");
ocb.status("-0 - use a NUL (\\0) for newline.");
ocb.status("-u - escape Unicode");
+ ocb.status("-E - Use case insensitive matching for filenames in audit mode");
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");
@@ -446,7 +447,6 @@ void algorithm_t::load_hashing_algorithms()
add_algorithm(alg_tiger, "tiger", 192, hash_init_tiger, hash_update_tiger, hash_final_tiger, DEFAULT_ENABLE_TIGER);
add_algorithm(alg_whirlpool, "whirlpool", 512, hash_init_whirlpool, hash_update_whirlpool, hash_final_whirlpool, DEFAULT_ENABLE_WHIRLPOOL);
- // RBF - Add SHA3 here
add_algorithm(alg_sha3,
"sha3",
256,
@@ -641,7 +641,6 @@ int state::hashdeep_process_command_line(int argc_, char **argv_)
break;
case 'I':
- // RBF - Document -I mode in hashdeep usage menu (-hh mode)
ocb.mode_size_all=true;
// falls through
case 'i':
@@ -742,7 +741,6 @@ int state::hashdeep_process_command_line(int argc_, char **argv_)
case 'u': ocb.opt_unicode_escape = true;break;
case 'j': ocb.opt_threadcount = atoi(optarg); break;
case 'F': ocb.opt_iomode = iomode::toiomode(optarg);break;
- // RBF - Document -E mode in hashdeep. Add to md5deep?
case 'E': ocb.opt_case_sensitive = false; break;
case 'h':
@@ -751,7 +749,7 @@ int state::hashdeep_process_command_line(int argc_, char **argv_)
did_usage = true;
break;
- case 'D': opt_debug = atoi(optarg);break;
+ case 'D': opt_debug = atoi(optarg); break;
default:
try_msg();
exit(EXIT_FAILURE);
@@ -1038,6 +1036,7 @@ int state::md5deep_process_command_line(int argc_, char **argv_)
case 'd': ocb.xml_open(stdout); break;
case 'f': opt_input_list = optarg; break;
case 'I':
+ // RBF - Document -I mode for hashdeep man page
ocb.mode_size_all=true;
// falls through
case 'i':
View
@@ -76,8 +76,7 @@ inline std::ostream & operator << (std::ostream &os,const hashid_t &h)
case alg_md5: os << "alg_md5" ; break ;
case alg_sha1: os << "alg_sha1" ; break ;
case alg_sha256: os << "alg_sha256" ; break ;
- // RBF - This is "alg_tige" not "alg_tiger". Is that ok?
- case alg_tiger: os << "alg_tige" ; break ;
+ case alg_tiger: os << "alg_tiger" ; break ;
case alg_whirlpool: os << "alg_whirlpool" ; break ;
case alg_sha3: os << "alg_sha3" ; break ;
case alg_unknown: os << "alg_unknown" ; break ;

0 comments on commit a64917a

Please sign in to comment.