# #
#############################################################################*/
-#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <gpgme.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/queue.h>
#include <sys/types.h>
#include <sys/stat.h>
#define BLOCKSIZE 1024 * 1024 // 1MB
-typedef struct archive_checksum {
- Pakfire pakfire;
- char* filename;
+struct pakfire_archive_chksum {
+ STAILQ_ENTRY(pakfire_archive_chksum) nodes;
+
+ char path[PATH_MAX];
archive_checksum_algo_t algo;
unsigned char digest[EVP_MAX_MD_SIZE];
-} archive_checksum_t;
+};
struct _PakfireArchive {
Pakfire pakfire;
PakfireParser parser;
PakfireFilelist filelist;
- archive_checksum_t** checksums;
+
+ // Checksums
+ STAILQ_HEAD(chksums, pakfire_archive_chksum) chksums;
// Signatures
PakfireArchiveSignature* signatures;
return archive_read_open1(*a);
}
+// Checksum Stuff
+
static const char* checksum_algo_string(archive_checksum_algo_t algo) {
switch (algo) {
case PAKFIRE_CHECKSUM_SHA512:
return 0;
}
-static void pakfire_archive_checksum_free(archive_checksum_t* c) {
- DEBUG(c->pakfire, "Releasing archive checksum at %p\n", c);
+static int pakfire_archive_add_chksum(PakfireArchive archive, const char* path,
+ archive_checksum_algo_t algo, const char* hexdigest) {
+ int r = 1;
- pakfire_unref(c->pakfire);
- free(c->filename);
- free(c);
-}
+ // Allocate a new chksum object
+ struct pakfire_archive_chksum* chksum = calloc(1, sizeof(*chksum));
+ if (!chksum)
+ return ENOMEM;
-static archive_checksum_t* pakfire_archive_checksum_create(Pakfire pakfire, const char* filename, archive_checksum_algo_t algo, const char* s) {
- archive_checksum_t* c = calloc(1, sizeof(*c));
- if (c) {
- c->pakfire = pakfire_ref(pakfire);
- c->filename = strdup(filename);
- c->algo = algo;
-
- int r = read_hexdigest(c->digest, sizeof(c->digest), s);
- if (r) {
- pakfire_archive_checksum_free(c);
- return NULL;
- }
+ // Store path
+ r = pakfire_string_set(chksum->path, path);
+ if (r < 0)
+ goto ERROR;
- DEBUG(c->pakfire, "Allocated archive checksum for %s (%s)\n",
- c->filename, checksum_algo_string(c->algo));
- }
+ // Store algo
+ chksum->algo = algo;
- return c;
-}
+ // Store hexdigest as digest
+ r = read_hexdigest(chksum->digest, sizeof(chksum->digest), hexdigest);
+ if (r)
+ goto ERROR;
+
+ // Append it
+ STAILQ_INSERT_TAIL(&archive->chksums, chksum, nodes);
+
+ DEBUG(archive->pakfire, "Read checksum for %s - %s:%s\n",
+ path, checksum_algo_string(algo), hexdigest);
+
+ return 0;
-static archive_checksum_t* pakfire_archive_checksum_find(PakfireArchive archive, const char* filename) {
- archive_checksum_t** checksums = archive->checksums;
+ERROR:
+ free(chksum);
+
+ return r;
+}
- while (checksums && *checksums) {
- archive_checksum_t* checksum = *checksums++;
+static struct pakfire_archive_chksum* pakfire_archive_find_chksum(
+ PakfireArchive archive, const char* path) {
+ struct pakfire_archive_chksum* chksum = NULL;
- if (strcmp(checksum->filename, filename) == 0)
- return checksum;
+ STAILQ_FOREACH(chksum, &archive->chksums, nodes) {
+ if (strcmp(chksum->path, path) == 0)
+ return chksum;
}
// Nothing found
return NULL;
}
+// Signature Stuff
+
static PakfireArchiveSignature pakfire_archive_signature_create(PakfireArchive archive, const char* sigdata) {
PakfireArchiveSignature signature = calloc(1, sizeof(*signature));
if (signature) {
archive->format = -1;
archive->parser = pakfire_parser_create(pakfire, NULL, NULL, 0);
archive->signatures = NULL;
+
+ STAILQ_INIT(&archive->chksums);
}
return archive;
return archive;
}
+static void pakfire_archive_free_chksums(PakfireArchive archive) {
+ struct pakfire_archive_chksum* chksum;
+
+ while ((chksum = STAILQ_FIRST(&archive->chksums))) {
+ STAILQ_REMOVE_HEAD(&archive->chksums, nodes);
+
+ free(chksum);
+ }
+}
+
static void pakfire_archive_free(PakfireArchive archive) {
DEBUG(archive->pakfire, "Releasing archive at %p\n", archive);
+ // Free all checksums
+ pakfire_archive_free_chksums(archive);
+
// Release OpenSSL context
if (archive->mdctx)
EVP_MD_CTX_free(archive->mdctx);
if (archive->path)
free(archive->path);
- // Free checksums
- archive_checksum_t** checksums = archive->checksums;
- while (checksums && *checksums)
- pakfire_archive_checksum_free(*checksums++);
-
// Free signatures
if (archive->signatures) {
PakfireArchiveSignature* signatures = archive->signatures;
// Terminate string.
data[data_size] = '\0';
- // Allocate some space to save the checksums
- archive_checksum_t** checksums = archive->checksums = calloc(10, sizeof(*archive->checksums));
-
const char* filename = NULL;
const char* checksum = NULL;
archive_checksum_algo_t algo = PAKFIRE_CHECKSUM_SHA512;
// Add new checksum object
if (filename && checksum) {
- *checksums++ = pakfire_archive_checksum_create(archive->pakfire, filename, algo, checksum);
+ r = pakfire_archive_add_chksum(archive, filename, algo, checksum);
+ if (r)
+ goto ERROR;
}
// Eat up any space before next thing starts
p++;
}
- // Terminate the list
- *checksums = NULL;
-
+ERROR:
free(data);
return 0;
return status;
}
-static pakfire_archive_verify_status_t pakfire_archive_verify_file(Pakfire pakfire, struct archive* a, const archive_checksum_t* checksum) {
+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;
int r;
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
// Select algorithm
- switch (checksum->algo) {
+ switch (chksum->algo) {
case PAKFIRE_CHECKSUM_SHA512:
md = EVP_sha512();
break;
}
// Compare digests
- if (CRYPTO_memcmp(digest, checksum->digest, EVP_MD_CTX_size(mdctx)) == 0) {
- DEBUG(pakfire, "Checksum of %s is OK\n", checksum->filename);
+ if (CRYPTO_memcmp(digest, chksum->digest, EVP_MD_CTX_size(mdctx)) == 0) {
+ DEBUG(pakfire, "Checksum of %s is OK\n", chksum->path);
status = PAKFIRE_ARCHIVE_VERIFY_OK;
} else {
- DEBUG(pakfire, "Checksum of %s did not match\n", checksum->filename);
+ DEBUG(pakfire, "Checksum of %s did not match\n", chksum->path);
status = PAKFIRE_ARCHIVE_VERIFY_INVALID;
}
const char* entry_name = archive_entry_pathname(entry);
// See if we have a checksum for this file
- const archive_checksum_t* checksum = pakfire_archive_checksum_find(archive, entry_name);
- if (!checksum) {
+ const struct pakfire_archive_chksum* chksum = pakfire_archive_find_chksum(archive, entry_name);
+ if (!chksum) {
DEBUG(archive->pakfire, "Could not find checksum for %s\n", entry_name);
continue;
}
// Compare the checksums
- status = pakfire_archive_verify_file(archive->pakfire, a, checksum);
+ status = pakfire_archive_verify_file(archive->pakfire, a, chksum);
if (status)
goto END;
}