From: Michael Tremer Date: Tue, 11 Oct 2022 10:54:30 +0000 (+0000) Subject: packages: Use binary digests in database X-Git-Tag: 0.9.28~270 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e082fb85fc58de345481390c4bdf70fd9187e8bd;p=pakfire.git packages: Use binary digests in database Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index 67380428b..d9e2b8a45 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -1005,11 +1005,13 @@ static int pakfire_archive_make_package_from_json(struct pakfire_archive* archiv // Set digest switch (PAKFIRE_ARCHIVE_CHECKSUM) { case PAKFIRE_DIGEST_SHA2_512: - pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, archive->digests.sha2_512); + pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, + archive->digests.sha2_512, sizeof(archive->digests.sha2_512)); break; case PAKFIRE_DIGEST_SHA2_256: - pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, archive->digests.sha2_256); + pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, + archive->digests.sha2_256, sizeof(archive->digests.sha2_256)); break; case PAKFIRE_DIGEST_UNDEFINED: @@ -1343,11 +1345,13 @@ static int pakfire_archive_make_legacy_package(struct pakfire_archive* archive, // Set digest switch (PAKFIRE_ARCHIVE_CHECKSUM) { case PAKFIRE_DIGEST_SHA2_512: - pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, archive->digests.sha2_512); + pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, + archive->digests.sha2_512, sizeof(archive->digests.sha2_512)); break; case PAKFIRE_DIGEST_SHA2_256: - pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, archive->digests.sha2_256); + pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM, + archive->digests.sha2_256, sizeof(archive->digests.sha2_256)); break; case PAKFIRE_DIGEST_UNDEFINED: diff --git a/src/libpakfire/db.c b/src/libpakfire/db.c index 260f79536..45c517b89 100644 --- a/src/libpakfire/db.c +++ b/src/libpakfire/db.c @@ -836,52 +836,6 @@ static void pakfire_db_add_userinstalled(struct pakfire* pakfire, const char* na queue_push2(&pool->pooljobs, SOLVER_USERINSTALLED|SOLVER_SOLVABLE_NAME, id); } -static const struct pakfire_digest { - enum pakfire_digest_types type; - const char* prefix; -} pakfire_digests[] = { - { PAKFIRE_DIGEST_SHA2_512, "sha512:" }, - { PAKFIRE_DIGEST_SHA2_256, "sha256:" }, - { 0, NULL }, -}; - -static char* pakfire_db_pack_digest(enum pakfire_digest_types type, const char* hexdigest) { - char* s = NULL; - int r; - - for (const struct pakfire_digest* digest = pakfire_digests; digest->type; digest++) { - if (digest->type == type) { - r = asprintf(&s, "%s%s", digest->prefix, hexdigest); - if (r < 0) - return NULL; - - return s; - } - } - - return NULL; -} - -static const char* pakfire_db_unpack_digest(const char* hexdigest, enum pakfire_digest_types* type) { - *type = 0; - - // Don't do anything for empty input - if (!hexdigest || !*hexdigest) - return NULL; - - for (const struct pakfire_digest* digest = pakfire_digests; digest->type; digest++) { - if (pakfire_string_startswith(hexdigest, digest->prefix)) { - *type = digest->type; - - // Return the beginning of the hexdigest - return hexdigest + strlen(digest->prefix); - } - } - - // No match - return NULL; -} - static int pakfire_db_add_dependencies(struct pakfire_db* db, unsigned long id, struct pakfire_package* pkg) { sqlite3_stmt* stmt = NULL; int r = 1; @@ -1299,7 +1253,6 @@ END: int pakfire_db_add_package(struct pakfire_db* db, struct pakfire_package* pkg, struct pakfire_archive* archive, int userinstalled) { sqlite3_stmt* stmt = NULL; - char* digest = NULL; int r; // Begin a new transaction @@ -1316,6 +1269,7 @@ int pakfire_db_add_package(struct pakfire_db* db, "filename, " "size, " "inst_size, " + "digest_type, " "digest, " "license, " "summary, " @@ -1347,6 +1301,7 @@ int pakfire_db_add_package(struct pakfire_db* db, "?, " "?, " "?, " + "?, " "CURRENT_TIMESTAMP, " "?, " "?, " @@ -1437,25 +1392,36 @@ int pakfire_db_add_package(struct pakfire_db* db, goto ERROR; } + const unsigned char* digest = NULL; enum pakfire_digest_types digest_type = 0; + size_t digest_length = 0; - const char* hexdigest = pakfire_package_get_hexdigest(pkg, &digest_type); - if (hexdigest) { - digest = pakfire_db_pack_digest(digest_type, hexdigest); - if (!digest) - goto ERROR; + // Fetch the digest + digest = pakfire_package_get_digest(pkg, &digest_type, &digest_length); + if (!digest) { + ERROR(db->pakfire, "Could not fetch the package's digest: %m\n"); + r = 1; + goto ERROR; + } - r = sqlite3_bind_text(stmt, 8, digest, -1, NULL); - if (r) { - ERROR(db->pakfire, "Could not bind digest: %s\n", sqlite3_errmsg(db->handle)); - goto ERROR; - } + // Set the digest type + r = sqlite3_bind_int64(stmt, 8, digest_type); + if (r) { + ERROR(db->pakfire, "Could not bind digest type: %s\n", sqlite3_errmsg(db->handle)); + goto ERROR; + } + + // Set the digest + r = sqlite3_bind_blob(stmt, 9, digest, digest_length, NULL); + if (r) { + ERROR(db->pakfire, "Could not bind digest: %s\n", sqlite3_errmsg(db->handle)); + goto ERROR; } // 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 ERROR; @@ -1464,7 +1430,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 ERROR; @@ -1473,7 +1439,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 ERROR; @@ -1482,7 +1448,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 ERROR; @@ -1491,7 +1457,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 ERROR; @@ -1500,7 +1466,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 ERROR; @@ -1509,7 +1475,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 ERROR; @@ -1521,19 +1487,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 ERROR; // No repository? } else { - r = sqlite3_bind_null(stmt, 16); + r = sqlite3_bind_null(stmt, 17); if (r) goto ERROR; } // 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 ERROR; @@ -1542,11 +1508,11 @@ int pakfire_db_add_package(struct pakfire_db* db, // Source package name const char* source_name = pakfire_package_get_source_name(pkg); if (source_name) { - r = sqlite3_bind_text(stmt, 18, source_name, -1, NULL); + r = sqlite3_bind_text(stmt, 19, source_name, -1, NULL); if (r) goto ERROR; } else { - r = sqlite3_bind_null(stmt, 18); + r = sqlite3_bind_null(stmt, 19); if (r) goto ERROR; } @@ -1554,11 +1520,11 @@ int pakfire_db_add_package(struct pakfire_db* db, // Source EVR const char* source_evr = pakfire_package_get_source_evr(pkg); if (source_evr) { - r = sqlite3_bind_text(stmt, 19, source_evr, -1, NULL); + r = sqlite3_bind_text(stmt, 20, source_evr, -1, NULL); if (r) goto ERROR; } else { - r = sqlite3_bind_null(stmt, 19); + r = sqlite3_bind_null(stmt, 20); if (r) goto ERROR; } @@ -1566,11 +1532,11 @@ int pakfire_db_add_package(struct pakfire_db* db, // Source arch const char* source_arch = pakfire_package_get_source_arch(pkg); if (source_arch) { - r = sqlite3_bind_text(stmt, 20, source_arch, -1, NULL); + r = sqlite3_bind_text(stmt, 21, source_arch, -1, NULL); if (r) goto ERROR; } else { - r = sqlite3_bind_null(stmt, 20); + r = sqlite3_bind_null(stmt, 21); if (r) goto ERROR; } @@ -1578,11 +1544,11 @@ int pakfire_db_add_package(struct pakfire_db* db, // Distribution const char* distribution = pakfire_package_get_distribution(pkg); if (distribution) { - r = sqlite3_bind_text(stmt, 21, distribution, -1, NULL); + r = sqlite3_bind_text(stmt, 22, distribution, -1, NULL); if (r) goto ERROR; } else { - r = sqlite3_bind_null(stmt, 21); + r = sqlite3_bind_null(stmt, 22); if (r) goto ERROR; } @@ -1620,8 +1586,6 @@ int pakfire_db_add_package(struct pakfire_db* db, ERROR: if (stmt) sqlite3_finalize(stmt); - if (digest) - free(digest); // Commit or rollback if (r) @@ -1815,72 +1779,73 @@ static int pakfire_db_load_package(struct pakfire_db* db, struct pakfire_repo* r pakfire_package_set_installsize(pkg, size); } - // Digest - const char* digest = (const char*)sqlite3_column_text(stmt, 8); - if (digest) { - enum pakfire_digest_types digest_type = 0; + // Digest type + enum pakfire_digest_types digest_type = sqlite3_column_int64(stmt, 8); + size_t digest_length = 0; - // Unpack digest - const char* hexdigest = pakfire_db_unpack_digest(digest, &digest_type); - if (hexdigest) - pakfire_package_set_hexdigest(pkg, digest_type, hexdigest); + // Digest length + + // Digest + const unsigned char* digest = sqlite3_column_blob(stmt, 9); + if (digest_type && digest) { + pakfire_package_set_digest(pkg, digest_type, digest, digest_length); } // 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) @@ -1893,15 +1858,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 }, }; @@ -1913,22 +1878,22 @@ static int pakfire_db_load_package(struct pakfire_db* db, struct pakfire_repo* r } // Source package - const char* source_name = (const char*)sqlite3_column_text(stmt, 28); + const char* source_name = (const char*)sqlite3_column_text(stmt, 29); if (source_name) pakfire_package_set_source_name(pkg, source_name); // Source EVR - const char* source_evr = (const char*)sqlite3_column_text(stmt, 29); + const char* source_evr = (const char*)sqlite3_column_text(stmt, 30); if (source_evr) pakfire_package_set_source_evr(pkg, source_evr); // Source arch - const char* source_arch = (const char*)sqlite3_column_text(stmt, 30); + const char* source_arch = (const char*)sqlite3_column_text(stmt, 31); if (source_arch) pakfire_package_set_source_arch(pkg, source_arch); // Distribution - const char* distribution = (const char*)sqlite3_column_text(stmt, 31); + const char* distribution = (const char*)sqlite3_column_text(stmt, 32); if (distribution) pakfire_package_set_distribution(pkg, distribution); @@ -1965,6 +1930,7 @@ int pakfire_db_load(struct pakfire_db* db, struct pakfire_repo* repo) { "filename, " "size, " "inst_size, " + "digest_type, " "digest, " "license, " "summary, " diff --git a/src/libpakfire/include/pakfire/package.h b/src/libpakfire/include/pakfire/package.h index 3ca6cda78..9ba647c4a 100644 --- a/src/libpakfire/include/pakfire/package.h +++ b/src/libpakfire/include/pakfire/package.h @@ -53,11 +53,11 @@ 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 unsigned char* pakfire_package_get_digest(struct pakfire_package* pkg, - enum pakfire_digest_types* type); + enum pakfire_digest_types* type, size_t* length); const char* pakfire_package_get_hexdigest(struct pakfire_package* pkg, enum pakfire_digest_types* type); int pakfire_package_set_digest(struct pakfire_package* pkg, - enum pakfire_digest_types type, const unsigned char* digest); + enum pakfire_digest_types type, const unsigned char* digest, const size_t length); int pakfire_package_set_hexdigest(struct pakfire_package* pkg, enum pakfire_digest_types type, const char* hexdigest); const char* pakfire_package_get_summary(struct pakfire_package* pkg); diff --git a/src/libpakfire/package.c b/src/libpakfire/package.c index 3a78a0fc8..ea1acedef 100644 --- a/src/libpakfire/package.c +++ b/src/libpakfire/package.c @@ -409,9 +409,9 @@ static enum pakfire_digest_types pakfire_package_id2digest(Id id) { } PAKFIRE_EXPORT const unsigned char* pakfire_package_get_digest( - struct pakfire_package* pkg, enum pakfire_digest_types* type) { + struct pakfire_package* pkg, enum pakfire_digest_types* type, size_t* length) { Solvable* s = get_solvable(pkg); - Id id; + Id id = 0; const unsigned char* checksum = solvable_lookup_bin_checksum(s, SOLVABLE_CHECKSUM, &id); @@ -422,28 +422,15 @@ PAKFIRE_EXPORT const unsigned char* pakfire_package_get_digest( checksum = NULL; } - return checksum; -} - -PAKFIRE_EXPORT const char* pakfire_package_get_hexdigest( - struct pakfire_package* pkg, enum pakfire_digest_types* type) { - Solvable* s = get_solvable(pkg); - Id id; - - const char* checksum = solvable_lookup_checksum(s, SOLVABLE_CHECKSUM, &id); - - // Convert ID to digest type - *type = pakfire_package_id2digest(id); - if (!*type) { - errno = ENOTSUP; - checksum = NULL; - } + // Store the length (if requested) + if (length) + *length = pakfire_digest_length(*type); return checksum; } PAKFIRE_EXPORT int pakfire_package_set_digest(struct pakfire_package* pkg, - enum pakfire_digest_types type, const unsigned char* digest) { + enum pakfire_digest_types type, const unsigned char* digest, const size_t length) { Solvable* s = get_solvable(pkg); Pool* pool = s->repo->pool; Id id; @@ -463,6 +450,12 @@ PAKFIRE_EXPORT int pakfire_package_set_digest(struct pakfire_package* pkg, return 1; } + // Check if the digest length matches + if (pakfire_digest_length(type) != length) { + errno = EINVAL; + return 1; + } + struct pakfire_repo* repo = pakfire_package_get_repo(pkg); Repodata* data = pakfire_repo_get_repodata(repo); diff --git a/src/libpakfire/transaction.c b/src/libpakfire/transaction.c index e3ce768e6..53e509d11 100644 --- a/src/libpakfire/transaction.c +++ b/src/libpakfire/transaction.c @@ -688,16 +688,15 @@ static int pakfire_transaction_verify(struct pakfire_transaction* transaction, } enum pakfire_digest_types digest_type = PAKFIRE_DIGEST_UNDEFINED; + size_t length = 0; // Fetch digest from package - const unsigned char* expected_digest = pakfire_package_get_digest(pkg, &digest_type); + const unsigned char* expected_digest = pakfire_package_get_digest(pkg, &digest_type, &length); if (!expected_digest) { DEBUG(transaction->pakfire, "Package %s has no digest\n", nevra); return 0; } - const size_t length = pakfire_digest_length(digest_type); - // Check against the digest of the archive return pakfire_archive_check_digest(archive, digest_type, expected_digest, length); } @@ -1152,10 +1151,10 @@ static int pakfire_transaction_download_package(struct pakfire_transaction* tran } enum pakfire_digest_types digest_type = 0; + size_t digest_length = 0; // Retrieve package digest - const unsigned char* digest = pakfire_package_get_digest(pkg, &digest_type); - const size_t digest_length = pakfire_digest_length(digest_type); + const unsigned char* digest = pakfire_package_get_digest(pkg, &digest_type, &digest_length); // Add transfer to downloader r = pakfire_downloader_add_transfer(downloader, baseurl, mirrorlist,