return NULL;
}
-static PyObject* Archive_get_signatures(ArchiveObject* self) {
- PyObject* list = PyList_New(0);
-
- PakfireArchiveSignature* head = pakfire_archive_get_signatures(self->archive);
-
- PakfireArchiveSignature* signatures = head;
- while (signatures && *signatures) {
- PakfireArchiveSignature signature = *signatures++;
-
- PyObject* object = new_archive_signature(self, signature);
- PyList_Append(list, object);
-
- Py_DECREF(object);
- }
-
- return list;
-}
-
static PyObject* Archive_extract(ArchiveObject* self, PyObject* args) {
const char* prefix = NULL;
NULL,
NULL
},
- {
- "signatures",
- (getter)Archive_get_signatures,
- NULL,
- NULL,
- NULL
- },
{ NULL },
};
//tp_str: (reprfunc)Archive_str,
//tp_richcompare: (richcmpfunc)Archive_richcompare,
};
-
-// Archive Signature
-
-static PyObject* ArchiveSignature_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
- ArchiveSignatureObject* self = (ArchiveSignatureObject *)type->tp_alloc(type, 0);
- if (self) {
- self->signature = NULL;
- }
-
- return (PyObject *)self;
-}
-
-PyObject* new_archive_signature(ArchiveObject* archive, PakfireArchiveSignature signature) {
- ArchiveSignatureObject* s = (ArchiveSignatureObject*)ArchiveSignature_new(&ArchiveSignatureType, NULL, NULL);
- if (s)
- s->signature = pakfire_archive_signature_ref(signature);
-
- return (PyObject *)s;
-}
-
-static void ArchiveSignature_dealloc(ArchiveSignatureObject* self) {
- if (self->signature)
- pakfire_archive_signature_unref(self->signature);
-
- Py_TYPE(self)->tp_free((PyObject *)self);
-}
-
-static PyObject* ArchiveSignature_str(ArchiveSignatureObject* self) {
- const char* data = pakfire_archive_signature_get_data(self->signature);
-
- return PyUnicode_FromString(data);
-}
-
-static struct PyGetSetDef ArchiveSignature_getsetters[] = {
- { NULL },
-};
-
-PyTypeObject ArchiveSignatureType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- tp_name: "_pakfire.ArchiveSignature",
- tp_basicsize: sizeof(ArchiveSignatureObject),
- tp_flags: Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
- tp_new: ArchiveSignature_new,
- tp_dealloc: (destructor)ArchiveSignature_dealloc,
- tp_doc: "ArchiveSignature object",
- tp_getset: ArchiveSignature_getsetters,
- tp_str: (reprfunc)ArchiveSignature_str,
-};
// Checksums
STAILQ_HEAD(chksums, pakfire_archive_chksum) chksums;
- // Signatures
- PakfireArchiveSignature* signatures;
- int signatures_loaded;
-
// Scriptlets
struct pakfire_scriptlet** scriptlets;
size_t nscriptlets;
int verify;
};
-struct _PakfireArchiveSignature {
- Pakfire pakfire;
- struct pakfire_key* key;
- char* sigdata;
- int nrefs;
-};
-
/*
A helper function to close the archive and reset our data structures
*/
return NULL;
}
-// Signature Stuff
-
-static PakfireArchiveSignature pakfire_archive_signature_create(PakfireArchive archive, const char* sigdata) {
- PakfireArchiveSignature signature = calloc(1, sizeof(*signature));
- if (signature) {
- signature->pakfire = pakfire_ref(archive->pakfire);
- signature->nrefs = 1;
- signature->sigdata = strdup(sigdata);
- }
-
- return signature;
-}
-
-static void pakfire_archive_signature_free(PakfireArchiveSignature signature) {
- pakfire_unref(signature->pakfire);
-
- if (signature->key)
- pakfire_key_unref(signature->key);
-
- free(signature->sigdata);
- free(signature);
-}
-
-PAKFIRE_EXPORT PakfireArchiveSignature pakfire_archive_signature_ref(PakfireArchiveSignature signature) {
- ++signature->nrefs;
-
- return signature;
-}
-
-PAKFIRE_EXPORT void pakfire_archive_signature_unref(PakfireArchiveSignature signature) {
- if (--signature->nrefs > 0)
- return;
-
- pakfire_archive_signature_free(signature);
-}
-
-static size_t _pakfire_archive_count_signatures(const PakfireArchiveSignature* signatures) {
- size_t i = 0;
-
- while (signatures && *signatures++) {
- i++;
- }
-
- return i;
-}
-
-PAKFIRE_EXPORT size_t pakfire_archive_count_signatures(PakfireArchive archive) {
- PakfireArchiveSignature* signatures = pakfire_archive_get_signatures(archive);
-
- return _pakfire_archive_count_signatures(signatures);
-}
-
static void pakfire_archive_free_chksums(PakfireArchive archive) {
struct pakfire_archive_chksum* chksum;
// Free all checksums
pakfire_archive_free_chksums(archive);
- // Free signatures
- if (archive->signatures) {
- PakfireArchiveSignature* signatures = archive->signatures;
- while (signatures && *signatures)
- pakfire_archive_signature_unref(*signatures++);
-
- free(archive->signatures);
- }
-
// Free scriptlets
if (archive->scriptlets) {
for (unsigned int i = 0; i < archive->nscriptlets; i++)
return pakfire_filelist_ref(archive->filelist);
}
-PAKFIRE_EXPORT const char* pakfire_archive_signature_get_data(PakfireArchiveSignature signature) {
- return signature->sigdata;
-}
-
-static int pakfire_archive_parse_entry_signature(PakfireArchive archive,
- struct archive* a, struct archive_entry* e) {
- char* data;
- size_t data_size;
-
- int r = pakfire_archive_copy_data_to_buffer(archive->pakfire, a, e, &data, &data_size);
- if (r)
- return 1;
-
- // Terminate string.
- data[data_size] = '\0';
-
- PakfireArchiveSignature signature = pakfire_archive_signature_create(archive, data);
- if (!signature)
- return 1;
-
- if (archive->signatures) {
- // Count signatures
- size_t num_signatures = _pakfire_archive_count_signatures(archive->signatures) + 1;
-
- // Resize the array
- archive->signatures = realloc(archive->signatures, sizeof(*archive->signatures) * num_signatures);
- } else {
- archive->signatures = calloc(2, sizeof(*archive->signatures));
- }
-
- // Look for last element
- PakfireArchiveSignature* signatures = archive->signatures;
- while (signatures && *signatures) {
- *signatures++;
- }
-
- // Append signature
- *signatures++ = signature;
-
- // Terminate list
- *signatures = NULL;
-
- return 0;
-}
-
-static int pakfire_archive_read_signature_entry(PakfireArchive archive, struct archive* a, struct archive_entry* e, void* data) {
- const char* entry_name = archive_entry_pathname(e);
-
- if (strncmp(PAKFIRE_ARCHIVE_FN_SIGNATURES, entry_name, strlen(PAKFIRE_ARCHIVE_FN_SIGNATURES)) == 0) {
- int ret = pakfire_archive_parse_entry_signature(archive, a, e);
- if (ret)
- return EINVAL;
- }
-
- return 0;
-}
-
-static int pakfire_archive_load_signatures(PakfireArchive archive) {
- DEBUG(archive->pakfire, "Loading all signatures for archive at %p\n", archive);
-
- return pakfire_archive_walk(archive, pakfire_archive_read_signature_entry, NULL);
-}
-
-PAKFIRE_EXPORT PakfireArchiveSignature* pakfire_archive_get_signatures(PakfireArchive archive) {
- if (!archive->signatures_loaded++)
- pakfire_archive_load_signatures(archive);
-
- return archive->signatures;
-}
-
-static pakfire_archive_verify_status_t pakfire_archive_verify_checksums(PakfireArchive archive) {
- DEBUG(archive->pakfire, "Verifying checksums of %p\n", archive);
-
- // Cannot validate anything if no signatures are available
- PakfireArchiveSignature* signatures = pakfire_archive_get_signatures(archive);
- if (!signatures) {
- ERROR(archive->pakfire, "Archive %p does not have any signatures\n", archive);
- return PAKFIRE_ARCHIVE_VERIFY_NO_SIGNATURES;
- }
-
- pakfire_archive_verify_status_t status = PAKFIRE_ARCHIVE_VERIFY_INVALID;
- const char* data = NULL;
- size_t size = 0;
- gpgme_error_t error;
-
- // Load the checksums file
- int r = pakfire_archive_read(archive, PAKFIRE_ARCHIVE_FN_CHECKSUMS,
- (void *)&data, &size);
- if (r) {
- ERROR(archive->pakfire, "Could not read %s from archive %p\n",
- PAKFIRE_ARCHIVE_FN_CHECKSUMS, archive);
- return status;
- }
-
- // Get GPG context
- gpgme_ctx_t gpgctx = pakfire_get_gpgctx(archive->pakfire);
-
- // Convert into gpgme data object
- gpgme_data_t signed_text;
- error = gpgme_data_new_from_mem(&signed_text, data, size, 0);
- if (error != GPG_ERR_NO_ERROR) {
- ERROR(archive->pakfire, "Could not load signed text: %s\n%s\n",
- gpgme_strerror(status), data);
- goto ABORT;
- }
-
- // Try for each signature
- while (signatures && *signatures) {
- PakfireArchiveSignature signature = *signatures++;
-
- gpgme_data_t sigdata;
- error = gpgme_data_new_from_mem(&sigdata, signature->sigdata, strlen(signature->sigdata), 0);
- if (error != GPG_ERR_NO_ERROR) {
- ERROR(archive->pakfire, "Could not load signature:\n%s\n", signature->sigdata);
- continue;
- }
-
- DEBUG(archive->pakfire, "Validating signature %p\n", signature);
-
- // Perform verification
- error = gpgme_op_verify(gpgctx, sigdata, signed_text, NULL);
- if (error != GPG_ERR_NO_ERROR)
- goto CLEANUP;
-
- // 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 CLEANUP;
-
- // 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;
- }
- }
-
-CLEANUP:
- gpgme_data_release(sigdata);
- }
-
- gpgme_data_release(signed_text);
-
-ABORT:
- gpgme_release(gpgctx);
-
- DEBUG(archive->pakfire, "Checksum verification status: %s\n",
- pakfire_archive_verify_strerror(status));
-
- return status;
-}
-
static pakfire_archive_verify_status_t pakfire_archive_verify_file(Pakfire pakfire,
struct archive* a, const struct pakfire_archive_chksum* chksum) {
pakfire_archive_verify_status_t status = PAKFIRE_ARCHIVE_VERIFY_ERROR;
return PAKFIRE_ARCHIVE_VERIFY_OK; // XXX DEBUG
- // Verify that checksums file is signed with a valid key
- pakfire_archive_verify_status_t status = pakfire_archive_verify_checksums(archive);
- if (status)
- return status;
+ int status = 0;
// Open the archive file
struct archive* a;