Browse Source

6.5 improvements

pull/205/head
Charles Pigott 2 months ago
parent
commit
c2f3ad7ebf
  1. 2
      src/cli/extract.cpp
  2. 4
      src/loader/offsets.cpp
  3. 2
      src/setup/data.cpp
  4. 52
      src/setup/file.cpp
  5. 19
      src/setup/file.hpp
  6. 4
      src/setup/header.cpp
  7. 4
      src/setup/header.hpp
  8. 101
      src/setup/info.cpp
  9. 20
      src/setup/info.hpp
  10. 22
      src/setup/issigkey.cpp
  11. 22
      src/setup/issigkey.hpp
  12. 4
      src/setup/version.hpp
  13. 4
      src/stream/block.cpp
  14. 4
      src/stream/chunk.hpp
  15. 6
      src/stream/slice.cpp
  16. 2
      src/stream/slice.hpp
  17. 11
      src/util/output.hpp

2
src/cli/extract.cpp

@ -1100,7 +1100,7 @@ void process_file(const fs::path & installer, const extract_options & o) {
if(o.test || o.extract) {
boost::uint64_t offset = info.data_entries[file.entry().location].uncompressed_size;
boost::uint32_t sort_slice = info.data_entries[file.entry().location].chunk.first_slice;
boost::uint32_t sort_offset = info.data_entries[file.entry().location].chunk.sort_offset;
boost::uint64_t sort_offset = info.data_entries[file.entry().location].chunk.sort_offset;
BOOST_FOREACH(boost::uint32_t location, file.entry().additional_locations) {
setup::data_entry & data = info.data_entries[location];
files_for_location[location].push_back(output_location(&file, offset));

4
src/loader/offsets.cpp

@ -219,8 +219,8 @@ bool offsets::load_offsets_at(std::istream & is, boost::uint32_t pos) {
boost::uint32_t actual = checksum.finalize();
if(actual != expected) {
log_warning << "Setup loader checksum mismatch! Expected: "
<< print_hex(expected)
<< " Actual: " << print_hex(actual);
<< print_hex(expected)
<< " Actual: " << print_hex(actual);
}
}

2
src/setup/data.cpp

@ -57,7 +57,7 @@ void data_entry::load(std::istream & is, const info & i) {
}
if(i.version >= INNO_VERSION(6, 5, 2)) {
chunk.sort_offset = chunk.offset = util::load<boost::int64_t>(is);
chunk.sort_offset = chunk.offset = util::load<boost::uint64_t>(is);
} else {
chunk.sort_offset = chunk.offset = util::load<boost::uint32_t>(is);
}

52
src/setup/file.cpp

@ -29,6 +29,11 @@
namespace setup {
namespace {
STORED_ENUM_MAP(stored_file_verification_type, file_entry::fvNone,
file_entry::fvNone,
file_entry::fvHash,
file_entry::fvISSig,
);
enum file_copy_mode {
cmNormal,
@ -60,6 +65,14 @@ STORED_ENUM_MAP(stored_file_type_1, file_entry::UserFile,
} // namespace setup
NAMED_ENUM(setup::file_entry::file_verification_type)
NAMES(setup::file_entry::file_verification_type, "File Verification Type",
"none",
"hash",
"IS sig",
)
NAMED_ENUM(setup::file_copy_mode)
NAMES(setup::file_copy_mode, "File Copy Mode",
@ -92,26 +105,25 @@ void file_entry::load(std::istream & is, const info & i) {
load_condition_data(is, i);
if(i.version >= INNO_VERSION(6, 5, 0)) {
is >> util::encoded_string(excludes, i.codepage, i.header.lead_bytes);
is >> util::encoded_string(download_issig_source, i.codepage, i.header.lead_bytes);
is >> util::encoded_string(download_user_name, i.codepage, i.header.lead_bytes);
is >> util::encoded_string(download_password, i.codepage, i.header.lead_bytes);
is >> util::encoded_string(extract_archive_password, i.codepage, i.header.lead_bytes);
// Verification structure
std::string issig_allowed_keys;
is >> util::ansi_string(issig_allowed_keys);
char hash[32];
is.read(hash, 32);
boost::uint8_t verification_type = util::load<boost::uint8_t>(is);
} else {
excludes.clear();
download_issig_source.clear();
download_user_name.clear();
download_password.clear();
extract_archive_password.clear();
}
if(i.version >= INNO_VERSION(6, 5, 0)) {
is >> util::encoded_string(excludes, i.codepage, i.header.lead_bytes);
is >> util::encoded_string(download_issig_source, i.codepage, i.header.lead_bytes);
is >> util::encoded_string(download_user_name, i.codepage, i.header.lead_bytes);
is >> util::encoded_string(download_password, i.codepage, i.header.lead_bytes);
is >> util::encoded_string(extract_archive_password, i.codepage, i.header.lead_bytes);
// Verification structure
is >> util::ansi_string(issig_allowed_keys);
is.read(checksum.sha256, std::streamsize(sizeof(checksum.sha256)));
checksum.type = crypto::SHA256;
verification = stored_enum<stored_file_verification_type>(is).get();
} else {
excludes.clear();
download_issig_source.clear();
download_user_name.clear();
download_password.clear();
extract_archive_password.clear();
}
load_version_data(is, i.version);

19
src/setup/file.hpp

@ -84,6 +84,12 @@ struct file_entry : public item {
IsReadmeFile
);
enum file_verification_type {
fvNone,
fvHash,
fvISSig,
};
enum file_type {
UserFile,
UninstExe,
@ -98,11 +104,14 @@ struct file_entry : public item {
std::string destination;
std::string install_font_name;
std::string strong_assembly_name;
std::string excludes;
std::string download_issig_source;
std::string download_user_name;
std::string download_password;
std::string extract_archive_password;
std::string excludes;
std::string download_issig_source;
std::string download_user_name;
std::string download_password;
std::string extract_archive_password;
std::string issig_allowed_keys;
file_verification_type verification;
boost::uint32_t location; //!< index into the data entry list
boost::uint32_t attributes;

4
src/setup/header.cpp

@ -710,7 +710,7 @@ header::flags header::load_flags(std::istream & is, const version & version) {
flagreader.add(AppendDefaultDirName);
flagreader.add(AppendDefaultGroupName);
}
if(version >= INNO_VERSION(4, 2, 2)) {
if(version >= INNO_VERSION(4, 2, 2) && version < INNO_VERSION(6, 5, 0)) {
flagreader.add(EncryptionUsed);
}
if(version >= INNO_VERSION(5, 0, 4) && version < INNO_VERSION(5, 6, 1)) {
@ -830,7 +830,6 @@ NAMES(setup::header::flags, "Setup Option",
"wizard image stretch",
"append default dir name",
"append default group name",
"encrypted",
"changes environment",
"show undisplayable languages",
"setup logging",
@ -858,6 +857,7 @@ NAMES(setup::header::flags, "Setup Option",
"disable dir exists warning",
"back solid",
"overwrite uninst reg entries",
"encrypted",
)
NAMES(setup::header::architecture_types, "Architecture",

4
src/setup/header.hpp

@ -87,7 +87,6 @@ struct header {
WizardImageStretch,
AppendDefaultDirName,
AppendDefaultGroupName,
EncryptionUsed,
ChangesEnvironment,
ShowUndisplayableLanguages,
SetupLogging,
@ -116,7 +115,8 @@ struct header {
DetectLanguageUsingLocale,
DisableDirExistsWarning,
BackSolid,
OverwriteUninstRegEntries
OverwriteUninstRegEntries,
EncryptionUsed
);

101
src/setup/info.cpp

@ -39,6 +39,7 @@
#include "setup/icon.hpp"
#include "setup/ini.hpp"
#include "setup/item.hpp"
#include "setup/issigkey.hpp"
#include "setup/language.hpp"
#include "setup/message.hpp"
#include "setup/permission.hpp"
@ -159,7 +160,7 @@ void info::try_load(std::istream & is, entry_types entries, util::codepage_id fo
debug("loading main header");
header.load(*reader, version);
debug("loading languages");
debug("loading " << header.language_count << " languages");
load_entries(*reader, entries, header.language_count, languages, Languages);
debug("determining encoding");
@ -193,39 +194,36 @@ void info::try_load(std::istream & is, entry_types entries, util::codepage_id fo
load_wizard_and_decompressor(*reader, version, header, *this, entries);
}
debug("loading messages");
debug("loading " << header.message_count << " messages");
load_entries(*reader, entries, header.message_count, messages, Messages);
debug("loading permissions");
debug("loading " << header.permission_count << " permissions");
load_entries(*reader, entries, header.permission_count, permissions, Permissions);
debug("loading types");
debug("loading " << header.type_count << " types");
load_entries(*reader, entries, header.type_count, types, Types);
debug("loading components");
debug("loading " << header.component_count << " components");
load_entries(*reader, entries, header.component_count, components, Components);
debug("loading tasks");
debug("loading " << header.task_count << " tasks");
load_entries(*reader, entries, header.task_count, tasks, Tasks);
debug("loading directories");
debug("loading " << header.directory_count << " directories");
load_entries(*reader, entries, header.directory_count, directories, Directories);
debug("slipping issig keys");
for(size_t i = 0; i < header.issig_key_count; i++) {
issig_key_entry entry;
entry.load(*reader, *this);
}
debug("loading files");
debug("loading " << header.issig_key_count << " issigs");
load_entries(*reader, entries, header.issig_key_count, issig_keys, ISSigs);
debug("loading " << header.file_count << " files");
load_entries(*reader, entries, header.file_count, files, Files);
debug("loading icons");
debug("loading " << header.icon_count << " icons");
load_entries(*reader, entries, header.icon_count, icons, Icons);
debug("loading ini entries");
debug("loading " << header.ini_entry_count << " ini entries");
load_entries(*reader, entries, header.ini_entry_count, ini_entries, IniEntries);
debug("loading registry entries");
debug("loading " << header.registry_entry_count << " registry entries");
load_entries(*reader, entries, header.registry_entry_count, registry_entries, RegistryEntries);
debug("loading delete entries");
debug("loading " << header.delete_entry_count << " delete entries");
load_entries(*reader, entries, header.delete_entry_count, delete_entries, DeleteEntries);
debug("loading uninstall delete entries");
debug("loading " << header.uninstall_delete_entry_count << " uninstall delete entries");
load_entries(*reader, entries, header.uninstall_delete_entry_count, uninstall_delete_entries,
UninstallDeleteEntries);
debug("loading run entries");
debug("loading " << header.run_entry_count << " run entries");
load_entries(*reader, entries, header.run_entry_count, run_entries, RunEntries);
debug("loading uninstall run entries");
debug("loading " << header.uninstall_run_entry_count << " uninstall run entries");
load_entries(*reader, entries, header.uninstall_run_entry_count, uninstall_run_entries,
UninstallRunEntries);
@ -245,49 +243,13 @@ void info::try_load(std::istream & is, entry_types entries, util::codepage_id fo
}
void info::load(std::istream & is, entry_types entries, util::codepage_id force_codepage,
boost::uint32_t loader_revision) {
boost::uint32_t loader_revision) {
version.load(is);
if(loader_revision == 2 && version >= INNO_VERSION(6, 5, 0)) {
version.set_64bit();
}
if(version >= INNO_VERSION(6, 5, 0)) {
boost::uint32_t eh_expected_crc = util::load<boost::uint32_t>(is);
encryption_header eh;
if(is.read(reinterpret_cast<char*>(&eh), sizeof(eh)).fail()) {
throw std::runtime_error("failed to read encryption header");
}
crypto::crc32 eh_crc;
eh_crc.init();
eh_crc.update(reinterpret_cast<const char*>(&eh), sizeof(eh));
if(eh_crc.finalize() != eh_expected_crc) {
//throw std::runtime_error("encryption header CRC mismatch");
}
if(eh.encryption_use == 2) {
throw std::runtime_error("full encryption mode is not supported");
}
if(eh.encryption_use == 1) {
header.password.type = crypto::PBKDF2_SHA256_XChaCha20;
header.password_salt.resize(44);
std::memcpy(&header.password_salt[0], eh.kdf_salt, 16);
util::little_endian::store<boost::uint32_t>(
boost::uint32_t(eh.kdf_iterations), &header.password_salt[16]
);
std::memcpy(&header.password_salt[20], &eh.base_nonce, sizeof(eh.base_nonce));
std::memcpy(header.password.sha256, &eh.password_test, 4);
} else {
header.password.type = crypto::None;
header.password_salt.clear();
std::memset(header.password.sha256, 0, 4);
}
}
if(!version.known) {
if(entries & NoUnknownVersion) {
std::ostringstream oss;
@ -309,6 +271,31 @@ void info::load(std::istream & is, entry_types entries, util::codepage_id force_
entries |= NoSkip;
}
if(version >= INNO_VERSION(6, 5, 0)) {
boost::uint32_t expected_encryption_crc = util::load<boost::uint32_t>(is);
crypto::crc32 checksum;
checksum.init();
boost::uint8_t encryption_use = checksum.load<boost::uint8_t>(is);
if(encryption_use != 0) {
log_error << "Unsupported encrypted setup";
}
for(int i = 0; i < 16; i++) {
/* KDFSalt */(void)checksum.load<boost::uint8_t>(is);
}
/* KDFIterations */(void)checksum.load<boost::uint32_t>(is);
/* BaseNonce.RandomXorStartOffset */(void)checksum.load<boost::uint64_t>(is);
/* BaseNonce.RandomXorFirstSlice */(void)checksum.load<boost::uint32_t>(is);
for(int i = 0; i < 3; i++) {
/* BaseNonce.RemainingRandom */(void)checksum.load<boost::uint32_t>(is);
}
/* PasswordTest */(void)checksum.load<boost::uint32_t>(is);
if(checksum.finalize() != expected_encryption_crc) {
log_warning << "Encryption header checksum mismatch!";
}
}
bool parsed_without_errors = false;
std::streampos start = is.tellg();
for(;;) {

20
src/setup/info.hpp

@ -41,6 +41,7 @@ struct component_entry;
struct data_entry;
struct delete_entry;
struct directory_entry;
struct issig_key_entry;
struct file_entry;
struct icon_entry;
struct ini_entry;
@ -52,20 +53,6 @@ struct run_entry;
struct task_entry;
struct type_entry;
#pragma pack(push, 1)
struct encryption_header {
boost::uint8_t encryption_use; // 0=none, 1=files, 2=full
boost::uint8_t kdf_salt[16];
boost::int32_t kdf_iterations;
struct {
boost::int64_t random_xor_start_offset;
boost::int32_t random_xor_first_slice;
boost::int32_t remaining_random[3];
} base_nonce;
boost::int32_t password_test;
};
#pragma pack(pop)
/*!
* Class used to hold and load the various \ref setup headers.
*/
@ -81,6 +68,7 @@ struct info {
DeleteEntries,
UninstallDeleteEntries,
Directories,
ISSigs,
Files,
Icons,
IniEntries,
@ -110,6 +98,7 @@ struct info {
std::vector<delete_entry> delete_entries; //! \c DeleteEntries
std::vector<delete_entry> uninstall_delete_entries; //! \c UninstallDeleteEntries
std::vector<directory_entry> directories; //! \c Directories
std::vector<issig_key_entry> issig_keys; //! \c ISSigKeys
std::vector<file_entry> files; //! \c Files
std::vector<icon_entry> icons; //! \c Icons
std::vector<ini_entry> ini_entries; //! \c IniEntries
@ -121,7 +110,6 @@ struct info {
std::vector<run_entry> uninstall_run_entries; //! \c UninstallRunEntries
std::vector<task_entry> tasks; //! \c Tasks
std::vector<type_entry> types; //! \c Types
std::vector<issig_key_entry> issig_keys; //! \c ISSigKeys
//! Images displayed in the installer UI.
//! Loading enabled by \c WizardImages
@ -147,7 +135,7 @@ struct info {
* \param force_codepage Windows codepage to use for strings in ANSI installers.
*/
void load(std::istream & is, entry_types entries, util::codepage_id force_codepage = 0,
boost::uint32_t loader_revision = 1);
boost::uint32_t loader_revision = 1);
std::string get_key(const std::string & password);

22
src/setup/issigkey.cpp

@ -1,3 +1,23 @@
/*
* Copyright (C) 2011-2025 Daniel Scharrer
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the author(s) be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "setup/issigkey.hpp"
#include "setup/info.hpp"
#include "util/load.hpp"
@ -10,4 +30,4 @@ void issig_key_entry::load(std::istream & is, const info & i) {
is >> util::encoded_string(runtime_id, i.codepage);
}
} // namespace setup
} // namespace setup

22
src/setup/issigkey.hpp

@ -1,3 +1,23 @@
/*
* Copyright (C) 2011-2025 Daniel Scharrer
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the author(s) be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef INNOEXTRACT_SETUP_ISSIGKEY_HPP
#define INNOEXTRACT_SETUP_ISSIGKEY_HPP
@ -18,4 +38,4 @@ struct issig_key_entry {
} // namespace setup
#endif // INNOEXTRACT_SETUP_ISSIGKEY_HPP
#endif // INNOEXTRACT_SETUP_ISSIGKEY_HPP

4
src/setup/version.hpp

@ -78,9 +78,9 @@ struct version {
void load(std::istream & is);
boost::uint16_t bits() const { return (variant & Bits16) ? 16 : 32; }
boost::uint16_t bits() const { return (variant & Bits16) ? 16 : 32; }
void set_64bit() { variant |= Bits64; }
void set_64bit() { variant |= Bits64; }
bool is_unicode() const { return (variant & Unicode) != 0; }
bool is_isx() const { return (variant & ISX) != 0; }
bool is_64bit() const { return (variant & Bits64) != 0; }

4
src/stream/block.cpp

@ -179,11 +179,11 @@ block_reader::pointer block_reader::get(std::istream & base, const setup::versio
stored_size = actual_checksum.load<boost::uint32_t>(base);
boost::uint8_t compressed = actual_checksum.load<boost::uint8_t>(base);
#ifdef DEBUG
#ifdef DEBUG
debug("" << (version.is_64bit() ? "64 bit offsets" : "32 bit offsets"));
debug("read stored_size: " << print_hex(stored_size) << " (" << stored_size << " bytes)");
debug("compressed flag: " << print_hex(boost::uint32_t(compressed)));
#endif
#endif
compression = compressed ? (version >= INNO_VERSION(4, 1, 6) ? LZMA1 : Zlib) : Stored;
} else {

4
src/stream/chunk.hpp

@ -81,9 +81,9 @@ struct chunk {
boost::uint32_t first_slice; //!< Slice where the chunk starts.
boost::uint32_t last_slice; //!< Slice where the chunk ends.
boost::uint32_t sort_offset;
boost::uint64_t sort_offset;
boost::uint32_t offset; //!< Offset of the compressed chunk in firstSlice.
boost::uint64_t offset; //!< Offset of the compressed chunk in firstSlice.
boost::uint64_t size; //! Total compressed size of the chunk.
compression_method compression; //!< Compression method used by the chunk.

6
src/stream/slice.cpp

@ -147,7 +147,7 @@ bool slice_reader::open_file(const path_type & file) {
slice_size = boost::uint32_t(slice_size_64);
if(std::streampos(slice_size_64) > file_size) {
if(slice_size_64 > boost::uint64_t(file_size)) {
ifs.close();
std::ostringstream oss;
oss << "bad slice size in " << file << ": " << slice_size_64 << " > " << file_size;
@ -247,7 +247,7 @@ void slice_reader::open(size_t slice) {
throw slice_error(oss.str());
}
bool slice_reader::seek(size_t slice, boost::uint32_t offset) {
bool slice_reader::seek(size_t slice, boost::uint64_t offset) {
seek(slice);
@ -257,7 +257,7 @@ bool slice_reader::seek(size_t slice, boost::uint32_t offset) {
return false;
}
if(is->seekg(offset).fail()) {
if(is->seekg(std::streamoff(offset)).fail()) {
return false;
}

2
src/stream/slice.hpp

@ -126,7 +126,7 @@ public:
* \return \c false if the requested slice could not be opened, or if the requested
* offset is not a valid position in that slice - \c true otherwise.
*/
bool seek(size_t slice, boost::uint32_t offset);
bool seek(size_t slice, boost::uint64_t offset);
/*!
* Read a number of bytes starting at the current slice and offset within that slice.

11
src/util/output.hpp

@ -73,7 +73,7 @@ inline std::ostream & operator<<(std::ostream & os, const if_not_empty & s) {
if(s.value.length() > 100) {
color::shell_command prev = color::current;
return os << s.name << ": " << color::white << s.value.length() << prev
<< " bytes" << '\n';
<< " bytes" << '\n';
} else if(!s.value.empty()) {
return os << s.name << ": " << quoted(s.value) << '\n';
} else {
@ -191,8 +191,7 @@ struct print_hex_dump {
size_t start_offset;
size_t bytes_per_line;
explicit print_hex_dump(const char * buffer, size_t length,
size_t offset = 0, size_t width = 16)
explicit print_hex_dump(const char * buffer, size_t length, size_t offset = 0, size_t width = 16)
: data(buffer), size(length), start_offset(offset), bytes_per_line(width) { }
};
@ -236,13 +235,11 @@ inline std::ostream & operator<<(std::ostream & os, const print_hex_dump & s) {
} // namespace detail
inline detail::print_hex_dump print_hex_dump(
const char * data, size_t size, size_t offset = 0, size_t width = 16) {
inline detail::print_hex_dump print_hex_dump(const char * data, size_t size, size_t offset = 0, size_t width = 16) {
return detail::print_hex_dump(data, size, offset, width);
}
inline detail::print_hex_dump print_hex_dump(
const std::string & data, size_t offset = 0, size_t width = 16) {
inline detail::print_hex_dump print_hex_dump(const std::string & data, size_t offset = 0, size_t width = 16) {
return print_hex_dump(data.c_str(), data.size(), offset, width);
}

Loading…
Cancel
Save