Browse Source

[Project] Use libarchive for troublesome archives

pull/4843/head
Vsevolod Stakhov 2 months ago
parent
commit
8e8a09ffbf
No account linked to committer's email address
2 changed files with 43 additions and 9 deletions
  1. 3
    0
      CMakeLists.txt
  2. 40
    9
      src/libmime/archives.c

+ 3
- 0
CMakeLists.txt View File

FIND_PACKAGE(PkgConfig REQUIRED) FIND_PACKAGE(PkgConfig REQUIRED)
FIND_PACKAGE(Perl REQUIRED) FIND_PACKAGE(Perl REQUIRED)



option(SANITIZE "Enable sanitizer: address, memory, undefined, leak (comma separated list)" "") option(SANITIZE "Enable sanitizer: address, memory, undefined, leak (comma separated list)" "")
INCLUDE(Toolset) INCLUDE(Toolset)
INCLUDE(Sanitizer) INCLUDE(Sanitizer)
ProcessPackage(SODIUM LIBRARY sodium INCLUDE sodium.h ProcessPackage(SODIUM LIBRARY sodium INCLUDE sodium.h
INCLUDE_SUFFIXES include/libsodium include/sodium INCLUDE_SUFFIXES include/libsodium include/sodium
ROOT ${LIBSODIUM_ROOT_DIR} MODULES libsodium>=1.0.0) ROOT ${LIBSODIUM_ROOT_DIR} MODULES libsodium>=1.0.0)
ProcessPackage(LIBARCHIVE LIBRARY archive INCLUDE archive.h
ROOT ${LIBARCHIVE_ROOT_DIR} MODULES libarchive>=3.0.0)


if (ENABLE_FASTTEXT MATCHES "ON") if (ENABLE_FASTTEXT MATCHES "ON")
ProcessPackage(FASTTEXT LIBRARY fasttext INCLUDE fasttext/fasttext.h ProcessPackage(FASTTEXT LIBRARY fasttext INCLUDE fasttext/fasttext.h

+ 40
- 9
src/libmime/archives.c View File

/*-
* Copyright 2016 Vsevolod Stakhov
/*
* Copyright 2024 Vsevolod Stakhov
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
#include <unicode/utf16.h> #include <unicode/utf16.h>
#include <unicode/ucnv.h> #include <unicode/ucnv.h>


#include <archive.h>
#include <archive_entry.h>

#define msg_debug_archive(...) rspamd_conditional_debug_fast(NULL, NULL, \ #define msg_debug_archive(...) rspamd_conditional_debug_fast(NULL, NULL, \
rspamd_archive_log_id, "archive", task->task_pool->tag.uid, \ rspamd_archive_log_id, "archive", task->task_pool->tag.uid, \
G_STRFUNC, \ G_STRFUNC, \
static const guchar * static const guchar *
rspamd_7zip_read_next_section(struct rspamd_task *task, rspamd_7zip_read_next_section(struct rspamd_task *task,
const guchar *p, const guchar *end, const guchar *p, const guchar *end,
struct rspamd_archive *arch)
struct rspamd_archive *arch,
struct rspamd_mime_part *part)
{ {
guchar t = *p; guchar t = *p;


* In fact, headers are just packed, but we assume it as * In fact, headers are just packed, but we assume it as
* encrypted to distinguish from the normal archives * encrypted to distinguish from the normal archives
*/ */
msg_debug_archive("7zip: encoded header, needs to be uncompressed");
arch->flags |= RSPAMD_ARCHIVE_CANNOT_READ;
p = NULL; /* Cannot get anything useful */
break;
{
msg_debug_archive("7zip: encoded header, needs to be uncompressed");
struct archive *a = archive_read_new();
archive_read_support_format_7zip(a);
int r = archive_read_open_memory(a, part->parsed_data.begin, part->parsed_data.len);
if (r != ARCHIVE_OK) {
msg_debug_archive("7zip: cannot open memory archive: %s", archive_error_string(a));
archive_read_free(a);
return NULL;
}

/* Clean the existing files if any */
rspamd_archive_dtor(arch);
arch->files = g_ptr_array_new();

struct archive_entry *ae;

while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
const char *name = archive_entry_pathname(ae);
if (name) {
msg_debug_archive("7zip: found file %s", name);
struct rspamd_archive_file *f = g_malloc0(sizeof(*f));
f->fname = g_string_new(name);
g_ptr_array_add(arch->files, f);
}
archive_read_data_skip(a);
}
archive_read_free(a);
p = NULL; /* Stop internal processor, as we rely on libarchive here */
break;
}
case kArchiveProperties: case kArchiveProperties:
p = rspamd_7zip_read_archive_props(task, p, end, arch); p = rspamd_7zip_read_archive_props(task, p, end, arch);
break; break;
return; return;
} }


while ((p = rspamd_7zip_read_next_section(task, p, end, arch)) != NULL)
while ((p = rspamd_7zip_read_next_section(task, p, end, arch, part)) != NULL)
; ;


part->part_type = RSPAMD_MIME_PART_ARCHIVE; part->part_type = RSPAMD_MIME_PART_ARCHIVE;

Loading…
Cancel
Save