/* * 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 #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; }