readdb: changed signature modifier delimiter from '/' to '::'

readdb: moved signature modifier handling from cli_parse_add to loadldb
readdb: fixed an issue regarding ';' within pcre subsigs
remotes/push_mirror/features/yara
Kevin Lin 10 years ago
parent c2d84c3ed5
commit 5d9cac7be6
  1. 188
      libclamav/readdb.c

@ -123,8 +123,9 @@ static int sigopts_handler(struct cli_matcher *root, const char *virname, const
char *hexcpy, *start, *end;
int i, ret = CL_SUCCESS;
/* prevent cyclic loops with cli_parse_add on same hexsig
* cyclic loops should be impossible though
/*
* cyclic loops with cli_parse_add are impossible now as cli_parse_add
* no longer calls sigopts_handler; leaving here for safety
*/
if (sigopts & ACPATT_OPTION_ONCE) {
cli_errmsg("sigopts_handler: invalidly called multiple times!\n");
@ -351,7 +352,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
return CL_SUCCESS;
}
if (strrchr(hexsig, '/')) {
char *start, *end, *sub;
char *start, *end;
/* get copied */
hexcpy = cli_strdup(hexsig);
@ -362,75 +363,41 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
start = strchr(hexcpy, '/');
end = strrchr(hexcpy, '/');
/* get plus-ed (modifiers) */
sub = strchr(end, '+');
if (sub && start == end)
*end = '\0';
/* get pcre-ed */
if (!sub && start != end) {
if (start == end) {
cli_errmsg("cli_parseadd(): PCRE subsig mismatched '/' delimiter\n");
return CL_EMALFDB;
}
#if HAVE_PCRE
/* expected format => ^offset:trigger/regex/[cflags]$ */
const char *trigger, *pattern, *cflags;
/* expected format => ^offset:trigger/regex/[cflags]$ */
const char *trigger, *pattern, *cflags;
/* get checked */
if (hexsig[0] == '/') {
cli_errmsg("cli_parseadd(): PCRE subsig must contain logical trigger\n");
return CL_EMALFDB;
}
/* get checked */
if (hexsig[0] == '/') {
cli_errmsg("cli_parseadd(): PCRE subsig must contain logical trigger\n");
return CL_EMALFDB;
}
/* get NULL-ed */
*start = '\0';
*end = '\0';
/* get NULL-ed */
*start = '\0';
*end = '\0';
/* get tokens-ed */
trigger = hexcpy;
pattern = start+1;
cflags = end+1;
if (*cflags == '\0') /* get compat-ed */
cflags = NULL;
/* get tokens-ed */
trigger = hexcpy;
pattern = start+1;
cflags = end+1;
if (*cflags == '\0') /* get compat-ed */
cflags = NULL;
/* normal trigger, get added */
ret = cli_pcre_addpatt(root, virname, trigger, pattern, cflags, offset, lsigid, options);
free(hexcpy);
return ret;
/* normal trigger, get added */
ret = cli_pcre_addpatt(root, virname, trigger, pattern, cflags, offset, lsigid, options);
free(hexcpy);
return ret;
#else
free(hexcpy);
cli_errmsg("cli_parseadd(): cannot parse PCRE subsig without PCRE support\n");
return CL_EPARSE;
free(hexcpy);
cli_errmsg("cli_parseadd(): cannot parse PCRE subsig without PCRE support\n");
return CL_EPARSE;
#endif
} else { /* get option-ed */
/* get NULL-ed */
char *opt = sub ? sub : end;
uint8_t sigopts = 0;
*opt++ = '\0';
while (*opt != '\0') {
switch (*opt) {
case 'i':
sigopts |= ACPATT_OPTION_NOCASE;
break;
case 'f':
sigopts |= ACPATT_OPTION_FULLWORD;
break;
case 'w':
sigopts |= ACPATT_OPTION_WIDE;
break;
case 'a':
sigopts |= ACPATT_OPTION_ASCII;
break;
default:
cli_errmsg("cli_parse_add: Signature for %s uses invalid option: %02x\n", virname, *opt);
return CL_EMALFDB;
}
opt++;
}
ret = sigopts_handler(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options);
free(hexcpy);
return ret;
}
}
else if((wild = strchr(hexsig, '{'))) {
if(sscanf(wild, "%c%u%c", &l, &range, &r) == 3 && l == '{' && r == '}' && range > 0 && range < 128) {
@ -1610,25 +1577,55 @@ static inline int init_tdb(struct cli_lsig_tdb *tdb, struct cl_engine *engine, c
}
/* 0 1 2 3 4 5 ... (max 66)
* VirusName:Attributes:Logic:SubSig1[:SubSig2[:SubSig3 ... ]]
* VirusName;Attributes;Logic;SubSig1[;SubSig2[;SubSig3 ... ]]
* NOTE: Maximum of 64(see MAX_LDB_SUBSIGS) subsignatures (last would be token 66)
*/
#define LDB_TOKENS 67
static int ldb_tokenize(char *buffer, const char **tokens)
{
const size_t token_count = LDB_TOKENS + 1;
size_t tokens_found, i;
int within_pcre = 0;
for(tokens_found = 0; tokens_found < token_count; ) {
tokens[tokens_found++] = buffer;
while (*buffer != '\0') {
if (!within_pcre && (*buffer == ';'))
break;
else if ((tokens_found > 2) && (*buffer == '/'))
within_pcre = !within_pcre;
buffer++;
}
if(*buffer != '\0') {
*buffer++ = '\0';
} else {
i = tokens_found;
while(i < token_count)
tokens[i++] = NULL;
return tokens_found;
}
}
return tokens_found;
}
static int load_oneldb(char *buffer, int chkpua, struct cl_engine *engine, unsigned int options, const char *dbname, unsigned int line, unsigned int *sigs, unsigned bc_idx, const char *buffer_cpy, int *skip)
{
const char *sig, *virname, *offset, *logic;
struct cli_ac_lsig **newtable, *lsig;
char *tokens[LDB_TOKENS+1], *pt, *pt2;
char *tokens[LDB_TOKENS+1], *pt, *lsl, *rsl;
int i, subsigs, tokens_count;
unsigned short target = 0;
struct cli_matcher *root;
struct cli_lsig_tdb tdb;
uint32_t lsigid[2];
uint8_t subsig_opts;
int ret;
UNUSEDPARAM(dbname);
tokens_count = cli_strtokenize(buffer, ';', LDB_TOKENS + 1, (const char **) tokens);
tokens_count = ldb_tokenize(buffer, (const char **) tokens);
if(tokens_count < 4) {
return CL_EMALFDB;
}
@ -1737,22 +1734,59 @@ static int load_oneldb(char *buffer, int chkpua, struct cl_engine *engine, unsig
tdb.subsigs = subsigs;
for(i = 0; i < subsigs; i++) {
subsig_opts = 0;
lsigid[1] = i;
offset = "*";
sig = tokens[3 + i];
pt2 = strchr(tokens[3 + i], '/');
pt = strchr(tokens[3 + i], ':');
if(pt && (!pt2 || (pt < pt2))) {
*pt = 0;
sig = ++pt;
offset = tokens[3 + i];
} else {
offset = "*";
sig = tokens[3 + i];
/* check for offset and subsig modifiers */
pt = tokens[3 + i];
lsl = strchr(tokens[3 + i], '/');
rsl = strrchr(tokens[3 + i], '/');
while((pt = strchr(pt, ':'))) {
/* pcre subsig expression */
if((lsl && rsl) && (lsl < pt) && (pt < rsl)) {
pt++;
continue;
}
*pt++ = 0;
if(*pt == ':') { /* signature modifiers */
*pt++ = 0;
while(*pt != '\0') {
switch(*pt) {
case 'i':
subsig_opts |= ACPATT_OPTION_NOCASE;
break;
case 'f':
subsig_opts |= ACPATT_OPTION_FULLWORD;
break;
case 'w':
subsig_opts |= ACPATT_OPTION_WIDE;
break;
case 'a':
subsig_opts |= ACPATT_OPTION_ASCII;
break;
default:
cli_errmsg("cli_loadldb: Signature for %s uses invalid option: %02x\n", virname, *pt);
return CL_EMALFDB;
}
pt++;
}
} else {
sig = pt;
offset = tokens[3 + i];
}
}
if(subsig_opts)
ret = sigopts_handler(root, virname, sig, subsig_opts, 0, 0, offset, target, lsigid, options);
else
ret = cli_parse_add(root, virname, sig, 0, 0, 0, offset, target, lsigid, options);
if((ret = cli_parse_add(root, virname, sig, 0, 0, 0, offset, target, lsigid, options)))
if(ret)
return ret;
if(sig[0] == '$' && i) {

Loading…
Cancel
Save