summaryrefslogtreecommitdiff
path: root/libarchive/archive_entry.c
diff options
context:
space:
mode:
authorKonrad Kleine <konrad.wilhelm.kleine@gmail.com>2013-07-01 17:12:24 +0200
committerKonrad Kleine <konrad.wilhelm.kleine@gmail.com>2013-09-17 17:17:39 +0200
commitf31a5a02722adc67186a86b300ec88eb5c687dfb (patch)
tree9eb469787697298a191b66272997a27a7e3a834d /libarchive/archive_entry.c
parent132d839fb326bae66a060dd99f4633de22ad4e1a (diff)
downloadlibarchive-f31a5a02722adc67186a86b300ec88eb5c687dfb.tar.gz
Detect encrypted archive entries (ZIP, RAR, 7Zip)
With this change you can detect if an archive entry is encrypted. The archive formats covered with this change are: ZIP, RAR, and 7zip. Other formats can be added quite simply by looking at the already supported formats. For all the already supported formats we have tests that check if: * an archive entries's data is encryped (data test) * an archive entries's metadata is encrypted (header test) * one file is encrypted while another is not (partially test) These new functions are introduced. int archive_read_format_capabilities(struct archive*) Returns a bitmask of capabilities that are supported by the archive format reader. If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned; otherwise 0 is returned. You can call this function even before reading the first header from an archive. Return Values: * ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA The reader supports detection of encrypted data. * ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA The reader supports detection of encrypted metadata (e.g. filename, modification time, size, etc.) * ARCHIVE_READ_FORMAT_CAPS_NONE None of the above capabilities. If this value is returned, this doesn't mean that the format itself doesn't support any type of encryption it simply means that the reader is not capable of detecting it. int archive_read_has_encrypted_entries(struct archive *) Returns "true" (non-zero) if the archive contains at least one encrypted entry, no matter which encryption type (data or metadata) is used; otherwise 0 is returned. You should only call this function after reading the first header from an archive. NOTE: I'm not sure that this function will stay in for long. int archive_entry_is_data_encrypted(struct archive_entry*) Returns "true" (non-zero) if the archive entry's data is encrypted; otherwise 0 is returned. You can call this function after calling archive_read_next_header(). int archive_entry_is_metadata_encrypted(struct archive_entry*) Returns "true" (non-zero) if the archive entry's metadata is encrypted; otherwise 0 is returned. You can call this function after calling archive_read_next_header(). int archive_entry_is_encrypted(struct archive_entry*) Returns "true" (non-zero) if either the archive entry's data and/or it's metadata is encrypted; otherwise 0 is returned. You can call this function after calling archive_read_next_header(). If you use archive_read_format_capabilities() in combination with one of the archive_entry_is_[data|metadata]_encrypted() functions, you can be sure that you've encountered an encrypted entry. This allows you to react differently depending on libarchive's return codes. For instance, you might want to skip encrypted files from being extracted until decryption support has been implemented. Here's how I generated the 7zip test files: ------------------------------------------- With header encrpytion (-mhe=on): $ rm -f test_read_format_7zip_encryption_header.7z $ echo "foo" > bar.txt && 7z a -mhe=on -p12345678 \ test_read_format_7zip_encryption_header.7z bar.txt $ uuencode test_read_format_7zip_encryption_header.7z \ test_read_format_7zip_encryption_header.7z > \ test_read_format_7zip_encryption_header.7z.uu Without header encrpytion (-mhe=off): $ rm -f test_read_format_7zip_encryption.7z $ echo "foo" > bar.txt && 7z a -mhe=off -p12345678 \ test_read_format_7zip_encryption.7z bar.txt $ uuencode test_read_format_7zip_encryption.7z \ test_read_format_7zip_encryption.7z > \ test_read_format_7zip_encryption.7z.uu Partially encrypted archive: $ rm -f test_read_format_7zip_encryption_partially.7z $ echo "foo" > bar_unencrypted.txt && 7z a \ test_read_format_7zip_encryption_partially.7z bar_unencrypted.txt $ echo "foo" > bar_encrypted.txt && 7z a -mhe=off -p12345678 \ test_read_format_7zip_encryption_partially.7z bar_encrypted.txt $ uuencode test_read_format_7zip_encryption_partially.7z \ test_read_format_7zip_encryption_partially.7z > \ test_read_format_7zip_encryption_partially.7z.uu Here's how I generated the RAR test files: ------------------------------------------ These are the files we can will add to the archives: echo "data of foo.txt" > foo.txt echo "data of bar.txt" > bar.txt With header encrpytion (-hp): rm -f test_read_format_rar_encryption_header.rar rar a -hp12345678 test_read_format_rar_encryption_header.rar \ foo.txt bar.txt uuencode test_read_format_rar_encryption_header.rar \ test_read_format_rar_encryption_header.rar > \ test_read_format_rar_encryption_header.rar.uu Without header encrpytion (-p): rm -f test_read_format_rar_encryption_data.rar rar a -p12345678 test_read_format_rar_encryption_data.rar \ foo.txt bar.txt uuencode test_read_format_rar_encryption_data.rar \ test_read_format_rar_encryption_data.rar > \ test_read_format_rar_encryption_data.rar.uu Partially encrypted archive (-p on "foo.txt" and no password on "bar.txt"): rm -f test_read_format_rar_encryption_partially.rar rar a -p12345678 test_read_format_rar_encryption_partially.rar foo.txt rar a test_read_format_rar_encryption_partially.rar bar.txt uuencode test_read_format_rar_encryption_partially.rar \ test_read_format_rar_encryption_partially.rar > \ test_read_format_rar_encryption_partially.rar.uu Here's how I generated the ZIP test files: ------------------------------------------ This is how I've created the test files: These are the files we will add to the archives: On Windows: echo "data of foo.txt" > foo.txt echo "data of bar.txt" > bar.txt For the creation of the Zip archives I've used the PKZIP Command Line Add-On available from here: http://comm.pkware.com/pkzip-cli-download.html With header (aka central directory) encrpytion (-cd): On Windows: del /F test_read_format_zip_encryption_header.zip pkzipc.exe -add -cryptalgorithm=AES,256 -passphrase=12345678 -cd test_read_format_zip_encryption_header.zip foo.txt bar.txt On Linux: uuencode test_read_format_zip_encryption_header.zip \ test_read_format_zip_encryption_header.zip > \ test_read_format_zip_encryption_header.zip.uu Without header encrpytion: On Windows: del /F test_read_format_zip_encryption_data.zip pkzipc.exe -add -cryptalgorithm=AES,256 -passphrase=12345678 test_read_format_zip_encryption_data.zip foo.txt bar.txt On Linux: uuencode test_read_format_zip_encryption_data.zip \ test_read_format_zip_encryption_data.zip > \ test_read_format_zip_encryption_data.zip.uu Partially encrypted archive ("foo.txt" is encrypted and "bar.txt" is not): On Windows: del /F test_read_format_zip_encryption_partially.zip pkzipc.exe -add -cryptalgorithm=AES,256 -passphrase=12345678 test_read_format_zip_encryption_partially.zip foo.txt pkzipc.exe -add test_read_format_zip_encryption_partially.zip bar.txt On Linux: uuencode test_read_format_zip_encryption_partially.zip \ test_read_format_zip_encryption_partially.zip > \ test_read_format_zip_encryption_partially.zip.uu
Diffstat (limited to 'libarchive/archive_entry.c')
-rw-r--r--libarchive/archive_entry.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c
index 386e51d4..101e61f1 100644
--- a/libarchive/archive_entry.c
+++ b/libarchive/archive_entry.c
@@ -201,6 +201,10 @@ archive_entry_clone(struct archive_entry *entry)
entry2->ae_set = entry->ae_set;
archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
+ /* Copy encryption status */
+ entry2->is_data_encrypted = entry->is_data_encrypted;
+ entry2->is_metadata_encrypted = entry->is_metadata_encrypted;
+
/* Copy ACL data over. */
archive_acl_copy(&entry2->acl, &entry->acl);
@@ -695,6 +699,25 @@ _archive_entry_uname_l(struct archive_entry *entry,
return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc));
}
+int
+archive_entry_is_data_encrypted(struct archive_entry *entry)
+{
+ return (entry && entry->is_data_encrypted);
+}
+
+int
+archive_entry_is_metadata_encrypted(struct archive_entry *entry)
+{
+ return (entry && entry->is_metadata_encrypted);
+}
+
+int
+archive_entry_is_encrypted(struct archive_entry *entry)
+{
+ return (entry && (entry->is_data_encrypted
+ || entry->is_metadata_encrypted));
+}
+
/*
* Functions to set archive_entry properties.
*/
@@ -1216,6 +1239,22 @@ archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
return (0);
}
+void
+archive_entry_set_is_data_encrypted(struct archive_entry *entry, char encrypted)
+{
+ if (entry) {
+ entry->is_data_encrypted = encrypted;
+ }
+}
+
+void
+archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char encrypted)
+{
+ if (entry) {
+ entry->is_metadata_encrypted = encrypted;
+ }
+}
+
int
_archive_entry_copy_uname_l(struct archive_entry *entry,
const char *name, size_t len, struct archive_string_conv *sc)