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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ endif()

if(ENABLE_PDFIUM)
find_package(PDFIUM REQUIRED MODULE)
set(HAVE_PDFIUM 1)
endif()

if(ENABLE_JSON_SHARED)
Expand Down
102 changes: 102 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

163 changes: 163 additions & 0 deletions clamd/server-th.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <pthread.h>
#include <errno.h>
#include <stdint.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -58,6 +59,51 @@
#include "misc.h"
#include "idmef_logging.h"

static int parse_pdf_render_canvas(const char *value, uint32_t *width, uint32_t *height)
{
unsigned int parsed_width = 0;
unsigned int parsed_height = 0;
char trailing = '\0';

if ((NULL == value) || (NULL == width) || (NULL == height)) {
return 0;
}

if ((2 != sscanf(value, "%ux%u", &parsed_width, &parsed_height)) ||
(0 == parsed_width) ||
(0 == parsed_height)) {
return 0;
}

if (3 == sscanf(value, "%ux%u%c", &parsed_width, &parsed_height, &trailing)) {
return 0;
}

*width = parsed_width;
*height = parsed_height;

return 1;
}

static int parse_pdf_render_format(const char *value, uint32_t *format)
{
if ((NULL == value) || (NULL == format)) {
return 0;
}

if (0 == strcmp(value, "png")) {
*format = 1;
return 1;
}

if ((0 == strcmp(value, "jpeg")) || (0 == strcmp(value, "jpg"))) {
*format = 2;
return 1;
}

return 0;
}

#include "server.h"
#include "thrmgr.h"
#include "session.h"
Expand Down Expand Up @@ -1122,6 +1168,103 @@ int recvloop(int *socketds, unsigned nsockets, struct cl_engine *engine, unsigne
val = cl_engine_get_num(engine, CL_ENGINE_PCRE_MAX_FILESIZE, NULL);
logg(LOGG_INFO, "Limits: PCREMaxFileSize limit set to %llu.\n", val);

if (optget(opts, "PDFRenderDPI")->active && optget(opts, "PDFRenderCanvas")->active) {
#ifndef HAVE_PDFIUM
logg(LOGG_ERROR, "PDFRenderDPI and PDFRenderCanvas require ClamAV to be built with PDFium support.\n");
#else
logg(LOGG_ERROR, "Cannot set both PDFRenderDPI and PDFRenderCanvas.\n");
#endif
cl_engine_free(engine);
return 1;
}

if ((opt = optget(opts, "PDFRenderDPI"))->active) {
#ifndef HAVE_PDFIUM
logg(LOGG_ERROR, "PDFRenderDPI requires ClamAV to be built with PDFium support.\n");
cl_engine_free(engine);
return 1;
#else
if (opt->numarg <= 0) {
logg(LOGG_ERROR, "PDFRenderDPI must be greater than 0.\n");
cl_engine_free(engine);
return 1;
}
if ((ret = cl_engine_set_num(engine, CL_ENGINE_PDF_RENDER_DPI, opt->numarg))) {
logg(LOGG_ERROR, "cli_engine_set_num(PDFRenderDPI) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 1;
}
#endif
}
#ifdef HAVE_PDFIUM
val = cl_engine_get_num(engine, CL_ENGINE_PDF_RENDER_DPI, NULL);
if (val > 0) {
logg(LOGG_INFO, "PDF rendering: DPI set to %llu.\n", val);
}
#else
logg(LOGG_INFO, "PDF rendering unavailable: built without PDFium support.\n");
#endif

if ((opt = optget(opts, "PDFRenderCanvas"))->active) {
#ifndef HAVE_PDFIUM
logg(LOGG_ERROR, "PDFRenderCanvas requires ClamAV to be built with PDFium support.\n");
cl_engine_free(engine);
return 1;
#else
uint32_t canvas_width = 0;
uint32_t canvas_height = 0;

if (!parse_pdf_render_canvas(opt->strarg, &canvas_width, &canvas_height)) {
logg(LOGG_ERROR, "PDFRenderCanvas must be in WIDTHxHEIGHT format, for example 1920x1080.\n");
cl_engine_free(engine);
return 1;
}

if ((ret = cl_engine_set_num(engine, CL_ENGINE_PDF_RENDER_CANVAS_WIDTH, canvas_width))) {
logg(LOGG_ERROR, "cli_engine_set_num(PDFRenderCanvasWidth) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 1;
}
if ((ret = cl_engine_set_num(engine, CL_ENGINE_PDF_RENDER_CANVAS_HEIGHT, canvas_height))) {
logg(LOGG_ERROR, "cli_engine_set_num(PDFRenderCanvasHeight) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 1;
}
#endif
}
#ifdef HAVE_PDFIUM
val = cl_engine_get_num(engine, CL_ENGINE_PDF_RENDER_CANVAS_WIDTH, NULL);
logg(LOGG_INFO, "PDF rendering: canvas width set to %llu.\n", val);
val = cl_engine_get_num(engine, CL_ENGINE_PDF_RENDER_CANVAS_HEIGHT, NULL);
logg(LOGG_INFO, "PDF rendering: canvas height set to %llu.\n", val);
#endif

if ((opt = optget(opts, "PDFRenderFormat"))->active) {
#ifndef HAVE_PDFIUM
logg(LOGG_ERROR, "PDFRenderFormat requires ClamAV to be built with PDFium support.\n");
cl_engine_free(engine);
return 1;
#else
uint32_t render_format = 0;

if (!parse_pdf_render_format(opt->strarg, &render_format)) {
logg(LOGG_ERROR, "PDFRenderFormat must be either png or jpeg.\n");
cl_engine_free(engine);
return 1;
}

if ((ret = cl_engine_set_num(engine, CL_ENGINE_PDF_RENDER_FORMAT, render_format))) {
logg(LOGG_ERROR, "cli_engine_set_num(PDFRenderFormat) failed: %s\n", cl_strerror(ret));
cl_engine_free(engine);
return 1;
}
#endif
}
#ifdef HAVE_PDFIUM
val = cl_engine_get_num(engine, CL_ENGINE_PDF_RENDER_FORMAT, NULL);
logg(LOGG_INFO, "PDF rendering: format set to %s.\n", (2 == val) ? "jpeg" : "png");
#endif

if (optget(opts, "ScanArchive")->enabled) {
logg(LOGG_INFO, "Archive support enabled.\n");
options.parse |= CL_SCAN_PARSE_ARCHIVE;
Expand All @@ -1143,6 +1286,26 @@ int recvloop(int *socketds, unsigned nsockets, struct cl_engine *engine, unsigne
logg(LOGG_INFO, "Detection using image fuzzy hash disabled.\n");
}

#ifndef HAVE_PDFIUM
if (optget(opts, "ScanPDFImageFuzzyHash")->active &&
optget(opts, "ScanPDFImageFuzzyHash")->enabled) {
logg(LOGG_ERROR, "ScanPDFImageFuzzyHash requires ClamAV to be built with PDFium support.\n");
cl_engine_free(engine);
return 1;
}
#endif

if (optget(opts, "ScanPDFImageFuzzyHash")->enabled) {
#ifdef HAVE_PDFIUM
logg(LOGG_INFO, "Detection using PDF render image fuzzy hash enabled.\n");
options.parse |= CL_SCAN_PARSE_PDF_IMAGE_FUZZY_HASH;
#else
logg(LOGG_INFO, "Detection using PDF render image fuzzy hash unavailable: built without PDFium support.\n");
#endif
} else {
logg(LOGG_INFO, "Detection using PDF render image fuzzy hash disabled.\n");
}

/* TODO: Remove deprecated option in a future feature release. */
if (optget(opts, "ArchiveBlockEncrypted")->enabled) {
if (options.parse & CL_SCAN_PARSE_ARCHIVE) {
Expand Down
6 changes: 6 additions & 0 deletions clamscan/clamscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,12 @@ void help(void)
mprintf(LOGG_INFO, " --scan-archive[=yes(*)/no] Scan archive files (supported by libclamav).\n");
mprintf(LOGG_INFO, " --scan-image[=yes(*)/no] Scan image (graphics) files.\n");
mprintf(LOGG_INFO, " --scan-image-fuzzy-hash[=yes(*)/no] Detect files by calculating image (graphics) fuzzy hashes.\n");
#ifdef HAVE_PDFIUM
mprintf(LOGG_INFO, " --scan-pdf-image-fuzzy-hash[=yes(*)/no] Detect PDFs by rendering the first page and calculating an image fuzzy hash.\n");
mprintf(LOGG_INFO, " --pdf-render-dpi=#n Render PDF pages for fuzzy hashing at the specified DPI.\n");
mprintf(LOGG_INFO, " --pdf-render-canvas=WxH Render PDF pages for fuzzy hashing to fit within a WIDTH x HEIGHT canvas.\n");
mprintf(LOGG_INFO, " --pdf-render-format=TYPE Render PDF pages as either png or jpeg.\n");
#endif
mprintf(LOGG_INFO, " --alert-broken[=yes/no(*)] Alert on broken executable files (PE & ELF).\n");
mprintf(LOGG_INFO, " --alert-broken-media[=yes/no(*)] Alert on broken graphics files (JPEG, TIFF, PNG, GIF).\n");
mprintf(LOGG_INFO, " --alert-encrypted[=yes/no(*)] Alert on encrypted archives and documents.\n");
Expand Down
Loading