From: Michael Tremer Date: Sat, 20 Aug 2022 15:41:23 +0000 (+0000) Subject: archive: Drop support for signatures in archives X-Git-Tag: 0.9.28~412 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4e76c8c0e32d7fd71f55fa98f9ff75439e4dc367;p=pakfire.git archive: Drop support for signatures in archives Signed-off-by: Michael Tremer --- diff --git a/src/_pakfire/archive.c b/src/_pakfire/archive.c index c0d5e7109..882b3ed6f 100644 --- a/src/_pakfire/archive.c +++ b/src/_pakfire/archive.c @@ -106,46 +106,19 @@ static PyObject* Archive_read(ArchiveObject* self, PyObject* args) { } static PyObject* Archive_verify(ArchiveObject* self) { - pakfire_archive_verify_status_t status; + int status; // Verify this archive - int r = pakfire_archive_verify(self->archive, &status, NULL); + int r = pakfire_archive_verify(self->archive, &status); if (r) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } - // Evaluate result - switch (status) { - // Good - case PAKFIRE_ARCHIVE_VERIFY_OK: - case PAKFIRE_ARCHIVE_VERIFY_KEY_EXPIRED: - Py_RETURN_TRUE; - - // Bad - default: - PyErr_SetString(PyExc_BadSignatureError, - pakfire_archive_verify_strerror(status)); - break; - } - - return NULL; -} - -static PyObject* Archive_sign(ArchiveObject* self, PyObject* args) { - KeyObject* key = NULL; - - if (!PyArg_ParseTuple(args, "O!", &KeyType, &key)) - return NULL; - - // Create signature - int r = pakfire_archive_sign(self->archive, key->key); - if (r) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - Py_RETURN_NONE; + if (status) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; } static PyObject* Archive_extract(ArchiveObject* self) { @@ -246,12 +219,6 @@ static struct PyMethodDef Archive_methods[] = { METH_VARARGS, NULL }, - { - "sign", - (PyCFunction)Archive_sign, - METH_VARARGS, - NULL - }, { "verify", (PyCFunction)Archive_verify, diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index 53f8c50b7..fb192e53a 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -59,11 +59,6 @@ #include #include -enum pakfire_archive_verify_flags { - PAKFIRE_ARCHIVE_VERIFY_ALL, - PAKFIRE_ARCHIVE_VERIFY_BEST, -}; - static const char* pakfire_archive_files_without_chksums[] = { "pakfire-format", "chksums", @@ -173,8 +168,7 @@ ERROR: static int pakfire_archive_walk_entries(struct pakfire_archive* archive, struct archive* a, int (*callback)(struct pakfire_archive* archive, struct archive* a, - struct archive_entry* e, int flags, void* data), - int flags, void* data, off_t* offset) { + struct archive_entry* e, void* data), void* data) { struct archive_entry* e = NULL; // Walk through the archive @@ -182,12 +176,8 @@ static int pakfire_archive_walk_entries(struct pakfire_archive* archive, struct int r = archive_read_next_header(a, &e); // Return OK when we reached the end of the archive - if (r == ARCHIVE_EOF) { - if (offset) - *offset = archive_read_header_position(a); - + if (r == ARCHIVE_EOF) return ARCHIVE_OK; - } // Raise any other errors else if (r) @@ -195,7 +185,7 @@ static int pakfire_archive_walk_entries(struct pakfire_archive* archive, struct // Run callback if (callback) { - r = callback(archive, a, e, flags, data); + r = callback(archive, a, e, data); if (r) return r; } @@ -206,8 +196,7 @@ static int pakfire_archive_walk_entries(struct pakfire_archive* archive, struct static int pakfire_archive_walk(struct pakfire_archive* archive, int (*callback)(struct pakfire_archive* archive, struct archive* a, - struct archive_entry* e, int flags, void* data), - int flags, void* data, off_t* offset) { + struct archive_entry* e, void* data), void* data) { struct archive* a; // Open the archive file @@ -216,7 +205,7 @@ static int pakfire_archive_walk(struct pakfire_archive* archive, return r; // Walk through the archive - r = pakfire_archive_walk_entries(archive, a, callback, flags, data, offset); + r = pakfire_archive_walk_entries(archive, a, callback, data); // Close the archive close_archive(archive, a); @@ -293,13 +282,6 @@ static int open_archive_and_read(struct pakfire_archive* archive, const char* fi return r; } -/* - This function finds the end of the archive so that we can append more files -*/ -static off_t pakfire_archive_find_end(struct pakfire_archive* archive, off_t* offset) { - return pakfire_archive_walk(archive, NULL, 0, NULL, offset); -} - static la_ssize_t pakfire_archive_read_callback(struct archive* a, void* client_data, const void** buffer) { struct archive* archive = (struct archive*)client_data; @@ -1256,26 +1238,7 @@ struct pakfire_archive_validator { }; static int pakfire_archive_verify_add_validator(struct pakfire_archive_validator*** list, - struct pakfire* pakfire, const EVP_MD* md, const unsigned char* digest, - enum pakfire_archive_verify_flags flags) { - - switch (flags) { - // Fall through and add the validator - case PAKFIRE_ARCHIVE_VERIFY_ALL: - break; - - // We only accept one validator, so this function becomes a no-op when list - // has any validators already - case PAKFIRE_ARCHIVE_VERIFY_BEST: - if (*list) - return 0; - break; - - default: - errno = EINVAL; - return 1; - } - + struct pakfire* pakfire, const EVP_MD* md, const unsigned char* digest) { // Allocate validator struct pakfire_archive_validator* v = calloc(1, sizeof(*v)); if (!v) @@ -1335,13 +1298,9 @@ ERROR: } static int pakfire_archive_verify_file(struct pakfire_archive* archive, - struct archive* a, struct archive_entry* entry, int flags, void* data) { + struct archive* a, struct archive_entry* entry, void* data) { const char* path = archive_entry_pathname(entry); - // Signatures do not have checksums - if (pakfire_string_startswith(path, "signatures/")) - return 0; - // Some files do not have checksums for (const char** file = pakfire_archive_files_without_chksums; *file; file++) { if (strcmp(*file, path) == 0) @@ -1361,7 +1320,7 @@ static int pakfire_archive_verify_file(struct pakfire_archive* archive, // SHA512 if (pakfire_archive_chksum_has_digest(chksum->digest_sha512)) { r = pakfire_archive_verify_add_validator(&validators, archive->pakfire, - EVP_sha512(), chksum->digest_sha512, flags); + EVP_sha512(), chksum->digest_sha512); if (r) return r; } @@ -1369,7 +1328,7 @@ static int pakfire_archive_verify_file(struct pakfire_archive* archive, // SHA256 if (pakfire_archive_chksum_has_digest(chksum->digest_sha256)) { r = pakfire_archive_verify_add_validator(&validators, archive->pakfire, - EVP_sha256(), chksum->digest_sha256, flags); + EVP_sha256(), chksum->digest_sha256); if (r) return r; } @@ -1464,7 +1423,7 @@ ERROR: return r; } -static int pakfire_archive_verify_checksums(struct pakfire_archive* archive, int flags) { +PAKFIRE_EXPORT int pakfire_archive_verify(struct pakfire_archive* archive, int* status) { int r; // Read checksums from archive @@ -1473,7 +1432,7 @@ static int pakfire_archive_verify_checksums(struct pakfire_archive* archive, int return r; // Iterate over all files and verify them if a checksum is present - r = pakfire_archive_walk(archive, pakfire_archive_verify_file, flags, NULL, NULL); + r = pakfire_archive_walk(archive, pakfire_archive_verify_file, NULL); if (r) { ERROR(archive->pakfire, "File verification failed\n"); return r; @@ -1482,392 +1441,6 @@ static int pakfire_archive_verify_checksums(struct pakfire_archive* archive, int return 0; } -struct pakfire_archive_signature_check { - gpgme_data_t checksums; -}; - -/* - This function is called to examine whether we have a signature and if so verify it -*/ -static int pakfire_archive_verify_signature(struct pakfire_archive* archive, struct archive* a, - struct archive_entry* e, int flags, void* data) { - const char* entry_name = archive_entry_pathname(e); - - // This is not a signature - if (!pakfire_string_startswith(entry_name, "signatures/")) - return 0; - - // Fetch GPGME context - gpgme_ctx_t gpgctx = pakfire_get_gpgctx(archive->pakfire); - if (!gpgctx) - return 1; - - struct pakfire_archive_signature_check* check = (struct pakfire_archive_signature_check*)data; - - char* buffer = NULL; - size_t size = 0; - - // Load the signature into memory - int r = pakfire_archive_copy_data_to_buffer(archive->pakfire, a, e, &buffer, &size); - if (r) - return 1; - - gpgme_data_t signature; - gpgme_error_t error; - - // Make signature readable for GPGME - error = gpgme_data_new_from_mem(&signature, buffer, size, 0); - if (error != GPG_ERR_NO_ERROR) { - r = 1; - goto ERROR; - } - - // Perform verification - error = gpgme_op_verify(gpgctx, signature, check->checksums, NULL); - if (error != GPG_ERR_NO_ERROR) - goto ERROR; - - // Run the operation - gpgme_verify_result_t result = gpgme_op_verify_result(gpgctx); - - // Check if any signatures have been returned - if (!result || !result->signatures) - goto ERROR; - - // Walk through all signatures - for (gpgme_signature_t sig = result->signatures; sig; sig = sig->next) { - // Log some information about this signature - DEBUG(archive->pakfire, "Found signature %s\n", sig->fpr); - DEBUG(archive->pakfire, " Status : %s\n", gpgme_strerror(sig->status)); - DEBUG(archive->pakfire, " Timestamp : %lu\n", sig->timestamp); - if (sig->exp_timestamp) - DEBUG(archive->pakfire, " Expires : %lu\n", sig->exp_timestamp); - DEBUG(archive->pakfire, " Validity : %s\n", gpgme_strerror(sig->validity_reason)); - - switch (gpg_err_code(sig->status)) { - // All good - case GPG_ERR_NO_ERROR: - archive->verify = PAKFIRE_ARCHIVE_VERIFY_OK; - break; - - // Key has expired (still good) - case GPG_ERR_KEY_EXPIRED: - archive->verify = PAKFIRE_ARCHIVE_VERIFY_KEY_EXPIRED; - break; - - // Signature has expired (bad) - case GPG_ERR_SIG_EXPIRED: - archive->verify = PAKFIRE_ARCHIVE_VERIFY_SIG_EXPIRED; - break; - - // We don't have the key - case GPG_ERR_NO_PUBKEY: - archive->verify = PAKFIRE_ARCHIVE_VERIFY_KEY_UNKNOWN; - break; - - // Bad signature (or any other errors) - case GPG_ERR_BAD_SIGNATURE: - default: - archive->verify = PAKFIRE_ARCHIVE_VERIFY_INVALID; - break; - } - } - -ERROR: - // Free signature - gpgme_data_release(signature); - if (buffer) - free(buffer); - - return r; -} - -/* - This function walks through the archive looking for signatures and verifies them -*/ -static int pakfire_archive_verify_signatures(struct pakfire_archive* archive, - struct pakfire_key*** keys) { - char* buffer = NULL; - size_t size = 0; - - // Fetch GPGME context (to initialize GPGME) - gpgme_ctx_t gpgctx = pakfire_get_gpgctx(archive->pakfire); - if (!gpgctx) - return 1; - - // Find checksums - int r = open_archive_and_read(archive, "chksums", &buffer, &size); - if (r) { - ERROR(archive->pakfire, "Could not open chksums file: %m\n"); - return r; - } - - struct pakfire_archive_signature_check check; - - // Convert checksums readable for GPGME - gpgme_error_t error = gpgme_data_new_from_mem(&check.checksums, buffer, size, 0); - if (error != GPG_ERR_NO_ERROR) { - ERROR(archive->pakfire, "Could not initialize chksums: %s\n", gpgme_strerror(error)); - r = 1; - goto ERROR; - } - - // No signatures yet (will be reset later, maybe) - archive->verify = PAKFIRE_ARCHIVE_VERIFY_NOT_SIGNED; - - // Verify all signatures - r = pakfire_archive_walk(archive, pakfire_archive_verify_signature, 0, &check, NULL); - -ERROR: - gpgme_data_release(check.checksums); - if (buffer) - free(buffer); - - return r; -} - -PAKFIRE_EXPORT int pakfire_archive_verify(struct pakfire_archive* archive, - pakfire_archive_verify_status_t* status, struct pakfire_key*** keys) { - int r; - - DEBUG(archive->pakfire, "Verifying archive %p\n", archive); - - // Return previous result if this has already been called - if (archive->verify == PAKFIRE_ARCHIVE_VERIFY_UNKNOWN) { - // Verify all signatures - r = pakfire_archive_verify_signatures(archive, keys); - if (r) - goto ERROR; - - // Verify checksums - r = pakfire_archive_verify_checksums(archive, PAKFIRE_ARCHIVE_VERIFY_BEST); - if (r) - goto ERROR; - } - - // Store result - *status = archive->verify; - - // Log error - ERROR(archive->pakfire, "Archive verification for %s has failed: %s\n", - archive->path, pakfire_archive_verify_strerror(archive->verify)); - - return 0; - -ERROR: - if (keys && *keys) { - for (struct pakfire_key** key = *keys; *key; key++) - pakfire_key_unref(*key); - free(*keys); - } - - return r; -} - -PAKFIRE_EXPORT const char* pakfire_archive_verify_strerror(pakfire_archive_verify_status_t status) { - switch (status) { - case PAKFIRE_ARCHIVE_VERIFY_UNKNOWN: - return _("Unknown"); - - case PAKFIRE_ARCHIVE_VERIFY_NOT_SIGNED: - return _("Not signed"); - - case PAKFIRE_ARCHIVE_VERIFY_OK: - return _("Verify OK"); - - case PAKFIRE_ARCHIVE_VERIFY_ERROR: - return _("Error performing validation"); - - case PAKFIRE_ARCHIVE_VERIFY_INVALID: - return _("Invalid signature"); - - case PAKFIRE_ARCHIVE_VERIFY_SIG_EXPIRED: - return _("Signature expired"); - - case PAKFIRE_ARCHIVE_VERIFY_KEY_EXPIRED: - return _("Key expired"); - - case PAKFIRE_ARCHIVE_VERIFY_KEY_UNKNOWN: - return _("Key unknown"); - } - - return _("Unknown error"); -} - -static int pakfire_archive_create_signature(struct pakfire_archive* archive, - struct pakfire_key* key, char** signature, size_t* signature_length, time_t* timestamp) { - char* buffer = NULL; - size_t length = 0; - - // Read chksums - int r = open_archive_and_read(archive, "chksums", &buffer, &length); - if (r) { - ERROR(archive->pakfire, "Could not read chksums file: %m\n"); - goto ERROR; - } - - // Use the key to sign the buffer - r = pakfire_key_sign(key, buffer, length, signature, signature_length, timestamp); - if (r) - goto ERROR; - -ERROR: - if (buffer) - free(buffer); - - return r; -} - -/* - This function appends a single file to the archive - - Unfortunately libarchive cannot do this, so we have to manually find the end of the - archive and write another entry... -*/ -static int pakfire_archive_append_file(struct pakfire_archive* archive, - struct archive_entry* entry, const char* buffer, const size_t length) { - off_t offset = 0; - - // Find the end of the archive (exclusing the tar trailer) - int r = pakfire_archive_find_end(archive, &offset); - if (r) - return r; - - // Create a new archive writer - struct archive* a = archive_write_new(); - if (!a) { - ERROR(archive->pakfire, "Could not create an archive writer: %m\n"); - return 1; - } - - // Use the PAX format - r = archive_write_set_format_pax(a); - if (r) { - ERROR(archive->pakfire, "Could not set format to PAX: %s\n", archive_error_string(a)); - goto ERROR; - } - - // Seek to the end of the archive - r = fseek(archive->f, offset, SEEK_SET); - if (r) { - ERROR(archive->pakfire, "Could not seek to position %jd in archive: %m\n", offset); - return r; - } - - // Write archive to f - r = archive_write_open_FILE(a, archive->f); - if (r) { - ERROR(archive->pakfire, "archive_write_open_FILE() failed: %s\n", - archive_error_string(a)); - goto ERROR; - } - - // Write the header - r = archive_write_header(a, entry); - if (r) { - ERROR(archive->pakfire, "Error writing file header: %s\n", - archive_error_string(a)); - goto ERROR; - } - - // Write the payload - ssize_t bytes_written = archive_write_data(a, buffer, length); - if (bytes_written < 0) { - ERROR(archive->pakfire, "Error writing data: %s\n", - archive_error_string(a)); - goto ERROR; - } - - // Finish writing - r = archive_write_finish_entry(a); - if (r) { - ERROR(archive->pakfire, "Could not finish entry: %s\n", - archive_error_string(a)); - goto ERROR; - } - - // Success - r = 0; - -ERROR: - archive_write_free(a); - - return r; -} - -static int pakfire_archive_append_signature(struct pakfire_archive* archive, - struct pakfire_key* key, const char* signature, size_t length, time_t timestamp) { - char path[PATH_MAX]; - int r; - - // Make filename - r = pakfire_string_format(path, "signatures/%s", pakfire_key_get_fingerprint(key)); - if (r) - return r; - - // Create a new file entry - struct archive_entry* entry = archive_entry_new(); - if (!entry) - return 1; - - // Set filename - archive_entry_set_pathname(entry, path); - - // This is a regular file - archive_entry_set_filetype(entry, AE_IFREG); - archive_entry_set_perm(entry, 0444); - - // Set size - archive_entry_set_size(entry, length); - - // Set ownership - archive_entry_set_uname(entry, "root"); - archive_entry_set_uid(entry, 0); - archive_entry_set_gname(entry, "root"); - archive_entry_set_gid(entry, 0); - - // Set times - archive_entry_set_birthtime(entry, timestamp, 0); - archive_entry_set_ctime(entry, timestamp, 0); - archive_entry_set_mtime(entry, timestamp, 0); - archive_entry_set_atime(entry, timestamp, 0); - - // Write entry - r = pakfire_archive_append_file(archive, entry, signature, length); - archive_entry_free(entry); - - return r; -} - -PAKFIRE_EXPORT int pakfire_archive_sign(struct pakfire_archive* archive, struct pakfire_key* key) { - int r; - - // Verify checksums - r = pakfire_archive_verify_checksums(archive, PAKFIRE_ARCHIVE_VERIFY_ALL); - if (r) { - ERROR(archive->pakfire, "The archive checksums don't match\n"); - return r; - } - - char* signature = NULL; - size_t signature_length = 0; - time_t timestamp = 0; - - // Create the signature - r = pakfire_archive_create_signature(archive, key, - &signature, &signature_length, ×tamp); - if (r) - return r; - - // Append signature to archive - r = pakfire_archive_append_signature(archive, key, - signature, signature_length, timestamp); - if (r) - return r; - - return 0; -} - PAKFIRE_EXPORT ssize_t pakfire_archive_get_size(struct pakfire_archive* archive) { struct stat buf; @@ -2365,7 +1938,7 @@ PAKFIRE_EXPORT int pakfire_archive_make_package(struct pakfire_archive* archive, } static int pakfire_archive_load_scriptlet(struct pakfire_archive* archive, - struct archive* a, struct archive_entry* e, int flags, void* data) { + struct archive* a, struct archive_entry* e, void* data) { const char* path = archive_entry_pathname(e); // Skip if this isn't a scriptlet @@ -2411,7 +1984,7 @@ static int pakfire_archive_load_scriptlets(struct pakfire_archive* archive) { int counter = 0; - return pakfire_archive_walk(archive, pakfire_archive_load_scriptlet, 0, &counter, NULL); + return pakfire_archive_walk(archive, pakfire_archive_load_scriptlet, &counter); } struct pakfire_scriptlet* pakfire_archive_get_scriptlet( diff --git a/src/libpakfire/include/pakfire/archive.h b/src/libpakfire/include/pakfire/archive.h index c12eebf3c..e23a2dea0 100644 --- a/src/libpakfire/include/pakfire/archive.h +++ b/src/libpakfire/include/pakfire/archive.h @@ -26,22 +26,10 @@ struct pakfire_archive; #include -#include #include #include #include -typedef enum pakfire_archive_verify_status { - PAKFIRE_ARCHIVE_VERIFY_UNKNOWN = 0, - PAKFIRE_ARCHIVE_VERIFY_NOT_SIGNED, - PAKFIRE_ARCHIVE_VERIFY_OK, - PAKFIRE_ARCHIVE_VERIFY_INVALID, - PAKFIRE_ARCHIVE_VERIFY_SIG_EXPIRED, - PAKFIRE_ARCHIVE_VERIFY_KEY_EXPIRED, - PAKFIRE_ARCHIVE_VERIFY_KEY_UNKNOWN, - PAKFIRE_ARCHIVE_VERIFY_ERROR, -} pakfire_archive_verify_status_t; - int pakfire_archive_open(struct pakfire_archive** archive, struct pakfire* pakfire, const char* path); struct pakfire_archive* pakfire_archive_ref(struct pakfire_archive* archive); struct pakfire_archive* pakfire_archive_unref(struct pakfire_archive* archive); @@ -58,10 +46,7 @@ unsigned int pakfire_archive_get_format(struct pakfire_archive* archive); struct pakfire_filelist* pakfire_archive_get_filelist(struct pakfire_archive* archive); -int pakfire_archive_verify(struct pakfire_archive* archive, - pakfire_archive_verify_status_t* status, struct pakfire_key*** keys); -const char* pakfire_archive_verify_strerror(pakfire_archive_verify_status_t status); -int pakfire_archive_sign(struct pakfire_archive* archive, struct pakfire_key* key); +int pakfire_archive_verify(struct pakfire_archive* archive, int* status); ssize_t pakfire_archive_get_size(struct pakfire_archive* archive); int pakfire_archive_make_package(struct pakfire_archive* archive, diff --git a/src/libpakfire/libpakfire.sym b/src/libpakfire/libpakfire.sym index 305db5927..34ef59c7b 100644 --- a/src/libpakfire/libpakfire.sym +++ b/src/libpakfire/libpakfire.sym @@ -50,7 +50,6 @@ global: pakfire_arch_supported; # archive - pakfire_archive_count_signatures; pakfire_archive_extract; pakfire_archive_get; pakfire_archive_get_filelist; @@ -62,10 +61,8 @@ global: pakfire_archive_open; pakfire_archive_read; pakfire_archive_ref; - pakfire_archive_sign; pakfire_archive_unref; pakfire_archive_verify; - pakfire_archive_verify_strerror; # build pakfire_build;