struct pakfire_scriptlet** scriptlets;
size_t nscriptlets;
+ // Verify Status
+ int verify;
};
struct _PakfireArchiveSignature {
return status;
}
+/*
+ This function is called to examine whether we have a signature and if so verify it
+*/
+static int pakfire_archive_verify_signature(PakfireArchive archive, struct archive* a,
+ struct archive_entry* e, 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;
+
+ gpgme_data_t* checksums = (gpgme_data_t*)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;
+ }
+
+ printf("GOT HERE\n");
+
+ // Perform verification
+ error = gpgme_op_verify(gpgctx, signature, *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;
+
+ // XXX This is some old code and does not entirely do what is desired, yet
+ int status = 0;
+
+ // Walk through all signatures
+ for (gpgme_signature_t sig = result->signatures; sig; sig = sig->next) {
+ switch (gpg_err_code(sig->status)) {
+ // All good
+ case GPG_ERR_NO_ERROR:
+ status = PAKFIRE_ARCHIVE_VERIFY_OK;
+ break;
+
+ // Key has expired (still good)
+ case GPG_ERR_KEY_EXPIRED:
+ status = PAKFIRE_ARCHIVE_VERIFY_KEY_EXPIRED;
+ break;
+
+ // Signature has expired (bad)
+ case GPG_ERR_SIG_EXPIRED:
+ status = PAKFIRE_ARCHIVE_VERIFY_SIG_EXPIRED;
+ break;
+
+ // We don't have the key
+ case GPG_ERR_NO_PUBKEY:
+ status = PAKFIRE_ARCHIVE_VERIFY_KEY_UNKNOWN;
+ break;
+
+ // Bad signature (or any other errors)
+ case GPG_ERR_BAD_SIGNATURE:
+ default:
+ status = 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(PakfireArchive archive) {
+ char* buffer = NULL;
+ size_t size = 0;
+
+ // 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;
+ }
+
+ gpgme_data_t checksums;
+
+ // Convert checksums readable for GPGME
+ gpgme_error_t error = gpgme_data_new_from_mem(&checksums, buffer, size, 0);
+ if (error != GPG_ERR_NO_ERROR) {
+ r = 1;
+ goto ERROR;
+ }
+
+ // Verify all signatures
+ r = pakfire_archive_walk(archive, pakfire_archive_verify_signature, &checksums);
+
+ERROR:
+ gpgme_data_release(checksums);
+ if (buffer)
+ free(buffer);
+
+ return r;
+}
+
PAKFIRE_EXPORT pakfire_archive_verify_status_t pakfire_archive_verify(PakfireArchive archive) {
DEBUG(archive->pakfire, "Verifying archive %p\n", archive);
+ // Return previous result if this has already been called
+ if (archive->verify != PAKFIRE_ARCHIVE_VERIFY_UNKNOWN)
+ return archive->verify;
+
+ int r = pakfire_archive_verify_signatures(archive);
+ if (r)
+ return r;
+
return PAKFIRE_ARCHIVE_VERIFY_OK; // XXX DEBUG
// Verify that checksums file is signed with a valid key
// Open the archive file
struct archive* a;
- int r = open_archive(archive, &a);
+ r = open_archive(archive, &a);
if (r)
return PAKFIRE_ARCHIVE_VERIFY_ERROR;