Skip to content

Commit

Permalink
Code review fixes
Browse files Browse the repository at this point in the history
Fixup sigtool manpage.

Other stuff.
  • Loading branch information
micahsnyder committed Dec 16, 2024
1 parent e1b4f9e commit 99052ef
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 46 deletions.
2 changes: 1 addition & 1 deletion CMakeOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ else()
"share/clamav" CACHE STRING
"Database directory.")
set(CERTS_DIRECTORY
"etc/certs" CACHE STRING
"${APP_CONFIG_DIRECTORY}/certs" CACHE STRING
"ClamAV CA certificates directory.")
endif()

Expand Down
1 change: 1 addition & 0 deletions common/optparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ const struct clam_option __clam_options[] = {
{NULL, "verify", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", ""},
{NULL, "key", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", ""},
{NULL, "cert", 0, CLOPT_TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_SIGTOOL, "", ""},
{NULL, "append", 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", ""},
{NULL, "max-bad-sigs", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 3000, NULL, 0, OPT_SIGTOOL, "Maximum number of mismatched signatures when building a CVD. Zero disables this limit.", "3000"},
{NULL, "flevel", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, CL_FLEVEL, NULL, 0, OPT_SIGTOOL, "Feature level to put in the CVD", ""},
{NULL, "cvd-version", 0, CLOPT_TYPE_NUMBER, MATCH_NUMBER, 0, NULL, 0, OPT_SIGTOOL, "Version number of the CVD to build", ""},
Expand Down
112 changes: 89 additions & 23 deletions docs/man/sigtool.1.in
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
.TH "sigtool" "1" "February 12, 2007" "ClamAV @VERSION@" "Clam AntiVirus"

.SH "NAME"
.LP
sigtool \- signature and database management tool

.SH "SYNOPSIS"
.LP
sigtool [options]

.SH "DESCRIPTION"
.LP
sigtool can be used to generate MD5 checksums, convert data into hexadecimal format, list virus signatures and build/unpack/test/verify CVD databases and update scripts.
.SH "OPTIONS"
.LP

.SH "COMMON OPTIONS"
.LP
.TP
\fB\-h, \-\-help\fR
Output help information and exit.
Expand All @@ -19,13 +22,40 @@ Output help information and exit.
Print version number and exit.
.TP
\fB\-\-quiet\fR
Be quiet \- output only error messages.
Be quiet, output only error messages.
.TP
\fB\-\-debug\fR
Enable debug messages
.TP
\fB\-\-stdout\fR
Write all messages to stdout.
.TP
\fB\-\-hex\-dump\fR
Read data from stdin and write hex string to stdout.
\fB\-\-tempdir=DIRECTORY\fR
Create temporary files in DIRECTORY. Directory must be writable for the user running sigtool.
.TP
\fB\-\-leave\-temps\fR
Do not remove temporary files.
.TP
\fB\-\-datadir=DIR\fR
Use DIR as the default database directory for all operations.

.SH "COMMANDS FOR WORKING WITH SIGNATURES"
.LP
.TP
\fB\-l[FILE], \-\-list\-sigs[=FILE]\fR
List all signature names from the local database directory (default) or from FILE.
.TP
\fB\-fREGEX, \-\-find\-sigs=REGEX\fR
Find and display signatures from the local database directory which match the given REGEX. The whole signature body (name, hex string, etc.) is checked.
.TP
\fB\-\-decode\-sigs=REGEX\fR
Decode signatures read from the standard input (eg. piped from \-\-find\-sigs)
.TP
\fB\-\-test\-sigs=DATABASE TARGET_FILE\fR
Test all signatures from DATABASE against TARGET_FILE. This option will only give valid results if the target file is the final one (after unpacking, normalization, etc.) for which the signatures were created.

.SH "COMMANDS TO GENERATE SIGNATURES"
.LP
.TP
\fB\-\-md5 [FILES]\fR
Generate MD5 checksum from stdin or MD5 sigs for FILES.
Expand All @@ -37,23 +67,48 @@ Generate SHA1 checksum from stdin or SHA1 sigs for FILES.
Generate SHA256 checksum from stdin or SHA256 sigs for FILES.
.TP
\fB\-\-mdb [FILES]\fR
Generate .mdb signatures for FILES.
Generate .mdb (PE section hash) signatures for FILES.
.TP
\fB\-\-imp [FILES]\fR
Generate .imp (PE import address table hash) signatures for FILES.
.TP
\fB\-\-fuzzy\-img [FILES]\fR
Generate image fuzzy hash for each file.

.SH "COMMANDS TO NORMALIZE FILES"
.LP
.TP
\fB\-\-html\-normalise=FILE\fR
Create normalised HTML files comment.html, nocomment.html, and script.html in current working directory.
.TP
\fB\-\-ascii\-normalise=FILE\fR
Create normalised text file from ascii source.
.TP
\fB\-\-utf16\-decode=FILE\fR
Decode UTF16 encoded data.

.SH "COMMANDS FOR FILE ANALYSIS"
.LP
.TP
\fB\-\-vba=FILE\fR
Extract VBA/Word6 macros from given MS Office document.
.TP
\fB\-\-vba\-hex=FILE\fR
Extract Word6 macros from given MS Office document and display the corresponding hex values.
.TP
\fB\-\-print\-certs=FILE\fR
Print Authenticode details from a PE file.
.TP
\fB\-\-hex\-dump\fR
Read data from stdin and write hex string to stdout.

.SH "COMMANDS FOR WORKING WITH CVDS"
.LP
.TP
\fB\-i, \-\-info\fR
Print a CVD information and verify MD5 and a digital signature.
.TP
.TP
\fB\-\-build=FILE, \-b FILE\fR
Build a CVD file. \-s, \-\-server is required for signed virus databases(.cvd), or, \-\-unsigned for unsigned(.cud).
.TP
Expand All @@ -73,20 +128,25 @@ NOTE: If a CVD is found in the \-\-datadir its version+1 is used and this value
\fB\-\-no\-cdiff\fR
Don't create a .cdiff file when building a new database file.
.TP
\fB\-\-hybrid\fR
Create a hybrid (standard and bytecode) database file.
.TP
\fB\-\-unsigned\fR
Create a database file without digital signatures (.cud).
.TP
\fB\-\-server\fR
\fB\-\-server=ADDR\fR
ClamAV Signing Service address (for virus database maintainers only).
.TP
\fB\-\-datadir=DIR\fR
Use DIR as the default database directory for all operations.
.TP
\fB\-\-unpack=FILE, \-u FILE\fR
Unpack FILE (CVD) to a current directory.
.TP
.TP
\fB\-\-unpack\-current\fR
Unpack a local CVD file (main or daily) to current directory.

.SH "COMMANDS FOR WORKING WITH CDIFF PATCH FILES"
.LP
.TP
\fB\-\-diff=OLD NEW, \-d OLD NEW\fR
Create a diff file for OLD and NEW CVDs/INCDIRs.
Expand All @@ -99,27 +159,33 @@ Execute update script FILE in current directory.
.TP
\fB\-\-verify\-cdiff=FILE, \-r FILE\fR
Verify DIFF against CVD/INCDIR.

.SH "COMMANDS FOR CREATING AND VERIFYING DETACHED DIGITAL SIGNATURES"
.LP
.TP
\fB\-l[FILE], \-\-list\-sigs[=FILE]\fR
List all signature names from the local database directory (default) or from FILE.
\fB\-\-sign\fR
Sign a file. The resulting .sign file name will be in the form: dbname\-version.cvd.sign
or FILE.sign for non\-CVD targets. It will be created next to the target file.
If a .sign file already exists, then the new signature will be appended to file.
.TP
\fB\-fREGEX, \-\-find\-sigs=REGEX\fR
Find and display signatures from the local database directory which match the given REGEX. The whole signature body (name, hex string, etc.) is checked.
\fB\-\-key=FILE\fR
Specify a signing key.
.TP
\fB\-\-decode\-sigs=REGEX\fR
Decode signatures read from the standard input (eg. piped from \-\-find\-sigs)
\fB\-\-cert=FILE\fR
Specify a signing cert. May be used more than once to add intermediate and root certificates.
.TP
\fB\-\-test\-sigs=DATABASE TARGET_FILE\fR
Test all signatures from DATABASE against TARGET_FILE. This option will only give valid results if the target file is the final one (after unpacking, normalization, etc.) for which the signatures were created.
\fB\-\-append\fR
Use to add a signature line to an existing .sign file. Otherwise an existing .sign file will be overwritten.
.TP
\fB\-\-print\-certs=FILE\fR
Print Authenticode details from a PE file.
.TP
\fB\-\-tempdir=DIRECTORY\fR
Create temporary files in DIRECTORY. Directory must be writable for the user running sigtool.
\fB\-\-verify\fR
Find and verify a detached digital signature for the given file.
The digital signature file name must be in the form: dbname\-version.cvd.sign or FILE.sign for non-CVD targets.
It must be found next to the target file.
.TP
\fB\-\-leave\-temps\fR
Do not remove temporary files.
\fB\-\-cvdcertsdir=DIR\fR
Specify a directory containing the root CA cert needed to verify the signature.
If not provided, then sigtool will look in the default certs directory.

.SH "ENVIRONMENT VARIABLES"
.LP
Expand Down
2 changes: 2 additions & 0 deletions libclamav/clamav.h
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,8 @@ extern struct cl_cvd *cl_cvdparse(const char *head);
/**
* @brief Verify a CVD file by loading and unloading it.
*
* This function is deprecated. Use cl_cvdverify_ex() instead.
*
* @param file Filepath of CVD file.
* @return cl_error_t CL_SUCCESS if success, else a CL_E* error code.
*/
Expand Down
10 changes: 8 additions & 2 deletions libclamav/cvd.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ cl_error_t cl_cvdverify_ex(const char *file, const char *certs_directory)
{
struct cl_engine *engine;
cl_error_t ret;
cvd_type dbtype = CVD_TYPE_CVD;
cvd_type dbtype = CVD_TYPE_UNKNOWN;

if (!(engine = cl_engine_new())) {
cli_errmsg("cl_cvdverify: Can't create new engine\n");
Expand All @@ -413,10 +413,16 @@ cl_error_t cl_cvdverify_ex(const char *file, const char *certs_directory)
}
}

if (!!cli_strbcasestr(file, ".cld")) {
if (!!cli_strbcasestr(file, ".cvd")) {
dbtype = CVD_TYPE_CVD;
} else if (!!cli_strbcasestr(file, ".cld")) {
dbtype = CVD_TYPE_CLD;
} else if (!!cli_strbcasestr(file, ".cud")) {
dbtype = CVD_TYPE_CUD;
} else {
cli_errmsg("cl_cvdverify: File is not a CVD, CLD, or CUD: %s\n", file);
ret = CL_ECVD;
goto done;
}

ret = cli_cvdload(engine, NULL, CL_DB_STDOPT | CL_DB_PUA, dbtype, file, 1);
Expand Down
2 changes: 0 additions & 2 deletions libclamav/cvd.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ typedef enum cvd_type {
CVD_TYPE_CUD,
} cvd_type;

typedef void *cvd_t;

cl_error_t cli_cvdload(struct cl_engine *engine, unsigned int *signo, unsigned int options, cvd_type dbtype, const char *filename, unsigned int chkonly);

#endif
38 changes: 22 additions & 16 deletions libclamav_rust/src/codesign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub unsafe extern "C" fn codesign_sign_file(
signing_cert_path_str: *const c_char,
intermediate_cert_paths_str: *const *const c_char,
intermediate_cert_paths_len: usize,
append: bool,
err: *mut *mut FFIError,
) -> bool {
let target_file_path_str = validate_str_param!(target_file_path_str);
Expand Down Expand Up @@ -177,6 +178,7 @@ pub unsafe extern "C" fn codesign_sign_file(
&signing_cert_path,
&intermediate_cert_paths,
&signing_key_path,
append,
) {
Ok(()) => {
debug!("File signed successfully");
Expand All @@ -196,6 +198,7 @@ pub fn sign_file<P>(
signing_cert_path: &Path,
intermediate_cert_paths: &[P],
signing_key_path: &Path,
append: bool,
) -> Result<(), Error>
where
P: AsRef<Path>,
Expand All @@ -210,23 +213,26 @@ where
let mut sig_bytes: SigBytes = SigBytes::new();
signature.append_sigbytes(&mut sig_bytes)?;

// If the signature file already exists, open it and append the signature to it.
let mut writer = if signature_file_path.exists() {
let mut writer = std::io::BufWriter::new(
std::fs::OpenOptions::new()
.append(true)
.open(signature_file_path)?,
);
// Seek to the end of the file
writer.seek(std::io::SeekFrom::End(0))?;
// Write a newline before the signature
writer.write_all(b"\n")?;
let mut writer = {
let mut options = std::fs::OpenOptions::new();
options.write(true).create(true);

writer
} else {
// Create the signature file if it doesn't exist.
let mut writer = std::io::BufWriter::new(std::fs::File::create(signature_file_path)?);
writer.write_all(b"#clamsign-1.0\n")?;
if signature_file_path.exists() {
if append {
options.append(true);
} else {
options.truncate(true);
}
}

let mut writer = std::io::BufWriter::new(options.open(&signature_file_path)?);

if !signature_file_path.exists() || !append {
writer.write_all(b"#clamsign-1.0\n")?;
} else if append {
writer.seek(std::io::SeekFrom::End(0))?;
writer.write_all(b"\n")?;
}

writer
};
Expand Down
4 changes: 2 additions & 2 deletions libclamav_rust/src/cvd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ impl CVD {
match self.verify_rsa_dsig() {
Ok(()) => {
debug!("CVD verified successfully with Talos MD5-based RSA digital signature");
Ok("Talos".to_string())
Ok("Cisco Talos MD5-Based RSA Digital Signature".to_string())
}
Err(e) => {
warn!(
Expand Down Expand Up @@ -575,7 +575,7 @@ pub unsafe extern "C" fn cvd_unpack(

match cvd.unpack_to(&destination_path) {
Ok(()) => {
println!("CVD unpacked successfully");
debug!("CVD unpacked successfully");
true
}
Err(e) => {
Expand Down
9 changes: 9 additions & 0 deletions sigtool/sigtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,8 @@ static int sign(const struct optstruct *opts)
bool sign_result = false;
FFIError *sign_file_error = NULL;

bool append = false;

target = optget(opts, "sign")->strarg;
if (NULL == target) {
mprintf(LOGG_ERROR, "sign: No target file specified.\n");
Expand Down Expand Up @@ -1033,13 +1035,18 @@ static int sign(const struct optstruct *opts)
opt = opt->nextarg;
}

if (optget(opts, "append")->enabled) {
append = true;
}

sign_result = codesign_sign_file(
target,
sign_file_name,
signing_key,
signing_cert,
(const char **)intermediate_certs,
intermediate_certs_count,
append,
&sign_file_error);

if (!sign_result) {
Expand Down Expand Up @@ -4057,6 +4064,8 @@ static void help(void)
mprintf(LOGG_INFO, " --cert /path/to/private.key Specify a signing cert.\n");
mprintf(LOGG_INFO, " May be used more than once to add\n");
mprintf(LOGG_INFO, " intermediate and root certificates.\n");
mprintf(LOGG_INFO, " --append Use to add a signature line to an existing .sign file.\n");
mprintf(LOGG_INFO, " Otherwise an existing .sign file will be overwritten.\n");
mprintf(LOGG_INFO, "\n");
mprintf(LOGG_INFO, " --verify FILE Find and verify a detached digital\n");
mprintf(LOGG_INFO, " signature for the given file.\n");
Expand Down

0 comments on commit 99052ef

Please sign in to comment.