Skip to content

Commit b5665f3

Browse files
committed
Sigtool: fix --diff bugs and add support for '_' in cvd name
Sigtool's `--diff CVD_OLD CVD_NEW` feature will fail with preclass_tcfa (or any other CVD with an underscore). Apparently '_' is not a supported character in that code.   While debugging this, I found some other issues: * The call to verify the `.script` created with the `--diff` feature fails since adding the .sign digital signature verification code, because I called it wrong. We didn't notice because there are no automated tests for this feature. * The --diff feature assumes you're in the same directory as the CVD files and that it is a relative path.  * The --diff feature will change directories to a temp directory to verify the diff and then fail to apply the script because it has a relative path and now in a totally different directory I don't know how (2) or (3) ever worked right. One require absolute paths, while the other didn't provide a buffer big enough for absolute paths. So confused! This commit should make it so relative or absolute paths are fine for the CVD's and the cvd name may now include underscores. CLAM-2815
1 parent dd03336 commit b5665f3

4 files changed

Lines changed: 202 additions & 65 deletions

File tree

libclamav/others.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -587,9 +587,7 @@ struct cl_engine *cl_engine_new(void)
587587

588588
// Check if the CVD_CERTS_DIR environment variable is set
589589
cvdcertsdir = getenv("CVD_CERTS_DIR");
590-
if (NULL != cvdcertsdir) {
591-
new->certs_directory = CLI_MPOOL_STRDUP(new->mempool, cvdcertsdir);
592-
} else {
590+
if (NULL == cvdcertsdir) {
593591
#ifdef _WIN32
594592
// On Windows, CERTSDIR is NOT defined in clamav-config.h.
595593
// So instead we'll use the certs directory next to the module file.
@@ -611,11 +609,12 @@ struct cl_engine *cl_engine_new(void)
611609
// set the certs directory to be the module directory + certs
612610
snprintf(certs_directory, sizeof(certs_directory), "%s\\certs", dir);
613611

614-
new->certs_directory = CLI_MPOOL_STRDUP(new->mempool, certs_directory);
612+
cvdcertsdir = certs_directory;
615613
#else
616-
new->certs_directory = CLI_MPOOL_STRDUP(new->mempool, CERTSDIR);
614+
cvdcertsdir = CERTSDIR;
617615
#endif
618616
}
617+
new->certs_directory = CLI_MPOOL_STRDUP(new->mempool, cvdcertsdir);
619618

620619
status = CL_SUCCESS;
621620
cli_dbgmsg("Initialized %s engine\n", cl_retver());

libclamav_rust/src/cdiff.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ impl<'a> UnlinkOp<'a> {
326326

327327
if !db_name
328328
.chars()
329-
.all(|x: char| x.is_alphanumeric() || x == '.')
329+
.all(|x: char| x.is_alphanumeric() || x == '.' || x == '_')
330330
{
331331
// DB Name contains invalid characters.
332332
return Err(InputError::InvalidDBNameForbiddenCharacters(
@@ -601,7 +601,10 @@ pub unsafe extern "C" fn _cdiff_apply(
601601
Err(e) => {
602602
return ffi_error!(
603603
err = err,
604-
Error::CannotVerify(format!("Invalid cdiff file path: {}", e))
604+
Error::CannotVerify(format!(
605+
"Invalid cdiff file path '{}': {}",
606+
cdiff_file_path_str, e
607+
))
605608
);
606609
}
607610
};
@@ -758,7 +761,7 @@ fn cmd_open(ctx: &mut Context, db_name: Option<&[u8]>) -> Result<(), InputError>
758761

759762
if !db_name
760763
.chars()
761-
.all(|x: char| x.is_alphanumeric() || x == '.')
764+
.all(|x: char| x.is_alphanumeric() || x == '.' || x == '_')
762765
{
763766
// DB Name contains invalid characters.
764767
return Err(InputError::InvalidDBNameForbiddenCharacters(

sigtool/sigtool.c

Lines changed: 95 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@
7070

7171
#define MAX_DEL_LOOKAHEAD 5000
7272

73+
// global variable for the absolute path of the --cvdcertsdir option
74+
char *g_cvdcertsdir = NULL;
75+
7376
// struct s_info info;
7477
short recursion = 0, bell = 0;
7578
short printinfected = 0, printclean = 1;
@@ -1069,8 +1072,6 @@ static int verify(const struct optstruct *opts)
10691072
char *target = NULL;
10701073
char *sign_file_name = NULL;
10711074

1072-
char *cvdcertsdir = NULL;
1073-
10741075
char *signer_name = NULL;
10751076
bool verify_result = false;
10761077
FFIError *verify_file_error = NULL;
@@ -1081,8 +1082,9 @@ static int verify(const struct optstruct *opts)
10811082
target = optget(opts, "verify")->strarg;
10821083
if (NULL == target) {
10831084
mprintf(LOGG_ERROR, "verify: No target file specified.\n");
1084-
mprintf(LOGG_ERROR, "To verify a file signed with sigtool, you must specify a target file. You may also override the default certificates directory using --cvdcertsdir.\n");
1085-
mprintf(LOGG_ERROR, "For example: sigtool --verify myfile.cvd --cvdcertsdir /path/to/certs/\n");
1085+
mprintf(LOGG_ERROR, "To verify a file signed with sigtool, you must specify a target file. "
1086+
"You may also override the default certificates directory using --cvdcertsdir. "
1087+
"For example: sigtool --verify myfile.cvd --cvdcertsdir /path/to/certs/\n");
10861088
goto done;
10871089
}
10881090

@@ -1092,18 +1094,7 @@ static int verify(const struct optstruct *opts)
10921094
goto done;
10931095
}
10941096

1095-
cvdcertsdir = optget(opts, "cvdcertsdir")->strarg;
1096-
if (NULL == cvdcertsdir) {
1097-
// Check if the CVD_CERTS_DIR environment variable is set
1098-
cvdcertsdir = getenv("CVD_CERTS_DIR");
1099-
1100-
// If not, use the default value
1101-
if (NULL == cvdcertsdir) {
1102-
cvdcertsdir = OPT_CERTSDIR;
1103-
}
1104-
}
1105-
1106-
if (!codesign_verifier_new(cvdcertsdir, &verifier, &new_verifier_error)) {
1097+
if (!codesign_verifier_new(g_cvdcertsdir, &verifier, &new_verifier_error)) {
11071098
mprintf(LOGG_ERROR, "verify: Failed to create verifier: %s\n", ffierror_fmt(new_verifier_error));
11081099
goto done;
11091100
}
@@ -1194,6 +1185,14 @@ static int build(const struct optstruct *opts)
11941185
return 50;
11951186
}
11961187

1188+
if (NULL != g_cvdcertsdir) {
1189+
if ((ret = cl_engine_set_str(engine, CL_ENGINE_CVDCERTSDIR, g_cvdcertsdir))) {
1190+
logg(LOGG_ERROR, "cli_engine_set_str(CL_ENGINE_CVDCERTSDIR) failed: %s\n", cl_strerror(ret));
1191+
cl_engine_free(engine);
1192+
return -1;
1193+
}
1194+
}
1195+
11971196
if ((ret = cl_load(".", engine, &sigs, CL_DB_STDOPT | CL_DB_PUA | CL_DB_SIGNED))) {
11981197
mprintf(LOGG_ERROR, "build: Can't load database: %s\n", cl_strerror(ret));
11991198
cl_engine_free(engine);
@@ -1531,9 +1530,6 @@ static int build(const struct optstruct *opts)
15311530

15321531
mprintf(LOGG_INFO, "Created %s\n", newcvd);
15331532

1534-
if (optget(opts, "unsigned")->enabled)
1535-
return 0;
1536-
15371533
if (!oldcvd || optget(opts, "no-cdiff")->enabled) {
15381534
mprintf(LOGG_INFO, "Skipping .cdiff creation\n");
15391535
return 0;
@@ -1590,12 +1586,16 @@ static int build(const struct optstruct *opts)
15901586
} else {
15911587
mprintf(LOGG_ERROR, "Generated file is incorrect, renamed to %s\n", broken);
15921588
}
1589+
return ret;
1590+
}
1591+
1592+
if (optget(opts, "unsigned")->enabled)
1593+
return 0;
1594+
1595+
if (!script2cdiff(patch, builder, optget(opts, "server")->strarg)) {
1596+
ret = -1;
15931597
} else {
1594-
if (!script2cdiff(patch, builder, optget(opts, "server")->strarg)) {
1595-
ret = -1;
1596-
} else {
1597-
ret = 0;
1598-
}
1598+
ret = 0;
15991599
}
16001600

16011601
return ret;
@@ -1604,8 +1604,7 @@ static int build(const struct optstruct *opts)
16041604
static int unpack(const struct optstruct *opts)
16051605
{
16061606
char name[512], *dbdir;
1607-
const char *localdbdir = NULL;
1608-
const char *certs_directory = NULL;
1607+
const char *localdbdir = NULL;
16091608

16101609
if (optget(opts, "datadir")->active)
16111610
localdbdir = optget(opts, "datadir")->strarg;
@@ -1628,18 +1627,7 @@ static int unpack(const struct optstruct *opts)
16281627
name[sizeof(name) - 1] = '\0';
16291628
}
16301629

1631-
certs_directory = optget(opts, "cvdcertsdir")->strarg;
1632-
if (NULL == certs_directory) {
1633-
// Check if the CVD_CERTS_DIR environment variable is set
1634-
certs_directory = getenv("CVD_CERTS_DIR");
1635-
1636-
// If not, use the default value
1637-
if (NULL == certs_directory) {
1638-
certs_directory = OPT_CERTSDIR;
1639-
}
1640-
}
1641-
1642-
if (cl_cvdverify_ex(name, certs_directory) != CL_SUCCESS) {
1630+
if (cl_cvdverify_ex(name, g_cvdcertsdir) != CL_SUCCESS) {
16431631
mprintf(LOGG_ERROR, "unpack: %s is not a valid CVD\n", name);
16441632
return -1;
16451633
}
@@ -2265,8 +2253,8 @@ static int rundiff(const struct optstruct *opts)
22652253
int ret;
22662254
unsigned short mode;
22672255
const char *diff;
2268-
FFIError *cdiff_apply_error = NULL;
2269-
char *cvdcertsdir = NULL;
2256+
FFIError *cdiff_apply_error = NULL;
2257+
22702258
void *verifier = NULL;
22712259
FFIError *new_verifier_error = NULL;
22722260

@@ -2280,18 +2268,7 @@ static int rundiff(const struct optstruct *opts)
22802268
return -1;
22812269
}
22822270

2283-
cvdcertsdir = optget(opts, "cvdcertsdir")->strarg;
2284-
if (NULL == cvdcertsdir) {
2285-
// Check if the CVD_CERTS_DIR environment variable is set
2286-
cvdcertsdir = getenv("CVD_CERTS_DIR");
2287-
2288-
// If not, use the default value
2289-
if (NULL == cvdcertsdir) {
2290-
cvdcertsdir = OPT_CERTSDIR;
2291-
}
2292-
}
2293-
2294-
if (!codesign_verifier_new(cvdcertsdir, &verifier, &new_verifier_error)) {
2271+
if (!codesign_verifier_new(g_cvdcertsdir, &verifier, &new_verifier_error)) {
22952272
cli_errmsg("rundiff: Failed to create a new code-signature verifier: %s\n", ffierror_fmt(new_verifier_error));
22962273
ret = -1;
22972274
goto done;
@@ -2577,8 +2554,15 @@ static int verifydiff(const struct optstruct *opts, const char *diff, const char
25772554
int ret = -1;
25782555
unsigned short mode;
25792556
FFIError *cdiff_apply_error = NULL;
2580-
char *cvdcertsdir = NULL;
2581-
bool created_temp_dir = false;
2557+
2558+
void *verifier = NULL;
2559+
FFIError *new_verifier_error = NULL;
2560+
2561+
bool created_temp_dir = false;
2562+
2563+
cl_error_t cl_ret;
2564+
2565+
char *real_diff = NULL;
25822566

25832567
if (strstr(diff, ".cdiff")) {
25842568
mode = 1;
@@ -2611,17 +2595,31 @@ static int verifydiff(const struct optstruct *opts, const char *diff, const char
26112595
goto done;
26122596
}
26132597

2598+
cl_ret = cli_realpath((const char *)diff, &real_diff);
2599+
if (CL_SUCCESS != cl_ret) {
2600+
mprintf(LOGG_ERROR, "verifydiff: Failed to determine real filename of %s: %s\n", diff, cl_strerror(cl_ret));
2601+
goto done;
2602+
}
2603+
2604+
diff = real_diff;
2605+
26142606
if (chdir(tempdir) == -1) {
26152607
mprintf(LOGG_ERROR, "verifydiff: Can't chdir to %s\n", tempdir);
26162608
goto done;
26172609
}
26182610

2611+
if (!codesign_verifier_new(g_cvdcertsdir, &verifier, &new_verifier_error)) {
2612+
cli_errmsg("verifydiff: Failed to create a new code-signature verifier: %s\n", ffierror_fmt(new_verifier_error));
2613+
ret = -1;
2614+
goto done;
2615+
}
2616+
26192617
if (!cdiff_apply(
26202618
diff,
2621-
cvdcertsdir,
2619+
verifier,
26222620
mode,
26232621
&cdiff_apply_error)) {
2624-
mprintf(LOGG_ERROR, "verifydiff: Can't apply %s\n", diff);
2622+
mprintf(LOGG_ERROR, "verifydiff: Can't apply %s: %s\n", diff, ffierror_fmt(cdiff_apply_error));
26252623
if (chdir(cwd) == -1) {
26262624
mprintf(LOGG_WARNING, "verifydiff: Can't chdir to %s\n", cwd);
26272625
}
@@ -2652,6 +2650,15 @@ static int verifydiff(const struct optstruct *opts, const char *diff, const char
26522650
if (NULL != cdiff_apply_error) {
26532651
ffierror_free(cdiff_apply_error);
26542652
}
2653+
if (NULL != real_diff) {
2654+
free(real_diff);
2655+
}
2656+
if (NULL != verifier) {
2657+
codesign_verifier_free(verifier);
2658+
}
2659+
if (NULL != new_verifier_error) {
2660+
ffierror_free(new_verifier_error);
2661+
}
26552662

26562663
return ret;
26572664
}
@@ -3777,7 +3784,7 @@ static int diffdirs(const char *old, const char *new, const char *patch)
37773784

37783785
static int makediff(const struct optstruct *opts)
37793786
{
3780-
char *odir, *ndir, name[32], broken[39], dbname[32];
3787+
char *odir, *ndir, name[PATH_MAX], broken[PATH_MAX + 8], dbname[PATH_MAX];
37813788
struct cl_cvd *cvd;
37823789
unsigned int oldver, newver;
37833790
int ret;
@@ -4122,6 +4129,9 @@ int main(int argc, char **argv)
41224129
struct optstruct *opts;
41234130
STATBUF sb;
41244131

4132+
const char *cvdcertsdir = NULL;
4133+
STATBUF statbuf;
4134+
41254135
if (check_flevel())
41264136
exit(1);
41274137

@@ -4164,6 +4174,34 @@ int main(int argc, char **argv)
41644174
return 0;
41654175
}
41664176

4177+
// Evaluate the absolute path for cvdcertsdir in case we change directories later.
4178+
cvdcertsdir = optget(opts, "cvdcertsdir")->strarg;
4179+
if (NULL == cvdcertsdir) {
4180+
// If not set, check the environment variable.
4181+
cvdcertsdir = getenv("CVD_CERTS_DIR");
4182+
if (NULL == cvdcertsdir) {
4183+
// If not set, use the default path.
4184+
cvdcertsdir = OPT_CERTSDIR;
4185+
}
4186+
}
4187+
4188+
// Command line option must override the engine defaults
4189+
// (which would've used the env var or hardcoded path)
4190+
if (LSTAT(cvdcertsdir, &statbuf) == -1) {
4191+
logg(LOGG_ERROR,
4192+
"ClamAV CA certificates directory is missing: %s"
4193+
" - It should have been provided as a part of installation.\n",
4194+
cvdcertsdir);
4195+
return -1;
4196+
}
4197+
4198+
// Convert certs dir to real path.
4199+
ret = cli_realpath((const char *)cvdcertsdir, &g_cvdcertsdir);
4200+
if (CL_SUCCESS != ret) {
4201+
logg(LOGG_ERROR, "Failed to determine absolute path of '%s' for the CVD certs directory.\n", cvdcertsdir);
4202+
return -1;
4203+
}
4204+
41674205
if (optget(opts, "hex-dump")->enabled)
41684206
ret = hexdump();
41694207
else if (optget(opts, "md5")->enabled)

0 commit comments

Comments
 (0)