Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions clamd/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,8 +475,10 @@ static int dispatch_command(client_conn_t *conn, enum commands cmd, const char *
static int print_ver(int desc, char term, const struct cl_engine *engine)
{
uint32_t ver;
long long num_sigs;

ver = cl_engine_get_num(engine, CL_ENGINE_DB_VERSION, NULL);
num_sigs = cl_engine_get_num(engine, CL_ENGINE_NUM_SIGNATURES, NULL);
if (ver) {
char timestr[32];
const char *tstr;
Expand All @@ -485,8 +487,14 @@ static int print_ver(int desc, char term, const struct cl_engine *engine)
tstr = cli_ctime(&t, timestr, sizeof(timestr));
/* cut trailing \n */
timestr[strlen(tstr) - 1] = '\0';
if (num_sigs > 0) {
return mdprintf(desc, "ClamAV %s/%u/%s/%llu%c", get_version(), (unsigned int)ver, tstr, num_sigs, term);
}
return mdprintf(desc, "ClamAV %s/%u/%s%c", get_version(), (unsigned int)ver, tstr, term);
}
if (num_sigs > 0) {
return mdprintf(desc, "ClamAV %s/%llu%c", get_version(), num_sigs, term);
}
return mdprintf(desc, "ClamAV %s%c", get_version(), term);
}

Expand Down
4 changes: 4 additions & 0 deletions clamdscan/clamdscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ int main(int argc, char **argv)
/* TODO: Implement STATUS in clamd */
if (!optget(opts, "no-summary")->enabled) {
struct tm tmp;
unsigned long long sigs = 0;

date_end = time(NULL);
gettimeofday(&t2, NULL);
Expand All @@ -182,6 +183,9 @@ int main(int argc, char **argv)
ds -= (dms < 0) ? (1) : (0);
dms += (dms < 0) ? (1000000) : (0);
logg(LOGG_INFO, "\n----------- SCAN SUMMARY -----------\n");
if (get_clamd_signature_count(opts, &sigs) == 0) {
logg(LOGG_INFO, "Database: %llu signatures\n", sigs);
}
logg(LOGG_INFO, "Infected files: %d\n", infected);
if (err)
logg(LOGG_INFO, "Total errors: %d\n", err);
Expand Down
64 changes: 64 additions & 0 deletions clamdscan/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,70 @@ int reload_clamd_database(const struct optstruct *opts)
return 0;
}

int get_clamd_signature_count(const struct optstruct *opts, unsigned long long *sigs)
{
char *buff;
int len, sockd;
struct RCVLN rcv;
const char zVERSION[] = "zVERSION";
char *last_slash, *endptr;

if (!sigs) {
return 2;
}

*sigs = 0;

isremote(opts);
if ((sockd = dconnect(clamdopts)) < 0) return 2;
recvlninit(&rcv, sockd);

if (sendln(sockd, zVERSION, sizeof(zVERSION))) {
closesocket(sockd);
return 2;
}

while ((len = recvln(&rcv, &buff, NULL))) {
if (len == -1) {
logg(LOGG_ERROR, "Error occurred while receiving version information.\n");
break;
}

/* Check if the response was "COMMAND UNAVAILABLE" */
if (len >= 19 && memcmp(buff, "COMMAND UNAVAILABLE", 19) == 0) {
closesocket(sockd);
return 2;
}

/* Parse the VERSION response format:
* "ClamAV version/dbversion/timestamp/signatures" (if ver and sigs > 0)
* "ClamAV version/dbversion/timestamp" (if ver but sigs == 0)
* "ClamAV version/signatures" (if no ver but sigs > 0)
* "ClamAV version" (if no ver and no sigs)
*/
/* Only parse lines that start with "ClamAV" */
if (len >= 6 && memcmp(buff, "ClamAV", 6) == 0) {
/* Find the last '/' to get the signature count */
last_slash = strrchr(buff, '/');
if (last_slash) {
last_slash++;
/* Try to parse as number - if it's a number, it's the signature count */
*sigs = strtoull(last_slash, &endptr, 10);
if (endptr == last_slash || (*endptr != '\0' && *endptr != '\n' && *endptr != '\r')) {
/* Last field is not a number, so no signature count in response */
*sigs = 0;
} else if (*sigs > 0) {
/* Successfully parsed signature count, we're done */
break;
}
}
}
}

closesocket(sockd);
return (*sigs > 0) ? 0 : 2;
}

int client(const struct optstruct *opts, int *infected, int *err)
{
int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0;
Expand Down
1 change: 1 addition & 0 deletions clamdscan/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
int client(const struct optstruct *opts, int *infected, int *err);
int get_clamd_version(const struct optstruct *opts);
int reload_clamd_database(const struct optstruct *opts);
int get_clamd_signature_count(const struct optstruct *opts, unsigned long long *sigs);
int16_t ping_clamd(const struct optstruct *opts);

#endif
2 changes: 1 addition & 1 deletion clamscan/clamscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ int main(int argc, char **argv)
ds -= (dms < 0) ? (1) : (0);
dms += (dms < 0) ? (1000000) : (0);
logg(LOGG_INFO, "\n----------- SCAN SUMMARY -----------\n");
logg(LOGG_INFO, "Known viruses: %u\n", info.sigs);
logg(LOGG_INFO, "Database: %u signatures\n", info.sigs);
logg(LOGG_INFO, "Engine version: %s\n", get_version());
logg(LOGG_INFO, "Scanned directories: %u\n", info.dirs);
logg(LOGG_INFO, "Scanned files: %u\n", info.files);
Expand Down
77 changes: 55 additions & 22 deletions cmake/CheckFDPassing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,63 @@ if(HAVE_CONTROL_IN_MSGHDR)
set(EXTRA_COMPILE_DEFINITIONS "${EXTRA_COMPILE_DEFINITIONS} -DHAVE_SYS_UIO_H=1")
endif()

# Try without _XOPEN_SOURCE first
try_run(
# Name of variable to store the run result (process exit status; number) in:
test_run_result
# Name of variable to store the compile result (TRUE or FALSE) in:
test_compile_result
# Binary directory:
${CMAKE_CURRENT_BINARY_DIR}
# Source file to be compiled:
${_selfdir_CheckFDPassing}/CheckFDPassing.c
# Extra -D Compile Definitions
COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS}
# Where to store the output produced during compilation:
COMPILE_OUTPUT_VARIABLE test_compile_output
# Where to store the output produced by running the compiled executable:
RUN_OUTPUT_VARIABLE test_run_output )

# Did compilation succeed and process return 0 (success)?
if("${test_compile_result}" AND ("${test_run_result}" EQUAL 0))
set(HAVE_FD_PASSING 1)
else()
# Try again, this time with: #define _XOPEN_SOURCE 500
# OpenBSD requires _XOPEN_SOURCE for proper fdpassing support
if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
set(EXTRA_COMPILE_DEFINITIONS "${EXTRA_COMPILE_DEFINITIONS} -D_XOPEN_SOURCE=500")
set(FORCE_XOPEN_TEST 1)
else()
set(FORCE_XOPEN_TEST 0)
endif()

# Try without _XOPEN_SOURCE first (unless OpenBSD)
if(NOT FORCE_XOPEN_TEST)
try_run(
# Name of variable to store the run result (process exit status; number) in:
test_run_result
# Name of variable to store the compile result (TRUE or FALSE) in:
test_compile_result
# Binary directory:
${CMAKE_CURRENT_BINARY_DIR}
# Source file to be compiled:
${_selfdir_CheckFDPassing}/CheckFDPassing.c
# Extra -D Compile Definitions
COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS}
# Where to store the output produced during compilation:
COMPILE_OUTPUT_VARIABLE test_compile_output
# Where to store the output produced by running the compiled executable:
RUN_OUTPUT_VARIABLE test_run_output )

# Did compilation succeed and process return 0 (success)?
if("${test_compile_result}" AND ("${test_run_result}" EQUAL 0))
set(HAVE_FD_PASSING 1)
else()
# Try again, this time with: #define _XOPEN_SOURCE 500
set(EXTRA_COMPILE_DEFINITIONS "${EXTRA_COMPILE_DEFINITIONS} -D_XOPEN_SOURCE=500")

try_run(
# Name of variable to store the run result (process exit status; number) in:
test_run_result
# Name of variable to store the compile result (TRUE or FALSE) in:
test_compile_result
# Binary directory:
${CMAKE_CURRENT_BINARY_DIR}
# Source file to be compiled:
${_selfdir_CheckFDPassing}/CheckFDPassing.c
# Extra -D Compile Definitions
COMPILE_DEFINITIONS ${EXTRA_COMPILE_DEFINITIONS}
# Where to store the output produced during compilation:
COMPILE_OUTPUT_VARIABLE test_compile_output
# Where to store the output produced by running the compiled executable:
RUN_OUTPUT_VARIABLE test_run_output )

# Did compilation succeed and process return 0 (success)?
if("${test_compile_result}" AND ("${test_run_result}" EQUAL 0))
set(HAVE_FD_PASSING 1)
set(FDPASS_NEED_XOPEN 1)
endif()
endif()
else()
# For OpenBSD, test directly with _XOPEN_SOURCE=500
try_run(
# Name of variable to store the run result (process exit status; number) in:
test_run_result
Expand Down
3 changes: 3 additions & 0 deletions common/clamdcom.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include "clamav-config.h"
#endif

/* must be first because it may define _XOPEN_SOURCE */
#include "fdpassing.h"

#include <stdio.h>
#include <stdint.h>
#include <string.h>
Expand Down
1 change: 1 addition & 0 deletions libclamav/clamav.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ enum cl_engine_field {
CL_ENGINE_CVDCERTSDIR, /** (char *) */
CL_ENGINE_TMPDIR_RECURSION, /** uint32_t */
CL_ENGINE_FIPS_LIMITS, /** uint32_t */
CL_ENGINE_NUM_SIGNATURES, /** size_t */
};

enum bytecode_security {
Expand Down
2 changes: 2 additions & 0 deletions libclamav/others.c
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,8 @@ long long cl_engine_get_num(const struct cl_engine *engine, enum cl_engine_field
return engine->pcre_recmatch_limit;
case CL_ENGINE_PCRE_MAX_FILESIZE:
return engine->pcre_max_filesize;
case CL_ENGINE_NUM_SIGNATURES:
return (long long)engine->num_total_signatures;
default:
cli_errmsg("cl_engine_get: Incorrect field number\n");
if (err)
Expand Down
Loading