Skip to content

Commit

Permalink
CMake: fix issue finding openssl include directory for Rust build
Browse files Browse the repository at this point in the history
Also fix issue when certs directory param for cl_cvdunpack_ex is NULL
  • Loading branch information
val-ms committed Jan 19, 2025
1 parent ff84050 commit d5e6d20
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 47 deletions.
8 changes: 4 additions & 4 deletions clamd/clamd.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ int main(int argc, char **argv)
pid_t mainpid = 0;
mode_t old_umask = 0;
const char *user_name = NULL;
char *cvdcertsdir = NULL;
char *cvdcertsdir = NULL;
STATBUF statbuf;

if (check_flevel())
Expand Down Expand Up @@ -597,9 +597,9 @@ int main(int argc, char **argv)
// (which would've used the env var or hardcoded path)
if (LSTAT(cvdcertsdir, &statbuf) == -1) {
logg(LOGG_ERROR,
"ClamAV CA certificates directory is missing: %s\n"
"It should have been provided as a part of installation.",
cvdcertsdir);
"ClamAV CA certificates directory is missing: %s\n"
"It should have been provided as a part of installation.",
cvdcertsdir);
ret = 1;
break;
}
Expand Down
6 changes: 3 additions & 3 deletions clamscan/manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -1258,9 +1258,9 @@ int scanmanager(const struct optstruct *opts)
// (which would've used the env var or hardcoded path)
if (LSTAT(cvdcertsdir, &statbuf) == -1) {
logg(LOGG_ERROR,
"ClamAV CA certificates directory is missing: %s\n"
"It should have been provided as a part of installation.",
cvdcertsdir);
"ClamAV CA certificates directory is missing: %s\n"
"It should have been provided as a part of installation.",
cvdcertsdir);
ret = 2;
goto done;
}
Expand Down
26 changes: 17 additions & 9 deletions libclamav/cvd.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,25 +685,33 @@ cl_error_t cl_cvdunpack_ex(const char *file, const char *dir, bool dont_verify,
return CL_EOPEN;
}

if (!dont_verify) {
if (!codesign_verifier_new(certs_directory, &verifier, &new_verifier_error)) {
cli_errmsg("Failed to create a new code-signature verifier: %s\n", ffierror_fmt(new_verifier_error));
if (dont_verify) {
// Just unpack the CVD file.
if (!cvd_unpack(cvd, dir, &cvd_unpack_error)) {
cli_errmsg("CVD unpacking failed: %s\n", ffierror_fmt(cvd_unpack_error));
status = CL_EUNPACK;
goto done;
}
} else {
// Verify the CVD file and hten unpack it.

// The certs directory is optional.
// If not provided, then we can't validate external signatures and will have to rely
// on the internal MD5-based RSA signature.
if (NULL != certs_directory) {
if (!codesign_verifier_new(certs_directory, &verifier, &new_verifier_error)) {
cli_errmsg("Failed to create a new code-signature verifier: %s\n", ffierror_fmt(new_verifier_error));
status = CL_EUNPACK;
goto done;
}
}

status = cli_cvdunpack_and_verify(file, dir, dont_verify, verifier);
if (status != CL_SUCCESS) {
goto done;
}
}

if (!cvd_unpack(cvd, dir, &cvd_unpack_error)) {
cli_errmsg("CVD unpacking failed: %s\n", ffierror_fmt(cvd_unpack_error));
status = CL_EUNPACK;
goto done;
}

done:

if (NULL != signer_name) {
Expand Down
2 changes: 1 addition & 1 deletion libclamav/others.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ struct cl_engine {
uint32_t ac_mindepth;
uint32_t ac_maxdepth;
char *tmpdir;
char* certs_directory;
char *certs_directory;
uint32_t keeptmp;
uint64_t engine_options;
uint32_t cache_size;
Expand Down
39 changes: 33 additions & 6 deletions libclamav_rust/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,39 @@
# Copyright (C) 2021-2024 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
#

# if OPENSSL_ROOT_DIR is set, pass it to the environment
if(OPENSSL_ROOT_DIR)
set(ENVIRONMENT "OPENSSL_DIR=${OPENSSL_ROOT_DIR}")
else ()
set(ENVIRONMENT "")
endif()
get_filename_component(OPENSSL_DIR "${OPENSSL_INCLUDE_DIR}" DIRECTORY)

# The Rust openssl-sys crate needs to know how to find the OpenSSL headers and libraries.
set(OPENSSL_LIBS "")
foreach(LIB IN LISTS OPENSSL_LIBRARIES)
# Skip any libraries starting with `-l` (e.g. -lpthread).
# These are system libraries and won't be found in the OPENSSL_LIB_DIR.
if (NOT LIB MATCHES "^-l")
# Remove path and extension
get_filename_component(LIBNAME "${LIB}" NAME_WLE)

# Remove "lib" prefix, if present
string(REGEX REPLACE "^lib" "" LIBNAME "${LIBNAME}")

if (NOT OPENSSL_LIBS)
# Add first openssl lib.
set(OPENSSL_LIBS "${LIBNAME}")

# While we're at it... get directory of the first library to use for the OPENSSL_LIB_DIR.
# Note: This assumes that all libs are in the same directory.
get_filename_component(OPENSSL_LIB_DIR "${LIB}" DIRECTORY)
else()
# Add additional openssl libs.
set(OPENSSL_LIBS "${OPENSSL_LIBS}:${LIBNAME}")
endif()
endif()
endforeach()

set(ENVIRONMENT "")
list(APPEND ENVIRONMENT "OPENSSL_DIR=${OPENSSL_DIR}")
list(APPEND ENVIRONMENT "OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR}")
list(APPEND ENVIRONMENT "OPENSSL_LIBS=${OPENSSL_LIBS}")
list(APPEND ENVIRONMENT "OPENSSL_LIB_DIR=${OPENSSL_LIB_DIR}")

# libclamav rust static library
add_rust_library(TARGET clamav_rust
Expand Down
8 changes: 7 additions & 1 deletion libclamav_rust/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,13 @@ const BINDGEN_FUNCTIONS: &[&str] = &[
];

// Generate bindings for these types (structs, enums):
const BINDGEN_TYPES: &[&str] = &["cli_matcher", "cli_ac_data", "cli_ac_result", "onedump_t", "cvd_t"];
const BINDGEN_TYPES: &[&str] = &[
"cli_matcher",
"cli_ac_data",
"cli_ac_result",
"onedump_t",
"cvd_t",
];

// Find the required functions and types in these headers:
const BINDGEN_HEADERS: &[&str] = &[
Expand Down
10 changes: 9 additions & 1 deletion libclamav_rust/src/cdiff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@
*/

use std::{
collections::BTreeMap, ffi::{c_void, CStr, CString}, fs::{self, File, OpenOptions}, io::{prelude::*, BufReader, BufWriter, Read, Seek, SeekFrom, Write}, iter::*, mem::ManuallyDrop, os::raw::c_char, path::{Path, PathBuf}, str::{self, FromStr}
collections::BTreeMap,
ffi::{c_void, CStr, CString},
fs::{self, File, OpenOptions},
io::{prelude::*, BufReader, BufWriter, Read, Seek, SeekFrom, Write},
iter::*,
mem::ManuallyDrop,
os::raw::c_char,
path::{Path, PathBuf},
str::{self, FromStr},
};

use crate::{
Expand Down
63 changes: 50 additions & 13 deletions libclamav_rust/src/cvd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,18 @@ use std::{
fs::File,
io::{prelude::*, BufReader},
mem::ManuallyDrop,
os::{
fd::AsRawFd,
raw::{c_char, c_void},
},
os::raw::{c_char, c_void},
path::{Path, PathBuf},
str::FromStr,
time::{Duration, SystemTime},
};

#[cfg(any(unix))]
use std::os::fd::AsRawFd;

#[cfg(any(windows))]
use std::os::windows::io::{AsRawHandle, RawHandle};

use crate::codesign::Verifier;
use flate2::read::GzDecoder;
use hex;
Expand Down Expand Up @@ -647,16 +650,29 @@ pub unsafe extern "C" fn cvd_verify(
) -> bool {
let mut cvd = ManuallyDrop::new(Box::from_raw(cvd as *mut CVD));

let verifier = ManuallyDrop::new(Box::from_raw(verifier_ptr as *mut Verifier));

match cvd.verify(Some(&verifier), disable_md5) {
Ok(signer) => {
let signer_cstr = std::ffi::CString::new(signer).unwrap();
*signer_name = signer_cstr.into_raw();
true
if verifier_ptr.is_null() {
match cvd.verify(None, disable_md5) {
Ok(signer) => {
let signer_cstr = std::ffi::CString::new(signer).unwrap();
*signer_name = signer_cstr.into_raw();
true
}
Err(e) => {
ffi_error!(err = err, e)
}
}
Err(e) => {
ffi_error!(err = err, e)
} else {
let verifier = ManuallyDrop::new(Box::from_raw(verifier_ptr as *mut Verifier));

match cvd.verify(Some(&verifier), disable_md5) {
Ok(signer) => {
let signer_cstr = std::ffi::CString::new(signer).unwrap();
*signer_name = signer_cstr.into_raw();
true
}
Err(e) => {
ffi_error!(err = err, e)
}
}
}
}
Expand Down Expand Up @@ -778,8 +794,29 @@ pub unsafe extern "C" fn cvd_get_builder(cvd: *const c_void) -> *mut c_char {
///
/// No parameters may be NULL
/// The CVD pointer must be valid
#[cfg(any(unix))]
#[export_name = "cvd_get_file"]
pub unsafe extern "C" fn cvd_get_file(cvd: *const c_void) -> i32 {
let cvd = ManuallyDrop::new(Box::from_raw(cvd as *mut CVD));

cvd.file.as_raw_fd()
}

/// C interface for getting the file handle of a CVD.
/// Handles all the unsafe ffi stuff.
/// Returns the file handle an integer.
/// The caller must not close the file handle.
/// The file handle is not guaranteed to be valid after the CVD struct is freed.
///
/// # Safety
///
/// No parameters may be NULL
/// The CVD pointer must be valid
#[cfg(any(windows))]
#[export_name = "cvd_get_file"]
pub unsafe extern "C" fn cvd_get_file(cvd: *const c_void) -> i32 {
let cvd = ManuallyDrop::new(Box::from_raw(cvd as *mut CVD));

let file = cvd.file.as_raw_handle();
file.to_fd()
}
4 changes: 2 additions & 2 deletions libclamav_rust/src/ffi_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use std::{
os::raw::c_char,
};

use log::{warn};
use log::warn;

/// Wraps a call to a "result-returning function", allowing it to specify an
/// error receiver and (optionally) result receiver.
Expand Down Expand Up @@ -426,7 +426,7 @@ macro_rules! validate_str_param_null {
///
/// The CString pointer must be valid
/// The CString pointer must not be used after calling this function
#[export_name = "ffi_cstring_free"]
#[export_name = "ffi_cstring_free"]
pub unsafe extern "C" fn ffi_cstring_free(cstring: *mut c_char) {
if cstring.is_null() {
warn!("Attempted to free a NULL CString pointer. Please report this at:: https://github.com/Cisco-Talos/clamav/issues");
Expand Down
2 changes: 1 addition & 1 deletion libclamav_rust/src/fuzzy_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ pub unsafe extern "C" fn _fuzzy_hash_load_subsignature(
subsig_id: u32,
err: *mut *mut FFIError,
) -> bool {
let hexsig = validate_str_param!(hexsig, err=err);
let hexsig = validate_str_param!(hexsig, err = err);

let mut hashmap = ManuallyDrop::new(Box::from_raw(fuzzy_hashmap as *mut FuzzyHashMap));

Expand Down
5 changes: 1 addition & 4 deletions libclamav_rust/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,7 @@ pub unsafe fn scan_archive_metadata(
///
/// No parameters may be NULL.
#[export_name = "glob_rm"]
pub unsafe extern "C" fn glob_rm(
glob_str: *const c_char,
err: *mut *mut FFIError,
) -> bool {
pub unsafe extern "C" fn glob_rm(glob_str: *const c_char, err: *mut *mut FFIError) -> bool {
let glob_str = validate_str_param!(glob_str);

for entry in glob(glob_str).expect("Failed to read glob pattern") {
Expand Down
4 changes: 2 additions & 2 deletions unit_tests/check_clamav.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ START_TEST(test_cl_load)
struct cl_engine *engine;
unsigned int sigs = 0;
const char *testfile;
const char* cvdcertsdir;
const char *cvdcertsdir;

ret = cl_init(CL_INIT_DEFAULT);
ck_assert_msg(ret == CL_SUCCESS, "cl_init failed: %s", cl_strerror(ret));
Expand All @@ -443,7 +443,7 @@ START_TEST(test_cl_cvdverify)
FILE *orig_fs;
FILE *new_fs;
char cvd_bytes[5000];
const char* cvdcertsdir;
const char *cvdcertsdir;

cvdcertsdir = getenv("CVD_CERTS_DIR");
ck_assert_msg(cvdcertsdir != NULL, "CVD_CERTS_DIR not set");
Expand Down

0 comments on commit d5e6d20

Please sign in to comment.