From b28af23a991ebc878f022c5460ad8fe3d736b328 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Mon, 20 Sep 2021 09:27:35 +0000 Subject: [PATCH] package: Refactor checksums/digests Signed-off-by: Michael Tremer --- src/_pakfire/package.c | 44 +++++++-- src/libpakfire/db.c | 104 +++++++++++--------- src/libpakfire/include/pakfire/package.h | 15 ++- src/libpakfire/libpakfire.sym | 4 +- src/libpakfire/package.c | 115 +++++++++++++++++++++-- 5 files changed, 219 insertions(+), 63 deletions(-) diff --git a/src/_pakfire/package.c b/src/_pakfire/package.c index 694041840..b308dca0d 100644 --- a/src/_pakfire/package.c +++ b/src/_pakfire/package.c @@ -193,18 +193,35 @@ static void Package_set_uuid(PackageObject* self, PyObject* value) { pakfire_package_set_uuid(self->package, uuid); } -static PyObject* Package_get_checksum(PackageObject* self) { - const char* checksum = pakfire_package_get_checksum(self->package); - if (!checksum) +static PyObject* Package_get_hexdigest(PackageObject* self, enum pakfire_package_digests type) { + const char* hexdigest = pakfire_package_get_hexdigest(self->package, type); + if (!hexdigest) Py_RETURN_NONE; - return PyUnicode_FromString(checksum); + return PyUnicode_FromString(hexdigest); } -static void Package_set_checksum(PackageObject* self, PyObject* value) { - const char* checksum = PyUnicode_FromValue(value); +static PyObject* Package_get_hexdigest_sha256(PackageObject* self) { + return Package_get_hexdigest(self, PAKFIRE_PACKAGE_DIGEST_SHA256); +} + +static PyObject* Package_get_hexdigest_sha512(PackageObject* self) { + return Package_get_hexdigest(self, PAKFIRE_PACKAGE_DIGEST_SHA512); +} + +static int Package_set_hexdigest(PackageObject* self, + enum pakfire_package_digests type, PyObject* value) { + const char* hexdigest = PyUnicode_FromValue(value); + + return pakfire_package_set_hexdigest(self->package, type, hexdigest); +} - pakfire_package_set_checksum(self->package, checksum); +static int Package_set_hexdigest_sha256(PackageObject* self, PyObject* value) { + return Package_set_hexdigest(self, PAKFIRE_PACKAGE_DIGEST_SHA256, value); +} + +static int Package_set_hexdigest_sha512(PackageObject* self, PyObject* value) { + return Package_set_hexdigest(self, PAKFIRE_PACKAGE_DIGEST_SHA512, value); } static PyObject* Package_get_summary(PackageObject* self) { @@ -690,9 +707,16 @@ static struct PyGetSetDef Package_getsetters[] = { NULL }, { - "checksum", - (getter)Package_get_checksum, - (setter)Package_set_checksum, + "hexdigest_sha256", + (getter)Package_get_hexdigest_sha256, + (setter)Package_set_hexdigest_sha256, + NULL, + NULL + }, + { + "hexdigest_sha512", + (getter)Package_get_hexdigest_sha512, + (setter)Package_set_hexdigest_sha512, NULL, NULL }, diff --git a/src/libpakfire/db.c b/src/libpakfire/db.c index a79760144..445254f80 100644 --- a/src/libpakfire/db.c +++ b/src/libpakfire/db.c @@ -244,7 +244,8 @@ static int pakfire_db_create_schema(struct pakfire_db* db) { "filename TEXT, " "size INTEGER, " "inst_size INTEGER, " - "hash1 TEXT, " + "digest_sha512 TEXT, " + "digest_sha256 TEXT, " "license TEXT, " "summary TEXT, " "description TEXT, " @@ -1010,9 +1011,9 @@ int pakfire_db_add_package(struct pakfire_db* db, goto ROLLBACK; const char* sql = "INSERT INTO packages(name, evr, arch, groups, filename, size, " - "inst_size, hash1, license, summary, description, uuid, vendor, build_host, " - "build_time, installed, repository, userinstalled) " - "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)"; + "inst_size, digest_sha512, digest_sha256, license, summary, description, uuid, " + "vendor, build_host, build_time, installed, repository, userinstalled) " + "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)"; // Prepare the statement r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL); @@ -1095,19 +1096,28 @@ int pakfire_db_add_package(struct pakfire_db* db, goto ROLLBACK; } - // Bind hash1 - const char* hash1 = pakfire_package_get_checksum(pkg); + // Bind digest_sha512 + const char* digest_sha512 = pakfire_package_get_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA512); + + r = sqlite3_bind_text(stmt, 8, digest_sha512, -1, NULL); + if (r) { + ERROR(db->pakfire, "Could not bind digest_sha512: %s\n", sqlite3_errmsg(db->handle)); + goto ROLLBACK; + } + + // Bind digest_sha256 + const char* digest_sha256 = pakfire_package_get_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA256); - r = sqlite3_bind_text(stmt, 8, hash1, -1, NULL); + r = sqlite3_bind_text(stmt, 9, digest_sha256, -1, NULL); if (r) { - ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle)); + ERROR(db->pakfire, "Could not bind digest_sha256: %s\n", sqlite3_errmsg(db->handle)); goto ROLLBACK; } // Bind license const char* license = pakfire_package_get_license(pkg); - r = sqlite3_bind_text(stmt, 9, license, -1, NULL); + r = sqlite3_bind_text(stmt, 10, license, -1, NULL); if (r) { ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle)); goto ROLLBACK; @@ -1116,7 +1126,7 @@ int pakfire_db_add_package(struct pakfire_db* db, // Bind summary const char* summary = pakfire_package_get_summary(pkg); - r = sqlite3_bind_text(stmt, 10, summary, -1, NULL); + r = sqlite3_bind_text(stmt, 11, summary, -1, NULL); if (r) { ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle)); goto ROLLBACK; @@ -1125,7 +1135,7 @@ int pakfire_db_add_package(struct pakfire_db* db, // Bind description const char* description = pakfire_package_get_description(pkg); - r = sqlite3_bind_text(stmt, 11, description, -1, NULL); + r = sqlite3_bind_text(stmt, 12, description, -1, NULL); if (r) { ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle)); goto ROLLBACK; @@ -1134,7 +1144,7 @@ int pakfire_db_add_package(struct pakfire_db* db, // Bind uuid const char* uuid = pakfire_package_get_uuid(pkg); - r = sqlite3_bind_text(stmt, 12, uuid, -1, NULL); + r = sqlite3_bind_text(stmt, 13, uuid, -1, NULL); if (r) { ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle)); goto ROLLBACK; @@ -1143,7 +1153,7 @@ int pakfire_db_add_package(struct pakfire_db* db, // Bind vendor const char* vendor = pakfire_package_get_vendor(pkg); - r = sqlite3_bind_text(stmt, 13, vendor, -1, NULL); + r = sqlite3_bind_text(stmt, 14, vendor, -1, NULL); if (r) { ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle)); goto ROLLBACK; @@ -1152,7 +1162,7 @@ int pakfire_db_add_package(struct pakfire_db* db, // Bind build_host const char* build_host = pakfire_package_get_build_host(pkg); - r = sqlite3_bind_text(stmt, 14, build_host, -1, NULL); + r = sqlite3_bind_text(stmt, 15, build_host, -1, NULL); if (r) { ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle)); goto ROLLBACK; @@ -1161,7 +1171,7 @@ int pakfire_db_add_package(struct pakfire_db* db, // Bind build_time time_t build_time = pakfire_package_get_build_time(pkg); - r = sqlite3_bind_int64(stmt, 15, build_time); + r = sqlite3_bind_int64(stmt, 16, build_time); if (r) { ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle)); goto ROLLBACK; @@ -1173,19 +1183,19 @@ int pakfire_db_add_package(struct pakfire_db* db, const char* repo_name = pakfire_repo_get_name(repo); pakfire_repo_unref(repo); - r = sqlite3_bind_text(stmt, 16, repo_name, -1, NULL); + r = sqlite3_bind_text(stmt, 17, repo_name, -1, NULL); if (r) goto ROLLBACK; // No repository? } else { - r = sqlite3_bind_null(stmt, 16); + r = sqlite3_bind_null(stmt, 17); if (r) goto ROLLBACK; } // installed by the user? - r = sqlite3_bind_int(stmt, 17, userinstalled); + r = sqlite3_bind_int(stmt, 18, userinstalled); if (r) { ERROR(db->pakfire, "Could not bind userinstalled: %s\n", sqlite3_errmsg(db->handle)); goto ROLLBACK; @@ -1411,67 +1421,73 @@ static int pakfire_db_load_package(struct pakfire_db* db, struct pakfire_repo* r pakfire_package_set_installsize(pkg, size); } - // Hash 1 - const char* hash1 = (const char*)sqlite3_column_text(stmt, 8); - if (hash1) { - pakfire_package_set_checksum(pkg, hash1); + // Digest SHA512 + const char* digest_sha512 = (const char*)sqlite3_column_text(stmt, 8); + if (digest_sha512) { + pakfire_package_set_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA512, digest_sha512); + } + + // Digest SHA256 + const char* digest_sha256 = (const char*)sqlite3_column_text(stmt, 9); + if (digest_sha256) { + pakfire_package_set_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA256, digest_sha256); } // License - const char* license = (const char*)sqlite3_column_text(stmt, 9); + const char* license = (const char*)sqlite3_column_text(stmt, 10); if (license) { pakfire_package_set_license(pkg, license); } // Summary - const char* summary = (const char*)sqlite3_column_text(stmt, 10); + const char* summary = (const char*)sqlite3_column_text(stmt, 11); if (summary) { pakfire_package_set_summary(pkg, summary); } // Description - const char* description = (const char*)sqlite3_column_text(stmt, 11); + const char* description = (const char*)sqlite3_column_text(stmt, 12); if (description) { pakfire_package_set_description(pkg, description); } // UUID - const char* uuid = (const char*)sqlite3_column_text(stmt, 12); + const char* uuid = (const char*)sqlite3_column_text(stmt, 13); if (uuid) { pakfire_package_set_uuid(pkg, uuid); } // Vendor - const char* vendor = (const char*)sqlite3_column_text(stmt, 13); + const char* vendor = (const char*)sqlite3_column_text(stmt, 14); if (vendor) { pakfire_package_set_vendor(pkg, vendor); } // Build Host - const char* build_host = (const char*)sqlite3_column_text(stmt, 14); + const char* build_host = (const char*)sqlite3_column_text(stmt, 15); if (build_host) { pakfire_package_set_build_host(pkg, build_host); } // Build Time - time_t build_time = sqlite3_column_int64(stmt, 15); + time_t build_time = sqlite3_column_int64(stmt, 16); if (build_time) { pakfire_package_set_build_time(pkg, build_time); } // Install Time - time_t install_time = sqlite3_column_int64(stmt, 16); + time_t install_time = sqlite3_column_int64(stmt, 17); if (install_time) { pakfire_package_set_install_time(pkg, install_time); } // installed by user? - int userinstalled = sqlite3_column_int(stmt, 17); + int userinstalled = sqlite3_column_int(stmt, 18); if (userinstalled) pakfire_db_add_userinstalled(db->pakfire, name); // Files - const char* files = (const char*)sqlite3_column_text(stmt, 18); + const char* files = (const char*)sqlite3_column_text(stmt, 19); if (files) { r = pakfire_package_set_filelist_from_string(pkg, files); if (r) @@ -1484,15 +1500,15 @@ static int pakfire_db_load_package(struct pakfire_db* db, struct pakfire_repo* r unsigned int field; void (*func)(struct pakfire_package* pkg, const char* dep); } dependencies[] = { - { 19, pakfire_package_add_provides }, - { 20, pakfire_package_add_prerequires }, - { 21, pakfire_package_add_requires }, - { 22, pakfire_package_add_conflicts }, - { 23, pakfire_package_add_obsoletes }, - { 24, pakfire_package_add_recommends }, - { 25, pakfire_package_add_suggests }, - { 26, pakfire_package_add_supplements }, - { 27, pakfire_package_add_enhances }, + { 20, pakfire_package_add_provides }, + { 21, pakfire_package_add_prerequires }, + { 22, pakfire_package_add_requires }, + { 23, pakfire_package_add_conflicts }, + { 24, pakfire_package_add_obsoletes }, + { 25, pakfire_package_add_recommends }, + { 26, pakfire_package_add_suggests }, + { 27, pakfire_package_add_supplements }, + { 28, pakfire_package_add_enhances }, { 0, NULL }, }; @@ -1528,9 +1544,9 @@ int pakfire_db_load(struct pakfire_db* db, struct pakfire_repo* repo) { const char* sql = "SELECT " - "name, evr, arch, id, groups, filename, size, inst_size, hash1, license, " - "summary, description, uuid, vendor, build_host, build_time, " - "strftime('%s', installed) AS installed, userinstalled, " + "name, evr, arch, id, groups, filename, size, inst_size, " + "digest_sha512, digest_sha256, license, summary, description, uuid, vendor, " + "build_host, build_time, strftime('%s', installed) AS installed, userinstalled, " "(" "SELECT group_concat(path, '\n') FROM files WHERE files.pkg = packages.id" ") AS files, " diff --git a/src/libpakfire/include/pakfire/package.h b/src/libpakfire/include/pakfire/package.h index 61b802ebc..990f69243 100644 --- a/src/libpakfire/include/pakfire/package.h +++ b/src/libpakfire/include/pakfire/package.h @@ -30,6 +30,11 @@ struct pakfire_package; #include #include +enum pakfire_package_digests { + PAKFIRE_PACKAGE_DIGEST_SHA256, + PAKFIRE_PACKAGE_DIGEST_SHA512, +}; + struct pakfire_package* pakfire_package_create(struct pakfire* pakfire, struct pakfire_repo* repo, const char* name, const char* evr, const char* arch); @@ -51,8 +56,14 @@ void pakfire_package_set_arch(struct pakfire_package* pkg, const char* arch); const char* pakfire_package_get_uuid(struct pakfire_package* pkg); void pakfire_package_set_uuid(struct pakfire_package* pkg, const char* uuid); -const char* pakfire_package_get_checksum(struct pakfire_package* pkg); -void pakfire_package_set_checksum(struct pakfire_package* pkg, const char* checksum); +const unsigned char* pakfire_package_get_digest(struct pakfire_package* pkg, + enum pakfire_package_digests type); +const char* pakfire_package_get_hexdigest(struct pakfire_package* pkg, + enum pakfire_package_digests type); +int pakfire_package_set_digest(struct pakfire_package* pkg, + enum pakfire_package_digests type, const unsigned char* digest); +int pakfire_package_set_hexdigest(struct pakfire_package* pkg, + enum pakfire_package_digests type, const char* hexdigest); const char* pakfire_package_get_summary(struct pakfire_package* pkg); void pakfire_package_set_summary(struct pakfire_package* pkg, const char* summary); const char* pakfire_package_get_description(struct pakfire_package* pkg); diff --git a/src/libpakfire/libpakfire.sym b/src/libpakfire/libpakfire.sym index 8302a91e3..aadbb9fb2 100644 --- a/src/libpakfire/libpakfire.sym +++ b/src/libpakfire/libpakfire.sym @@ -140,15 +140,16 @@ global: pakfire_package_get_build_id; pakfire_package_get_build_time; pakfire_package_get_cache_path; - pakfire_package_get_checksum; pakfire_package_get_conflicts; pakfire_package_get_description; + pakfire_package_get_digest; pakfire_package_get_downloadsize; pakfire_package_get_enhances; pakfire_package_get_evr; pakfire_package_get_filelist; pakfire_package_get_filename; pakfire_package_get_groups; + pakfire_package_get_hexdigest; pakfire_package_get_license; pakfire_package_get_location; pakfire_package_get_installsize; @@ -185,6 +186,7 @@ global: pakfire_package_set_filelist; pakfire_package_set_filename; pakfire_package_set_groups; + pakfire_package_set_hexdigest; pakfire_package_set_installsize; pakfire_package_set_install_time; pakfire_package_set_license; diff --git a/src/libpakfire/package.c b/src/libpakfire/package.c index 6595779bd..0fcd6353c 100644 --- a/src/libpakfire/package.c +++ b/src/libpakfire/package.c @@ -375,12 +375,105 @@ PAKFIRE_EXPORT void pakfire_package_set_uuid(struct pakfire_package* pkg, const pakfire_package_set_string(pkg, SOLVABLE_PKGID, uuid); } -PAKFIRE_EXPORT const char* pakfire_package_get_checksum(struct pakfire_package* pkg) { - return pakfire_package_get_string(pkg, SOLVABLE_CHECKSUM); +static Id pakfire_package_digest2id(enum pakfire_package_digests type) { + Id id = 0; + + switch (type) { + case PAKFIRE_PACKAGE_DIGEST_SHA256: + id = REPOKEY_TYPE_SHA256; + break; + + case PAKFIRE_PACKAGE_DIGEST_SHA512: + id = REPOKEY_TYPE_SHA512; + break; + } + + // Type is invalid + if (!id) + errno = EINVAL; + + return id; +} + +PAKFIRE_EXPORT const unsigned char* pakfire_package_get_digest( + struct pakfire_package* pkg, enum pakfire_package_digests type) { + Solvable* s = get_solvable(pkg); + + Id id = pakfire_package_digest2id(type); + if (!id) + return NULL; + + return solvable_lookup_bin_checksum(s, SOLVABLE_CHECKSUM, &id); +} + +PAKFIRE_EXPORT const char* pakfire_package_get_hexdigest( + struct pakfire_package* pkg, enum pakfire_package_digests type) { + Solvable* s = get_solvable(pkg); + + Id id = pakfire_package_digest2id(type); + if (!id) + return NULL; + + return solvable_lookup_checksum(s, SOLVABLE_CHECKSUM, &id); +} + +PAKFIRE_EXPORT int pakfire_package_set_digest(struct pakfire_package* pkg, + enum pakfire_package_digests type, const unsigned char* digest) { + Solvable* s = get_solvable(pkg); + Pool* pool = s->repo->pool; + int r = 1; + + Id id = pakfire_package_digest2id(type); + if (!id) + return 1; + + struct pakfire_repo* repo = pakfire_package_get_repo(pkg); + + Repodata* data = pakfire_repo_get_repodata(repo); + if (!data) + goto ERROR; + + repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, id, digest); + + // Success + r = 0; + +ERROR: + pakfire_repo_unref(repo); + + return r; } -PAKFIRE_EXPORT void pakfire_package_set_checksum(struct pakfire_package* pkg, const char* checksum) { - pakfire_package_set_string(pkg, SOLVABLE_CHECKSUM, checksum); +static size_t pakfire_package_digest_length(enum pakfire_package_digests digest) { + switch (digest) { + case PAKFIRE_PACKAGE_DIGEST_SHA256: + return 32; + + case PAKFIRE_PACKAGE_DIGEST_SHA512: + return 64; + } + + return 0; +} + +PAKFIRE_EXPORT int pakfire_package_set_hexdigest(struct pakfire_package* pkg, + enum pakfire_package_digests type, const char* hexdigest) { + size_t digest_length = pakfire_package_digest_length(type); + + if (!digest_length) { + errno = EINVAL; + return 1; + } + + // Allocate a buffer for the binary representation of the digest + unsigned char* digest = alloca(digest_length); + if (!digest) + return 1; + + // Convert from hex to binary + __pakfire_unhexlify(digest, digest_length, hexdigest); + + return pakfire_package_set_digest(pkg, type, digest); } PAKFIRE_EXPORT const char* pakfire_package_get_summary(struct pakfire_package* pkg) { @@ -461,9 +554,9 @@ PAKFIRE_EXPORT void pakfire_package_set_maintainer(struct pakfire_package* pkg, static int pakfire_package_make_cache_path(struct pakfire_package* pkg) { const char* filename = pakfire_package_get_filename(pkg); - const char* checksum = pakfire_package_get_checksum(pkg); + const char* checksum = pakfire_package_get_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA256); - if (strlen(checksum) < 3) + if (!checksum || strlen(checksum) < 3) return 1; return pakfire_make_cache_path(pkg->pakfire, pkg->path, @@ -905,6 +998,16 @@ PAKFIRE_EXPORT char* pakfire_package_dump(struct pakfire_package* pkg, int flags if (build_id) pakfire_package_dump_add_line(&string, _("Build ID"), build_id); + // Digest SHA512 + const char* digest_sha512 = pakfire_package_get_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA512); + if (digest_sha512) + pakfire_package_dump_add_line(&string, _("SHA512 Digest"), digest_sha512); + + // Digest SHA256 + const char* digest_sha256 = pakfire_package_get_hexdigest(pkg, PAKFIRE_PACKAGE_DIGEST_SHA256); + if (digest_sha256) + pakfire_package_dump_add_line(&string, _("SHA256 Digest"), digest_sha256); + // Build time time_t build_time = pakfire_package_get_build_time(pkg); pakfire_package_dump_add_line_date(&string, _("Build Time"), build_time); -- 2.39.5