From 278b2b286d89f2e225cda21cb9cca70b725cb975 Mon Sep 17 00:00:00 2001 From: Shawn webb Date: Thu, 18 Oct 2012 10:41:12 -0400 Subject: [PATCH 1/8] Rudimentary blacklisting --- libclamav/asn1.c | 2 +- libclamav/crtmgr.c | 7 ++++++- libclamav/crtmgr.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libclamav/asn1.c b/libclamav/asn1.c index e29f105ce..1e914d8eb 100644 --- a/libclamav/asn1.c +++ b/libclamav/asn1.c @@ -840,7 +840,7 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg cli_dbgmsg("asn1_parse_mscat: %u new certificates collected\n", newcerts.items); while(x509) { cli_crt *parent = crtmgr_verify_crt(cmgr, x509); - if(parent) { + if(parent && !(parent->isBlacklisted)) { x509->codeSign &= parent->codeSign; x509->timeSign &= parent->timeSign; if(crtmgr_add(cmgr, x509)) diff --git a/libclamav/crtmgr.c b/libclamav/crtmgr.c index 0d64106a9..f8a16f465 100644 --- a/libclamav/crtmgr.c +++ b/libclamav/crtmgr.c @@ -31,6 +31,7 @@ int cli_crt_init(cli_crt *x509) { cli_errmsg("cli_crt_init: mp_init_multi failed with %d\n", ret); return 1; } + x509->isBlacklisted = 0; x509->not_before = x509->not_after = 0; x509->prev = x509->next = NULL; x509->certSign = x509->codeSign = x509->timeSign = 0; @@ -116,6 +117,7 @@ int crtmgr_add(crtmgr *m, cli_crt *x509) { i->certSign = x509->certSign; i->codeSign = x509->codeSign; i->timeSign = x509->timeSign; + i->isBlacklisted = x509->isBlacklisted; i->next = m->crts; i->prev = NULL; if(m->crts) @@ -314,8 +316,11 @@ cli_crt *crtmgr_verify_pkcs7(crtmgr *m, const uint8_t *issuer, const uint8_t *se continue; if(!memcmp(i->issuer, issuer, sizeof(i->issuer)) && !memcmp(i->serial, serial, sizeof(i->serial)) && - !crtmgr_rsa_verify(i, &sig, hashtype, refhash)) + !crtmgr_rsa_verify(i, &sig, hashtype, refhash)) { + if (i->isBlacklisted) + i = NULL; break; + } } mp_clear(&sig); return i; diff --git a/libclamav/crtmgr.h b/libclamav/crtmgr.h index a8d9d9e6c..007db16b8 100644 --- a/libclamav/crtmgr.h +++ b/libclamav/crtmgr.h @@ -43,6 +43,7 @@ typedef struct cli_crt_t { int certSign; int codeSign; int timeSign; + int isBlacklisted; struct cli_crt_t *prev; struct cli_crt_t *next; } cli_crt; From b01b78d190f2030bbb86db3c391d4893e57224ab Mon Sep 17 00:00:00 2001 From: Shawn webb Date: Tue, 23 Oct 2012 16:26:03 -0400 Subject: [PATCH 2/8] Fix checking the revoked certs --- libclamav/asn1.c | 19 ++++++++++++++----- libclamav/crtmgr.c | 2 -- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/libclamav/asn1.c b/libclamav/asn1.c index 1e914d8eb..59aa46cf4 100644 --- a/libclamav/asn1.c +++ b/libclamav/asn1.c @@ -749,6 +749,7 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg SHA1Context ctx; cli_crt *x509; int result; + int isBlacklisted = 0; cli_dbgmsg("in asn1_parse_mscat\n"); @@ -840,12 +841,15 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg cli_dbgmsg("asn1_parse_mscat: %u new certificates collected\n", newcerts.items); while(x509) { cli_crt *parent = crtmgr_verify_crt(cmgr, x509); - if(parent && !(parent->isBlacklisted)) { + if(parent) { + if (parent->isBlacklisted) + isBlacklisted = 1; + x509->codeSign &= parent->codeSign; x509->timeSign &= parent->timeSign; - if(crtmgr_add(cmgr, x509)) - break; - crtmgr_del(&newcerts, x509); + if(crtmgr_add(cmgr, x509)) + break; + crtmgr_del(&newcerts, x509); x509 = newcerts.crts; continue; } @@ -1276,6 +1280,10 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg } cli_dbgmsg("asn1_parse_mscat: catalog succesfully parsed\n"); + if (isBlacklisted) { + cli_dbgmsg("asn1_parse_mscat: executable containes revoked cert.\n"); + return 1; + } return 0; } while(0); @@ -1290,7 +1298,7 @@ int asn1_load_mscat(fmap_t *map, struct cl_engine *engine) { int i; if(asn1_parse_mscat(map, 0, map->len, &engine->cmgr, 0, &c.next, &size)) - return 1; + return 1; if(asn1_expect_objtype(map, c.next, &size, &c, 0x30)) return 1; @@ -1426,6 +1434,7 @@ int asn1_load_mscat(fmap_t *map, struct cl_engine *engine) { } } } + return 0; } diff --git a/libclamav/crtmgr.c b/libclamav/crtmgr.c index f8a16f465..730a0ff80 100644 --- a/libclamav/crtmgr.c +++ b/libclamav/crtmgr.c @@ -317,8 +317,6 @@ cli_crt *crtmgr_verify_pkcs7(crtmgr *m, const uint8_t *issuer, const uint8_t *se if(!memcmp(i->issuer, issuer, sizeof(i->issuer)) && !memcmp(i->serial, serial, sizeof(i->serial)) && !crtmgr_rsa_verify(i, &sig, hashtype, refhash)) { - if (i->isBlacklisted) - i = NULL; break; } } From 56b4f4b0b933860f39d0b83b40d4f62acec93409 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Sat, 27 Oct 2012 14:58:03 -0400 Subject: [PATCH 3/8] Change the cert management code to cache the trusted/revoked root certs in the engine struct --- libclamav/asn1.c | 4 +- libclamav/asn1.h | 2 +- libclamav/crtmgr.c | 122 ++++++++++++++++++++++++++------------------- libclamav/crtmgr.h | 2 +- libclamav/others.c | 4 +- libclamav/pe.c | 2 +- 6 files changed, 78 insertions(+), 58 deletions(-) diff --git a/libclamav/asn1.c b/libclamav/asn1.c index 59aa46cf4..72d85b278 100644 --- a/libclamav/asn1.c +++ b/libclamav/asn1.c @@ -1438,7 +1438,7 @@ int asn1_load_mscat(fmap_t *map, struct cl_engine *engine) { return 0; } -int asn1_check_mscat(fmap_t *map, size_t offset, unsigned int size, uint8_t *computed_sha1) { +int asn1_check_mscat(struct cl_engine *engine, fmap_t *map, size_t offset, unsigned int size, uint8_t *computed_sha1) { unsigned int content_size; struct cli_asn1 c; const void *content; @@ -1447,7 +1447,7 @@ int asn1_check_mscat(fmap_t *map, size_t offset, unsigned int size, uint8_t *com cli_dbgmsg("in asn1_check_mscat (offset: %lu)\n", offset); crtmgr_init(&certs); - if(crtmgr_add_roots(&certs)) { + if(crtmgr_add_roots(engine, &certs)) { crtmgr_free(&certs); return CL_VIRUS; } diff --git a/libclamav/asn1.h b/libclamav/asn1.h index 1cd8f4fbb..03a50bff9 100644 --- a/libclamav/asn1.h +++ b/libclamav/asn1.h @@ -25,6 +25,6 @@ #include "fmap.h" int asn1_load_mscat(fmap_t *map, struct cl_engine *engine); -int asn1_check_mscat(fmap_t *map, size_t offset, unsigned int size, uint8_t *computed_sha1); +int asn1_check_mscat(struct cl_engine *engine, fmap_t *map, size_t offset, unsigned int size, uint8_t *computed_sha1); #endif diff --git a/libclamav/crtmgr.c b/libclamav/crtmgr.c index 730a0ff80..61e8f1d6f 100644 --- a/libclamav/crtmgr.c +++ b/libclamav/crtmgr.c @@ -22,8 +22,8 @@ #include "clamav-config.h" #endif -#include "crtmgr.h" #include "others.h" +#include "crtmgr.h" int cli_crt_init(cli_crt *x509) { int ret; @@ -418,57 +418,77 @@ static const uint8_t VER_MOD[] = "\ static const uint8_t VER_EXP[] = "\x01\x00\x01"; -int crtmgr_add_roots(crtmgr *m) { +int crtmgr_add_roots(struct cl_engine *engine, crtmgr *m) { cli_crt ca; - if(cli_crt_init(&ca)) - return 1; - - do { - memset(ca.issuer, '\xca', sizeof(ca.issuer)); - memcpy(ca.subject, MSCA_SUBJECT, sizeof(ca.subject)); - memset(ca.serial, '\xca', sizeof(ca.serial)); - if(mp_read_unsigned_bin(&ca.n, MSCA_MOD, sizeof(MSCA_MOD)-1) || mp_read_unsigned_bin(&ca.e, MSCA_EXP, sizeof(MSCA_EXP)-1)) { - cli_errmsg("crtmgr_add_roots: failed to read MSCA key\n"); - break; - } - ca.not_before = 0; - ca.not_after = (-1U)>>1; - ca.certSign = 1; - ca.codeSign = 1; - ca.timeSign = 1; - if(crtmgr_add(m, &ca)) - break; - - memcpy(ca.subject, MSA_SUBJECT, sizeof(ca.subject)); - if(mp_read_unsigned_bin(&ca.n, MSA_MOD, sizeof(MSA_MOD)-1) || mp_read_unsigned_bin(&ca.e, MSA_EXP, sizeof(MSA_EXP)-1)) { - cli_errmsg("crtmgr_add_roots: failed to read MSA key\n"); - break; - } - if(crtmgr_add(m, &ca)) - break; - - memcpy(ca.subject, VER_SUBJECT, sizeof(ca.subject)); - if(mp_read_unsigned_bin(&ca.n, VER_MOD, sizeof(VER_MOD)-1) || mp_read_unsigned_bin(&ca.e, VER_EXP, sizeof(VER_EXP)-1)) { - cli_errmsg("crtmgr_add_roots: failed to read VER key\n"); - break; - } - ca.timeSign = 0; - if(crtmgr_add(m, &ca)) - break; - - memcpy(ca.subject, THAW_SUBJECT, sizeof(ca.subject)); - if(mp_read_unsigned_bin(&ca.n, THAW_MOD, sizeof(THAW_MOD)-1) || mp_read_unsigned_bin(&ca.e, THAW_EXP, sizeof(THAW_EXP)-1)) { - cli_errmsg("crtmgr_add_roots: failed to read THAW key\n"); - break; - } - ca.codeSign = 0; - ca.timeSign = 1; - if(crtmgr_add(m, &ca)) - break; - return 0; - } while(0); + cli_crt *crt, *new_crt; + + /* + * Only add trusted (and revoked) root certs once. Copy certs + * from engine's root certs list. + */ + if (m == &(engine->cmgr)) { + do { + if(cli_crt_init(&ca)) + return 1; + + memset(ca.issuer, '\xca', sizeof(ca.issuer)); + memcpy(ca.subject, MSCA_SUBJECT, sizeof(ca.subject)); + memset(ca.serial, '\xca', sizeof(ca.serial)); + if(mp_read_unsigned_bin(&ca.n, MSCA_MOD, sizeof(MSCA_MOD)-1) || mp_read_unsigned_bin(&ca.e, MSCA_EXP, sizeof(MSCA_EXP)-1)) { + cli_errmsg("crtmgr_add_roots: failed to read MSCA key\n"); + break; + } + ca.not_before = 0; + ca.not_after = (-1U)>>1; + ca.certSign = 1; + ca.codeSign = 1; + ca.timeSign = 1; + if(crtmgr_add(m, &ca)) + break; + + memcpy(ca.subject, MSA_SUBJECT, sizeof(ca.subject)); + if(mp_read_unsigned_bin(&ca.n, MSA_MOD, sizeof(MSA_MOD)-1) || mp_read_unsigned_bin(&ca.e, MSA_EXP, sizeof(MSA_EXP)-1)) { + cli_errmsg("crtmgr_add_roots: failed to read MSA key\n"); + break; + } + if(crtmgr_add(m, &ca)) + break; + + memcpy(ca.subject, VER_SUBJECT, sizeof(ca.subject)); + if(mp_read_unsigned_bin(&ca.n, VER_MOD, sizeof(VER_MOD)-1) || mp_read_unsigned_bin(&ca.e, VER_EXP, sizeof(VER_EXP)-1)) { + cli_errmsg("crtmgr_add_roots: failed to read VER key\n"); + break; + } + ca.timeSign = 0; + if(crtmgr_add(m, &ca)) + break; + + memcpy(ca.subject, THAW_SUBJECT, sizeof(ca.subject)); + if(mp_read_unsigned_bin(&ca.n, THAW_MOD, sizeof(THAW_MOD)-1) || mp_read_unsigned_bin(&ca.e, THAW_EXP, sizeof(THAW_EXP)-1)) { + cli_errmsg("crtmgr_add_roots: failed to read THAW key\n"); + break; + } + ca.codeSign = 0; + ca.timeSign = 1; + if(crtmgr_add(m, &ca)) + break; + + return 0; + } while(0); + + cli_crt_clear(&ca); + crtmgr_free(m); + return 1; + } else { + for (crt = engine->cmgr.crts; crt != NULL; crt = crt->next) { + if (crtmgr_add(m, crt)) { + crtmgr_free(m); + return 1; + } + } + + return 0; + } - cli_crt_clear(&ca); - crtmgr_free(m); return 1; } diff --git a/libclamav/crtmgr.h b/libclamav/crtmgr.h index 007db16b8..ad65c68a3 100644 --- a/libclamav/crtmgr.h +++ b/libclamav/crtmgr.h @@ -63,7 +63,7 @@ cli_crt *crtmgr_lookup(crtmgr *m, cli_crt *x509); void crtmgr_del(crtmgr *m, cli_crt *x509); cli_crt *crtmgr_verify_crt(crtmgr *m, cli_crt *x509); cli_crt *crtmgr_verify_pkcs7(crtmgr *m, const uint8_t *issuer, const uint8_t *serial, const void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash, cli_vrfy_type vrfytype); -int crtmgr_add_roots(crtmgr *m); +int crtmgr_add_roots(struct cl_engine *engine, crtmgr *m); #endif diff --git a/libclamav/others.c b/libclamav/others.c index 87ce1ec77..b917df9b0 100644 --- a/libclamav/others.c +++ b/libclamav/others.c @@ -351,8 +351,8 @@ struct cl_engine *cl_engine_new(void) return NULL; } - crtmgr_init(&new->cmgr); - if(crtmgr_add_roots(&new->cmgr)) { + crtmgr_init(&(new->cmgr)); + if(crtmgr_add_roots(new, &(new->cmgr))) { cli_errmsg("cl_engine_new: Can't initialize root certificates\n"); mpool_free(new->mempool, new->dconf); mpool_free(new->mempool, new->root); diff --git a/libclamav/pe.c b/libclamav/pe.c index c11835582..643144864 100644 --- a/libclamav/pe.c +++ b/libclamav/pe.c @@ -2851,5 +2851,5 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { if(hlen < 8) return CL_VIRUS; hlen -= 8; - return asn1_check_mscat(map, at + 8, hlen, authsha1); + return asn1_check_mscat(ctx->engine, map, at + 8, hlen, authsha1); } From d12f1646f209a919f2bf1c1b2ebdf4085adbc59e Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Thu, 1 Nov 2012 10:26:08 -0400 Subject: [PATCH 4/8] bb5638. Parse the new cert db file. --- libclamav/crtmgr.c | 60 ++--------------------- libclamav/readdb.c | 115 +++++++++++++++++++++++++++++++++++++++++++++ libclamav/readdb.h | 1 + 3 files changed, 119 insertions(+), 57 deletions(-) diff --git a/libclamav/crtmgr.c b/libclamav/crtmgr.c index 61e8f1d6f..9114e2a4d 100644 --- a/libclamav/crtmgr.c +++ b/libclamav/crtmgr.c @@ -423,63 +423,9 @@ int crtmgr_add_roots(struct cl_engine *engine, crtmgr *m) { cli_crt *crt, *new_crt; /* - * Only add trusted (and revoked) root certs once. Copy certs - * from engine's root certs list. + * Certs are cached in engine->cmgr. Copy from there. */ - if (m == &(engine->cmgr)) { - do { - if(cli_crt_init(&ca)) - return 1; - - memset(ca.issuer, '\xca', sizeof(ca.issuer)); - memcpy(ca.subject, MSCA_SUBJECT, sizeof(ca.subject)); - memset(ca.serial, '\xca', sizeof(ca.serial)); - if(mp_read_unsigned_bin(&ca.n, MSCA_MOD, sizeof(MSCA_MOD)-1) || mp_read_unsigned_bin(&ca.e, MSCA_EXP, sizeof(MSCA_EXP)-1)) { - cli_errmsg("crtmgr_add_roots: failed to read MSCA key\n"); - break; - } - ca.not_before = 0; - ca.not_after = (-1U)>>1; - ca.certSign = 1; - ca.codeSign = 1; - ca.timeSign = 1; - if(crtmgr_add(m, &ca)) - break; - - memcpy(ca.subject, MSA_SUBJECT, sizeof(ca.subject)); - if(mp_read_unsigned_bin(&ca.n, MSA_MOD, sizeof(MSA_MOD)-1) || mp_read_unsigned_bin(&ca.e, MSA_EXP, sizeof(MSA_EXP)-1)) { - cli_errmsg("crtmgr_add_roots: failed to read MSA key\n"); - break; - } - if(crtmgr_add(m, &ca)) - break; - - memcpy(ca.subject, VER_SUBJECT, sizeof(ca.subject)); - if(mp_read_unsigned_bin(&ca.n, VER_MOD, sizeof(VER_MOD)-1) || mp_read_unsigned_bin(&ca.e, VER_EXP, sizeof(VER_EXP)-1)) { - cli_errmsg("crtmgr_add_roots: failed to read VER key\n"); - break; - } - ca.timeSign = 0; - if(crtmgr_add(m, &ca)) - break; - - memcpy(ca.subject, THAW_SUBJECT, sizeof(ca.subject)); - if(mp_read_unsigned_bin(&ca.n, THAW_MOD, sizeof(THAW_MOD)-1) || mp_read_unsigned_bin(&ca.e, THAW_EXP, sizeof(THAW_EXP)-1)) { - cli_errmsg("crtmgr_add_roots: failed to read THAW key\n"); - break; - } - ca.codeSign = 0; - ca.timeSign = 1; - if(crtmgr_add(m, &ca)) - break; - - return 0; - } while(0); - - cli_crt_clear(&ca); - crtmgr_free(m); - return 1; - } else { + if (m != &(engine->cmgr)) { for (crt = engine->cmgr.crts; crt != NULL; crt = crt->next) { if (crtmgr_add(m, crt)) { crtmgr_free(m); @@ -490,5 +436,5 @@ int crtmgr_add_roots(struct cl_engine *engine, crtmgr *m) { return 0; } - return 1; + return 0; } diff --git a/libclamav/readdb.c b/libclamav/readdb.c index d0f769c39..a85d22d85 100644 --- a/libclamav/readdb.c +++ b/libclamav/readdb.c @@ -2362,6 +2362,118 @@ static int cli_loadcdb(FILE *fs, struct cl_engine *engine, unsigned int *signo, return CL_SUCCESS; } +/* + * Name;trusted:subject:pubkey;exponent;comment[;minFL;maxFL] + * Name and comment are ignored. They're just for the end user. + */ +#define CRT_TOKENS 11 +static int cli_loadcrt(FILE *fs, struct cl_engine *engine, struct cli_dbio *dbio) { + char buffer[FILEBUFF]; + char *tokens[CRT_TOKENS+1]; + size_t line=0, tokens_count, i, j; + cli_crt ca; + int ret=CL_SUCCESS; + char *subject, *pubkey, *exponent; + const uint8_t exp[] = "\x01\x00\x01"; + char c; + + cli_crt_init(&ca); + memset(ca.issuer, '\xca', sizeof(ca.issuer)); + memset(ca.serial, '\xca', sizeof(ca.serial)); + + while (cli_dbgets(buffer, FILEBUFF, fs, dbio)) { + line++; + + if (buffer[0] == '#') + continue; + + cli_chomp(buffer); + if (!strlen(buffer)) + continue; + + tokens_count = cli_strtokenize(buffer, ';', CRT_TOKENS + 1, (const char **)tokens); + if (tokens_count > CRT_TOKENS || tokens_count < CRT_TOKENS - 2) { + cli_errmsg("cli_loadcrt: line %u: Invalid number of tokens: %u\n", line, tokens_count); + ret = CL_EMALFDB; + goto end; + } + + switch (tokens[1][0]) { + case '1': + ca.isBlacklisted = 0; + break; + case '0': + ca.isBlacklisted = 1; + break; + default: + cli_errmsg("cli_loadcrt: line %u: Invalid trust specification. Expected 0 or 1\n", line); + ret = CL_EMALFDB; + goto end; + } + + subject = cli_hex2str(tokens[2]); + pubkey = cli_hex2str(tokens[3]); + + if (!subject) { + cli_errmsg("cli_loadcrt: line %u: Cannot convert subject to binary string\n", line); + ret = CL_EMALFDB; + goto end; + } + if (!pubkey) { + cli_errmsg("cli_loadcrt: line %u: Cannot convert public key to binary string\n", line); + ret = CL_EMALFDB; + goto end; + } + + memcpy(ca.subject, subject, sizeof(ca.subject)); + if (mp_read_unsigned_bin(&(ca.n), pubkey, strlen(tokens[3])/2) || mp_read_unsigned_bin(&(ca.e), exp, sizeof(exp)-1)) { + cli_errmsg("cli_loadcrt: line %u: Cannot convert exponent to binary data\n", line); + ret = CL_EMALFDB; + goto end; + } + + cli_dbgmsg("sizeof(exp): %u. sizeof(exp)-1: %u\n", sizeof(exp), sizeof(exp)-1); + + switch (tokens[5][0]) { + case '1': + ca.codeSign = 1; + break; + case '0': + ca.codeSign = 0; + break; + default: + cli_errmsg("cli_loadcrt: line %u: Invalid code sign specification. Expected 0 or 1\n", line); + ret = CL_EMALFDB; + goto end; + } + + switch (tokens[6][0]) { + case '1': + ca.timeSign = 1; + break; + case '0': + ca.timeSign = 0; + break; + default: + cli_errmsg("cli_loadcrt: line %u: Invalid time sign specification. Expected 0 or 1\n", line); + ret = CL_EMALFDB; + goto end; + } + + if (strlen(tokens[7])) + ca.not_before = atoi(tokens[7]); + ca.not_after = (-1U)>>1; + ca.certSign = 1; + + crtmgr_add(&(engine->cmgr), &ca); + } + +end: + cli_dbgmsg("Number of certs: %d\n", engine->cmgr.items); + cli_crt_clear(&ca); + return ret; +} + static int cli_loadmscat(FILE *fs, const char *dbname, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio) { fmap_t *map; @@ -2422,6 +2534,9 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo } else if(cli_strbcasestr(dbname, ".cud")) { ret = cli_cvdload(fs, engine, signo, options, 2, filename, 0); + } else if (cli_strbcasestr(dbname, ".crt")) { + ret = cli_loadcrt(fs, engine, dbio); + } else if(cli_strbcasestr(dbname, ".hdb") || cli_strbcasestr(dbname, ".hsb")) { ret = cli_loadhash(fs, engine, signo, MD5_HDB, options, dbio, dbname); } else if(cli_strbcasestr(dbname, ".hdu") || cli_strbcasestr(dbname, ".hsu")) { diff --git a/libclamav/readdb.h b/libclamav/readdb.h index b836d0287..94916a01f 100644 --- a/libclamav/readdb.h +++ b/libclamav/readdb.h @@ -60,6 +60,7 @@ cli_strbcasestr(ext, ".cud") || \ cli_strbcasestr(ext, ".cdb") || \ cli_strbcasestr(ext, ".cat") || \ + cli_strbcasestr(ext, ".crt") || \ cli_strbcasestr(ext, ".idb") \ ) From ee07fcd640cd82ded803de189b191507863f0342 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Thu, 1 Nov 2012 10:51:57 -0400 Subject: [PATCH 5/8] bb5638. Parse minFL and maxFL --- libclamav/readdb.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/libclamav/readdb.c b/libclamav/readdb.c index a85d22d85..05b2a6e68 100644 --- a/libclamav/readdb.c +++ b/libclamav/readdb.c @@ -2363,8 +2363,9 @@ static int cli_loadcdb(FILE *fs, struct cl_engine *engine, unsigned int *signo, } /* - * Name;trusted:subject:pubkey;exponent;comment[;minFL;maxFL] + * name;trusted;subject;pubkey;exp;codesign;timesign;notbefore;comment[;minFL[;maxFL]] * Name and comment are ignored. They're just for the end user. + * Exponent is ignored for now and hardcoded to \x01\x00\x01. */ #define CRT_TOKENS 11 static int cli_loadcrt(FILE *fs, struct cl_engine *engine, struct cli_dbio *dbio) { @@ -2398,6 +2399,31 @@ static int cli_loadcrt(FILE *fs, struct cl_engine *engine, struct cli_dbio *dbio goto end; } + if (tokens_count > CRT_TOKENS - 2) { + if (!cli_isnumber(tokens[CRT_TOKENS-1])) { + cli_errmsg("cli_loadcrt: line %u: Invalid minimum feature level\n", line); + ret = CL_EMALFDB; + goto end; + } + if ((unsigned int)atoi(tokens[CRT_TOKENS-1]) > cl_retflevel()) { + cli_dbgmsg("cli_loadcrt: Cert %s not loaded (required f-level: %u)\n", tokens[0], cl_retflevel()); + continue; + } + + if (tokens_count == CRT_TOKENS) { + if (!cli_isnumber(tokens[CRT_TOKENS])) { + cli_errmsg("cli_loadcrt: line %u: Invalid maximum feature level\n", line); + ret = CL_EMALFDB; + goto end; + } + + if ((unsigned int)atoi(tokens[CRT_TOKENS]) < cl_retflevel) { + cli_dbgmsg("cli_ladcrt: Cert %s not loaded (maximum f-level: %s)\n", tokens[0], tokens[CRT_TOKENS]); + continue; + } + } + } + switch (tokens[1][0]) { case '1': ca.isBlacklisted = 0; @@ -2432,8 +2458,6 @@ static int cli_loadcrt(FILE *fs, struct cl_engine *engine, struct cli_dbio *dbio goto end; } - cli_dbgmsg("sizeof(exp): %u. sizeof(exp)-1: %u\n", sizeof(exp), sizeof(exp)-1); - switch (tokens[5][0]) { case '1': ca.codeSign = 1; From 2c2e89e107e198b78078c7bd81e7cb878b300b85 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Thu, 1 Nov 2012 11:35:42 -0400 Subject: [PATCH 6/8] bb5638. Check if cert already exists in cache. --- libclamav/crtmgr.c | 13 +++++++++++++ libclamav/readdb.c | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libclamav/crtmgr.c b/libclamav/crtmgr.c index 9114e2a4d..f0fb6c901 100644 --- a/libclamav/crtmgr.c +++ b/libclamav/crtmgr.c @@ -88,8 +88,21 @@ int crtmgr_add(crtmgr *m, cli_crt *x509) { i->certSign |= x509->certSign; i->codeSign |= x509->codeSign; i->timeSign |= x509->timeSign; + return 0; } + + /* If certs match, we're likely just revoking it */ + if (!memcmp(x509->subject, i->subject, sizeof(x509->subject)) && + !memcmp(x509->issuer, i->issuer, sizeof(x509->issuer)) && + !memcmp(x509->serial, i->serial, sizeof(x509->serial)) && + !mp_cmp(&x509->n, &i->n) && + !mp_cmp(&x509->e, &i->e)) { + if (i->isBlacklisted != x509->isBlacklisted) + i->isBlacklisted = x509->isBlacklisted; + + return 0; + } } i = cli_malloc(sizeof(*i)); diff --git a/libclamav/readdb.c b/libclamav/readdb.c index 05b2a6e68..ae46a33d1 100644 --- a/libclamav/readdb.c +++ b/libclamav/readdb.c @@ -2417,7 +2417,7 @@ static int cli_loadcrt(FILE *fs, struct cl_engine *engine, struct cli_dbio *dbio goto end; } - if ((unsigned int)atoi(tokens[CRT_TOKENS]) < cl_retflevel) { + if ((unsigned int)atoi(tokens[CRT_TOKENS]) < cl_retflevel()) { cli_dbgmsg("cli_ladcrt: Cert %s not loaded (maximum f-level: %s)\n", tokens[0], tokens[CRT_TOKENS]); continue; } From 76bca4c8c8e3ddc5fefe21df5d552ddf5a5b118f Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Thu, 1 Nov 2012 11:51:21 -0400 Subject: [PATCH 7/8] bb5638. Add documentation for new certs database. --- docs/signatures.tex | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/signatures.tex b/docs/signatures.tex index 6b0b64a85..9b7635105 100644 --- a/docs/signatures.tex +++ b/docs/signatures.tex @@ -579,6 +579,32 @@ FileDescription Entertainment Pack FreeCell Game \end{verbatim} + \subsection{Trusted and Revoked Certificates} + Clamav 0.98 checks signed PE files for certificates and verifies each + certificate in the chain against a database of trusted and revoked + certificates. The sinagure format is +\begin{verbatim} +Name;Trusted;Subject;Pubkey;Exponent;CodeSign;TimeSign;NotBefore;Comment +[;minFL[;maxFL]] +\end{verbatim} + where the corresponding fields are: + \begin{itemize} + \item \verb+Name:+ name of the entry + \item \verb+Trusted:+ bit field, specifying whether the cert is + trusted. 1 for trusted. 0 for revoked + \item \verb+Subject:+ sha1 of the Subject field in hex + \item \verb+Pubkey:+ the public key in hex + \item \verb+Exponent:+ the exponent in hex. Currently ignored and + hardcoded to 010001 (in hex) + \item \verb+CodeSign:+ bit field, specifying whether this cert + can sign code. 1 for true, 0 for false + \item \verb+TimeSign:+ bit field. 1 for true, 0 for false + \item \verb+NotBefore:+ integer, cert should not be added before + this variable. Defaults to 0 if left empty + \item \verb+Comment:+ comments for this entry + \end{itemize} + The signatures for certs are stored inside \verb+.crt+ files. + \subsection{Signatures based on container metadata} ClamAV 0.96 allows creating generic signatures matching files stored inside different container types which meet specific conditions. From 32056014502265a2709a613c8d14d2e0e8abf0ea Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Thu, 1 Nov 2012 11:54:21 -0400 Subject: [PATCH 8/8] bb5638. Quiet compiler warning --- libclamav/pe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libclamav/pe.c b/libclamav/pe.c index 643144864..fb01ec6ea 100644 --- a/libclamav/pe.c +++ b/libclamav/pe.c @@ -2851,5 +2851,5 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) { if(hlen < 8) return CL_VIRUS; hlen -= 8; - return asn1_check_mscat(ctx->engine, map, at + 8, hlen, authsha1); + return asn1_check_mscat((struct cl_engine *)(ctx->engine), map, at + 8, hlen, authsha1); }