ClamAV is an open source (GPLv2) anti-virus toolkit.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
clamav/libclamav/matcher-md5.c

135 lines
3.0 KiB

/*
* Copyright (C) 2007-2010 Sourcefire, Inc.
*
* Authors: Tomasz Kojm
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdio.h>
#include "clamav.h"
#include "memory.h"
#include "mpool.h"
#include "others.h"
#include "cltypes.h"
#include "matcher.h"
#include "matcher-md5.h"
#define HASH(a,b,c) (211 * a + 37 * b + c)
int cli_md5m_addpatt(struct cli_matcher *root, struct cli_md5m_patt *patt)
{
unsigned int idx;
struct cli_md5m_patt *prev, *next = NULL;
idx = HASH(patt->md5[0], patt->md5[1], patt->md5[2]);
prev = next = root->md5tab[idx];
while(next) {
if(patt->md5[0] >= next->md5[0])
break;
prev = next;
next = next->next;
}
if(next == root->md5tab[idx]) {
patt->next = root->md5tab[idx];
root->md5tab[idx] = patt;
} else {
patt->next = prev->next;
prev->next = patt;
}
root->md5_patterns++;
return CL_SUCCESS;
}
int cli_md5m_init(struct cli_matcher *root)
{
#ifdef USE_MPOOL
if(!root->mempool) {
cli_errmsg("cli_md5m_init: mempool must be initialized\n");
return CL_EMEM;
}
#endif
if(!(root->md5tab = (struct cli_md5m_patt **) mpool_calloc(root->mempool, HASH(255, 255, 255) + 1, sizeof(struct cli_md5m_patt *)))) {
mpool_free(root->mempool, root->bm_shift);
return CL_EMEM;
}
return CL_SUCCESS;
}
void cli_md5m_free(struct cli_matcher *root)
{
struct cli_md5m_patt *patt, *prev;
unsigned int i, size = HASH(255, 255, 255) + 1;
if(root->md5tab) {
for(i = 0; i < size; i++) {
patt = root->md5tab[i];
while(patt) {
prev = patt;
patt = patt->next;
if(prev->virname)
mpool_free(root->mempool, prev->virname);
mpool_free(root->mempool, prev);
}
}
mpool_free(root->mempool, root->md5tab);
}
}
int cli_md5m_scan(const unsigned char *md5, uint32_t filesize, const char **virname, const struct cli_matcher *root)
{
unsigned int pchain = 0, idx;
struct cli_md5m_patt *p;
if(!root)
return CL_CLEAN;
idx = HASH(md5[0], md5[1], md5[2]);
p = root->md5tab[idx];
if(!p || (!p->next && p->filesize != filesize))
return CL_CLEAN;
while(p) {
if(p->md5[0] != md5[0]) {
if(pchain)
break;
p = p->next;
continue;
} else pchain = 1;
if(p->filesize != filesize) {
p = p->next;
continue;
}
if(!memcmp(p->md5, md5, 16)) {
if(virname)
*virname = p->virname;
return CL_VIRUS;
}
p = p->next;
}
return CL_CLEAN;
}