00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef lint
00039 static char copyright[] =
00040 "@(#) Copyright (c) 2002\n\
00041 Netherlands Forensic Institute. All rights reserved.\n";
00042 #endif
00043
00044 #ifdef HAVE_CONFIG_H
00045 #include <config.h>
00046 #endif
00047
00048 #include "rdd.h"
00049 #include "rdd_internals.h"
00050
00051 #include <math.h>
00052 #include <string.h>
00053 #include <stdio.h>
00054
00055 #ifdef HAVE_OPENSSL
00056 #include <openssl/md5.h>
00057 #include <openssl/sha.h>
00058 #endif
00059
00060 #include "error.h"
00061 #include "writer.h"
00062 #include "filter.h"
00063 #include "msgprinter.h"
00064
00065 typedef struct _RDD_BLOCKHASH_FILTER {
00066 rdd_count_t blocknum;
00067 MD5_CTX md5_state;
00068 char *path;
00069 RDD_MSGPRINTER *printer;
00070 } RDD_BLOCKHASH_FILTER;
00071
00072 static int blockhash_input(RDD_FILTER *f,
00073 const unsigned char *buf, unsigned nbyte);
00074 static int blockhash_block(RDD_FILTER *f, unsigned nbyte);
00075 static int blockhash_close(RDD_FILTER *f);
00076 static int blockhash_free(RDD_FILTER *f);
00077
00078 static RDD_FILTER_OPS blockhash_ops = {
00079 blockhash_input,
00080 blockhash_block,
00081 blockhash_close,
00082 0,
00083 blockhash_free
00084 };
00085
00086 int
00087 rdd_new_md5_blockfilter(RDD_FILTER **self, unsigned blocksize,
00088 const char *outpath, const int force_overwrite)
00089 {
00090 RDD_FILTER *f = 0;
00091 RDD_BLOCKHASH_FILTER *state = 0;
00092 RDD_MSGPRINTER *prn = 0;
00093 char *path = 0;
00094 int rc;
00095
00096 rc = rdd_new_filter(&f, &blockhash_ops, sizeof(RDD_BLOCKHASH_FILTER),
00097 blocksize);
00098 if (rc != RDD_OK) {
00099 goto error;
00100 }
00101 state = (RDD_BLOCKHASH_FILTER *)f->state;
00102
00103 if ((path = malloc(strlen(outpath) + 1)) == 0) {
00104 rc = RDD_NOMEM;
00105 goto error;
00106 }
00107 strcpy(path, outpath);
00108
00109 if ((rc = rdd_mp_open_file_printer(&prn, outpath, force_overwrite)) != RDD_OK) {
00110 goto error;
00111 }
00112
00113 state->path = path;
00114 state->printer = prn;
00115 MD5_Init(&state->md5_state);
00116
00117 *self = f;
00118 return RDD_OK;
00119
00120 error:
00121 *self = 0;
00122 if (path != 0) free(path);
00123 if (state != 0) free(state);
00124 if (f != 0) free(f);
00125 return rc;
00126 }
00127
00130 static int
00131 blockhash_input(RDD_FILTER *self, const unsigned char *buf, unsigned nbyte)
00132 {
00133 RDD_BLOCKHASH_FILTER *state = (RDD_BLOCKHASH_FILTER *) self->state;
00134
00135 MD5_Update(&state->md5_state, buf, nbyte);
00136
00137 return RDD_OK;
00138 }
00139
00143 static int
00144 blockhash_block(RDD_FILTER *self, unsigned block_size)
00145 {
00146 RDD_BLOCKHASH_FILTER *state = (RDD_BLOCKHASH_FILTER *) self->state;
00147 unsigned char md5bytes[MD5_DIGEST_LENGTH];
00148 char digest[2*MD5_DIGEST_LENGTH + 1];
00149 int rc;
00150
00151 MD5_Final(md5bytes, &state->md5_state);
00152
00153 rc = rdd_buf2hex(md5bytes, sizeof md5bytes, digest, sizeof digest);
00154 if (rc != RDD_OK) {
00155 return rc;
00156 }
00157 rdd_mp_message(state->printer, RDD_MSG_INFO, "%llu\t%s",
00158 state->blocknum, digest);
00159
00160 state->blocknum++;
00161 MD5_Init(&state->md5_state);
00162
00163 return RDD_OK;
00164 }
00165
00166 static int
00167 blockhash_close(RDD_FILTER *self)
00168 {
00169 RDD_BLOCKHASH_FILTER *state = (RDD_BLOCKHASH_FILTER *) self->state;
00170 unsigned char md5bytes[MD5_DIGEST_LENGTH];
00171 int rc;
00172
00173 MD5_Final(md5bytes, &state->md5_state);
00174
00175 rc = rdd_mp_close(state->printer, RDD_MP_RECURSE|RDD_MP_READONLY);
00176 if (rc != RDD_OK) {
00177 return rc;
00178 }
00179
00180 return RDD_OK;
00181 }
00182
00183 static int
00184 blockhash_free(RDD_FILTER *self)
00185 {
00186 RDD_BLOCKHASH_FILTER *state = (RDD_BLOCKHASH_FILTER *) self->state;
00187
00188 free(state->path);
00189
00190 return RDD_OK;
00191 }