libxbps: ABI/API break due to hash function changes

This commit is contained in:
Duncan Overbruck 2020-02-10 01:54:52 +01:00
parent aa4d726dca
commit 0d90534236
No known key found for this signature in database
GPG Key ID: 335C1D17EC3D6E35
18 changed files with 141 additions and 118 deletions

View File

@ -55,7 +55,8 @@ struct xentry {
TAILQ_ENTRY(xentry) entries; TAILQ_ENTRY(xentry) entries;
uint64_t mtime; uint64_t mtime;
uint64_t size; uint64_t size;
char *file, *type, *target, *hash; char *file, *type, *target;
char sha256[XBPS_SHA256_SIZE];
ino_t inode; ino_t inode;
}; };
@ -317,6 +318,7 @@ ftw_cb(const char *fpath, const struct stat *sb, const struct dirent *dir UNUSED
xbps_dictionary_t fileinfo = NULL; xbps_dictionary_t fileinfo = NULL;
const char *filep = NULL; const char *filep = NULL;
char *buf, *p, *p2, *dname; char *buf, *p, *p2, *dname;
char sha256[XBPS_SHA256_SIZE];
ssize_t r; ssize_t r;
/* Ignore metadata files generated by xbps-src and destdir */ /* Ignore metadata files generated by xbps-src and destdir */
@ -480,12 +482,9 @@ ftw_cb(const char *fpath, const struct stat *sb, const struct dirent *dir UNUSED
} }
assert(xe->type); assert(xe->type);
if ((p = xbps_file_hash(fpath)) == NULL) if (!xbps_file_sha256(xe->sha256, sizeof sha256, fpath))
die("failed to process hash for %s:", fpath);
xbps_dictionary_set_cstring(fileinfo, "sha256", p);
free(p);
if ((xe->hash = xbps_file_hash(fpath)) == NULL)
die("failed to process hash for %s:", fpath); die("failed to process hash for %s:", fpath);
xbps_dictionary_set_cstring(fileinfo, "sha256", xe->sha256);
xbps_dictionary_set_uint64(fileinfo, "inode", sb->st_ino); xbps_dictionary_set_uint64(fileinfo, "inode", sb->st_ino);
xe->inode = sb->st_ino; xe->inode = sb->st_ino;
@ -607,8 +606,8 @@ process_xentry(const char *key, const char *mutable_files)
xbps_dictionary_set_cstring(d, "file", p); xbps_dictionary_set_cstring(d, "file", p);
if (xe->target) if (xe->target)
xbps_dictionary_set_cstring(d, "target", xe->target); xbps_dictionary_set_cstring(d, "target", xe->target);
if (xe->hash) if (*xe->sha256)
xbps_dictionary_set_cstring(d, "sha256", xe->hash); xbps_dictionary_set_cstring(d, "sha256", xe->sha256);
if (xe->mtime) if (xe->mtime)
xbps_dictionary_set_uint64(d, "mtime", xe->mtime); xbps_dictionary_set_uint64(d, "mtime", xe->mtime);
if (xe->size) if (xe->size)

View File

@ -53,7 +53,7 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int c; int c;
char *hash = NULL; char sha256[XBPS_SHA256_SIZE];
const char *mode = NULL, *progname = argv[0]; const char *mode = NULL, *progname = argv[0];
const struct option longopts[] = { const struct option longopts[] = {
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
@ -84,23 +84,19 @@ main(int argc, char **argv)
} }
if (argc < 1) { if (argc < 1) {
hash = xbps_file_hash("/dev/stdin"); if (!xbps_file_sha256(sha256, sizeof sha256, "/dev/stdin"))
if (hash == NULL)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
printf("%s\n", hash); printf("%s\n", sha256);
free(hash);
} else { } else {
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
hash = xbps_file_hash(argv[i]); if (!xbps_file_sha256(sha256, sizeof sha256, argv[i])) {
if (hash == NULL) {
fprintf(stderr, fprintf(stderr,
"%s: couldn't get hash for %s (%s)\n", "%s: couldn't get hash for %s (%s)\n",
progname, argv[i], strerror(errno)); progname, argv[i], strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
printf("%s\n", hash); printf("%s\n", sha256);
free(hash);
} }
} }
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);

View File

@ -138,13 +138,13 @@ main(int argc, char **argv)
} }
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
unsigned char *digest = NULL; unsigned char digest[XBPS_SHA256_DIGEST_SIZE];
if (i > 0 || !filename) if (i > 0 || !filename)
filename = fname(argv[i]); filename = fname(argv[i]);
if (shasum) { if (shasum) {
rv = xbps_fetch_file_dest_digest(&xh, argv[i], filename, verbose ? "v" : "", &digest); rv = xbps_fetch_file_dest_sha256(&xh, argv[i], filename, verbose ? "v" : "", digest, sizeof digest);
} else { } else {
rv = xbps_fetch_file_dest(&xh, argv[i], filename, verbose ? "v" : ""); rv = xbps_fetch_file_dest(&xh, argv[i], filename, verbose ? "v" : "");
} }
@ -153,15 +153,19 @@ main(int argc, char **argv)
fprintf(stderr, "%s: %s\n", argv[i], xbps_fetch_error_string()); fprintf(stderr, "%s: %s\n", argv[i], xbps_fetch_error_string());
} else if (rv == 0) { } else if (rv == 0) {
fprintf(stderr, "%s: file is identical with remote.\n", argv[i]); fprintf(stderr, "%s: file is identical with remote.\n", argv[i]);
if (shasum) if (shasum) {
digest = xbps_file_hash_raw(filename); if (!xbps_file_sha256_raw(digest, sizeof digest, filename)) {
xbps_error_printf("%s: failed to hash libxbps: %s: %s\n",
progname, filename, strerror(rv));
*digest = '\0';
}
}
} else { } else {
rv = 0; rv = 0;
} }
if (digest != NULL) { if (*digest) {
print_digest(digest, SHA256_DIGEST_LENGTH); print_digest(digest, SHA256_DIGEST_LENGTH);
printf(" %s\n", filename); printf(" %s\n", filename);
free(digest);
} }
} }

View File

@ -102,7 +102,7 @@ check_pkg_integrity(struct xbps_handle *xhp,
free(buf); free(buf);
return -1; return -1;
} }
rv = xbps_file_hash_check(buf, sha256); rv = xbps_file_sha256_check(buf, sha256);
free(buf); free(buf);
if (rv == ENOENT) { if (rv == ENOENT) {
xbps_dictionary_remove(opkgd, "metafile-sha256"); xbps_dictionary_remove(opkgd, "metafile-sha256");

View File

@ -101,7 +101,7 @@ check_pkg_files(struct xbps_handle *xhp, const char *pkgname, void *arg)
path = xbps_xasprintf("%s/%s", xhp->rootdir, file); path = xbps_xasprintf("%s/%s", xhp->rootdir, file);
xbps_dictionary_get_cstring_nocopy(obj, xbps_dictionary_get_cstring_nocopy(obj,
"sha256", &sha256); "sha256", &sha256);
rv = xbps_file_hash_check(path, sha256); rv = xbps_file_sha256_check(path, sha256);
switch (rv) { switch (rv) {
case 0: case 0:
if (check_file_mtime(obj, pkgname, path)) { if (check_file_mtime(obj, pkgname, path)) {

View File

@ -72,7 +72,7 @@ cleaner_cb(struct xbps_handle *xhp, xbps_object_t obj,
if (repo_pkgd) { if (repo_pkgd) {
xbps_dictionary_get_cstring_nocopy(repo_pkgd, xbps_dictionary_get_cstring_nocopy(repo_pkgd,
"filename-sha256", &rsha256); "filename-sha256", &rsha256);
if (xbps_file_hash_check(binpkg, rsha256) == 0) { if (xbps_file_sha256_check(binpkg, rsha256) == 0) {
/* hash matched */ /* hash matched */
return 0; return 0;
} }

View File

@ -252,7 +252,8 @@ index_add(struct xbps_handle *xhp, int args, int argmax, char **argv, bool force
*/ */
for (int i = args; i < argmax; i++) { for (int i = args; i < argmax; i++) {
const char *arch = NULL, *pkg = argv[i]; const char *arch = NULL, *pkg = argv[i];
char *sha256 = NULL, *pkgver = NULL; char *pkgver = NULL;
char sha256[XBPS_SHA256_SIZE];
char pkgname[XBPS_NAME_SIZE]; char pkgname[XBPS_NAME_SIZE];
assert(pkg); assert(pkg);
@ -331,7 +332,7 @@ index_add(struct xbps_handle *xhp, int args, int argmax, char **argv, bool force
* - filename-size * - filename-size
* - filename-sha256 * - filename-sha256
*/ */
if ((sha256 = xbps_file_hash(pkg)) == NULL) { if (!xbps_file_sha256(sha256, sizeof sha256, pkg)) {
xbps_object_release(binpkgd); xbps_object_release(binpkgd);
free(pkgver); free(pkgver);
rv = EINVAL; rv = EINVAL;
@ -339,12 +340,10 @@ index_add(struct xbps_handle *xhp, int args, int argmax, char **argv, bool force
} }
if (!xbps_dictionary_set_cstring(binpkgd, "filename-sha256", sha256)) { if (!xbps_dictionary_set_cstring(binpkgd, "filename-sha256", sha256)) {
xbps_object_release(binpkgd); xbps_object_release(binpkgd);
free(sha256);
free(pkgver); free(pkgver);
rv = EINVAL; rv = EINVAL;
goto out; goto out;
} }
free(sha256);
if (stat(pkg, &st) == -1) { if (stat(pkg, &st) == -1) {
xbps_object_release(binpkgd); xbps_object_release(binpkgd);
free(pkgver); free(pkgver);

View File

@ -77,7 +77,7 @@ idx_cleaner_cb(struct xbps_handle *xhp,
*/ */
xbps_dictionary_get_cstring_nocopy(obj, xbps_dictionary_get_cstring_nocopy(obj,
"filename-sha256", &sha256); "filename-sha256", &sha256);
if (xbps_file_hash_check(filen, sha256) != 0) { if (xbps_file_sha256_check(filen, sha256) != 0) {
if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver))
goto out; goto out;
xbps_dictionary_remove(dest, pkgname); xbps_dictionary_remove(dest, pkgname);

View File

@ -97,25 +97,26 @@ static bool
rsa_sign_file(RSA *rsa, const char *file, rsa_sign_file(RSA *rsa, const char *file,
unsigned char **sigret, unsigned int *siglen) unsigned char **sigret, unsigned int *siglen)
{ {
unsigned char *sha256; unsigned char digest[XBPS_SHA256_DIGEST_SIZE];
sha256 = xbps_file_hash_raw(file); if (!xbps_file_sha256_raw(digest, sizeof digest, file))
if(!sha256)
return false; return false;
if ((*sigret = calloc(1, RSA_size(rsa) + 1)) == NULL) { if ((*sigret = calloc(1, RSA_size(rsa) + 1)) == NULL) {
free(sha256);
return false; return false;
} }
if (!RSA_sign(NID_sha1, sha256, SHA256_DIGEST_LENGTH, /*
* XXX: NID_sha1 is wrong, doesn't make it any weaker
* but the ASN1 is wrong, OpenSSL/LibreSSL doesn't care.
* Other implementations like golang fail because of this.
*/
if (!RSA_sign(NID_sha1, digest, XBPS_SHA256_DIGEST_SIZE,
*sigret, siglen, rsa)) { *sigret, siglen, rsa)) {
free(sha256);
free(*sigret); free(*sigret);
return false; return false;
} }
free(sha256);
return true; return true;
} }

View File

@ -285,19 +285,20 @@ main(int argc, char **argv)
printf("%s\n", XBPS_SYSDEFCONF_PATH); printf("%s\n", XBPS_SYSDEFCONF_PATH);
} else if (strcmp(argv[0], "digest") == 0) { } else if (strcmp(argv[0], "digest") == 0) {
char sha256[XBPS_SHA256_SIZE];
/* Prints SHA256 hashes for specified files */ /* Prints SHA256 hashes for specified files */
if (argc < 2) if (argc < 2)
usage(); usage();
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
filename = xbps_file_hash(argv[i]); if (!xbps_file_sha256(sha256, sizeof sha256, argv[i])) {
if (filename == NULL) {
fprintf(stderr, fprintf(stderr,
"E: couldn't get hash for %s (%s)\n", "E: couldn't get hash for %s (%s)\n",
argv[i], strerror(errno)); argv[i], strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
printf("%s\n", filename); printf("%s\n", sha256);
} }
} else if (strcmp(argv[0], "fetch") == 0) { } else if (strcmp(argv[0], "fetch") == 0) {
/* Fetch a file from specified URL */ /* Fetch a file from specified URL */

View File

@ -51,7 +51,7 @@
* *
* This header documents the full API for the XBPS Library. * This header documents the full API for the XBPS Library.
*/ */
#define XBPS_API_VERSION "20200208" #define XBPS_API_VERSION "20200210"
#ifndef XBPS_VERSION #ifndef XBPS_VERSION
#define XBPS_VERSION "UNSET" #define XBPS_VERSION "UNSET"
@ -258,6 +258,9 @@
*/ */
#define XBPS_FETCH_TIMEOUT 30 #define XBPS_FETCH_TIMEOUT 30
#define XBPS_SHA256_DIGEST_SIZE 32
#define XBPS_SHA256_SIZE 64+1
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -763,8 +766,8 @@ int xbps_fetch_file(struct xbps_handle *xhp, const char *uri,
* @return -1 on error, 0 if not downloaded (because local/remote size/mtime * @return -1 on error, 0 if not downloaded (because local/remote size/mtime
* do not match) and 1 if downloaded successfully. * do not match) and 1 if downloaded successfully.
**/ **/
int xbps_fetch_file_digest(struct xbps_handle *xhp, const char *uri, int xbps_fetch_file_sha256(struct xbps_handle *xhp, const char *uri,
const char *flags, unsigned char **digestp); const char *flags, unsigned char *digest, size_t digestlen);
/** /**
* Download a file from a remote URL to current working directory, * Download a file from a remote URL to current working directory,
@ -794,8 +797,9 @@ int xbps_fetch_file_dest(struct xbps_handle *xhp, const char *uri,
* @return -1 on error, 0 if not downloaded (because local/remote size/mtime * @return -1 on error, 0 if not downloaded (because local/remote size/mtime
* do not match) and 1 if downloaded successfully. * do not match) and 1 if downloaded successfully.
**/ **/
int xbps_fetch_file_dest_digest(struct xbps_handle *xhp, const char *uri, int xbps_fetch_file_dest_sha256(struct xbps_handle *xhp, const char *uri,
const char *filename, const char *flags, unsigned char **digestp); const char *filename, const char *flags,
unsigned char *digest, size_t digestlen);
/** /**
* Returns last error string reported by xbps_fetch_file(). * Returns last error string reported by xbps_fetch_file().
@ -1859,7 +1863,7 @@ bool xbps_mmap_file(const char *file, void **mmf, size_t *mmflen, size_t *filele
* is set appropiately. The pointer should be free(3)d when it's no * is set appropiately. The pointer should be free(3)d when it's no
* longer needed. * longer needed.
*/ */
char *xbps_file_hash(const char *file); bool xbps_file_sha256(char *dst, size_t dstlen, const char *file);
/** /**
* Returns a raw byte buffer with the sha256 hash for the file specified * Returns a raw byte buffer with the sha256 hash for the file specified
@ -1870,7 +1874,7 @@ char *xbps_file_hash(const char *file);
* is set appropiately. The pointer should be free(3)d when it's no * is set appropiately. The pointer should be free(3)d when it's no
* longer needed. * longer needed.
*/ */
unsigned char *xbps_file_hash_raw(const char *file); bool xbps_file_sha256_raw(unsigned char *dst, size_t dstlen, const char *file);
/** /**
* Compares the sha256 hash of the file \a file with the sha256 * Compares the sha256 hash of the file \a file with the sha256
@ -1882,7 +1886,7 @@ unsigned char *xbps_file_hash_raw(const char *file);
* @return 0 if \a file and \a sha256 have the same hash, ERANGE * @return 0 if \a file and \a sha256 have the same hash, ERANGE
* if it differs, or any other errno value on error. * if it differs, or any other errno value on error.
*/ */
int xbps_file_hash_check(const char *file, const char *sha256); int xbps_file_sha256_check(const char *file, const char *sha256);
/** /**
* Verifies the RSA signature \a sigfile against \a digest with the * Verifies the RSA signature \a sigfile against \a digest with the

View File

@ -93,7 +93,7 @@ xbps_fetch_error_string(void)
} }
int int
xbps_fetch_file_dest_digest(struct xbps_handle *xhp, const char *uri, const char *filename, const char *flags, unsigned char **digestp) xbps_fetch_file_dest_sha256(struct xbps_handle *xhp, const char *uri, const char *filename, const char *flags, unsigned char *digest, size_t digestlen)
{ {
struct stat st, st_tmpfile, *stp; struct stat st, st_tmpfile, *stp;
struct url *url = NULL; struct url *url = NULL;
@ -106,16 +106,13 @@ xbps_fetch_file_dest_digest(struct xbps_handle *xhp, const char *uri, const char
char fetch_flags[8]; char fetch_flags[8];
int fd = -1, rv = 0; int fd = -1, rv = 0;
bool refetch = false, restart = false; bool refetch = false, restart = false;
unsigned char *digest = NULL;
SHA256_CTX sha256; SHA256_CTX sha256;
assert(xhp); assert(xhp);
assert(uri); assert(uri);
if (digestp) { if (digest) {
digest = malloc(SHA256_DIGEST_LENGTH); assert(digestlen != XBPS_SHA256_DIGEST_SIZE);
if (!digest)
return -1;
SHA256_Init(&sha256); SHA256_Init(&sha256);
} }
@ -317,10 +314,8 @@ rename_file:
} }
rv = 1; rv = 1;
if (digest) { if (digest)
SHA256_Final(digest, &sha256); SHA256_Final(digest, &sha256);
*digestp = digest;
}
fetch_file_out: fetch_file_out:
if (fio != NULL) if (fio != NULL)
@ -339,12 +334,12 @@ int
xbps_fetch_file_dest(struct xbps_handle *xhp, const char *uri, xbps_fetch_file_dest(struct xbps_handle *xhp, const char *uri,
const char *filename, const char *flags) const char *filename, const char *flags)
{ {
return xbps_fetch_file_dest_digest(xhp, uri, filename, flags, NULL); return xbps_fetch_file_dest_sha256(xhp, uri, filename, flags, NULL, 0);
} }
int int
xbps_fetch_file_digest(struct xbps_handle *xhp, const char *uri, xbps_fetch_file_sha256(struct xbps_handle *xhp, const char *uri,
const char *flags, unsigned char **digestp) const char *flags, unsigned char *digest, size_t digestlen)
{ {
const char *filename; const char *filename;
/* /*
@ -354,11 +349,12 @@ xbps_fetch_file_digest(struct xbps_handle *xhp, const char *uri,
return -1; return -1;
filename++; filename++;
return xbps_fetch_file_dest_digest(xhp, uri, filename, flags, digestp); return xbps_fetch_file_dest_sha256(xhp, uri, filename, flags,
digest, digestlen);
} }
int int
xbps_fetch_file(struct xbps_handle *xhp, const char *uri, const char *flags) xbps_fetch_file(struct xbps_handle *xhp, const char *uri, const char *flags)
{ {
return xbps_fetch_file_digest(xhp, uri, flags, NULL); return xbps_fetch_file_sha256(xhp, uri, flags, NULL, 0);
} }

View File

@ -69,7 +69,7 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp,
xbps_object_t obj, obj2; xbps_object_t obj, obj2;
xbps_object_iterator_t iter, iter2; xbps_object_iterator_t iter, iter2;
const char *version = NULL, *cffile, *sha256_new = NULL; const char *version = NULL, *cffile, *sha256_new = NULL;
char buf[PATH_MAX], *sha256_cur = NULL, *sha256_orig = NULL; char buf[PATH_MAX], sha256_cur[XBPS_SHA256_SIZE], *sha256_orig = NULL;
int rv = 0; int rv = 0;
assert(xbps_object_type(binpkg_filesd) == XBPS_TYPE_DICTIONARY); assert(xbps_object_type(binpkg_filesd) == XBPS_TYPE_DICTIONARY);
@ -139,9 +139,7 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp,
if (strcmp(entry_pname, buf)) { if (strcmp(entry_pname, buf)) {
continue; continue;
} }
sha256_cur = xbps_file_hash(buf); if (!xbps_file_sha256(sha256_cur, sizeof sha256_cur, buf)) {
xbps_dictionary_get_cstring_nocopy(obj, "sha256", &sha256_new);
if (sha256_cur == NULL) {
if (errno == ENOENT) { if (errno == ENOENT) {
/* /*
* File not installed, install new one. * File not installed, install new one.
@ -155,6 +153,7 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp,
break; break;
} }
} }
xbps_dictionary_get_cstring_nocopy(obj, "sha256", &sha256_new);
/* /*
* Orig = X, Curr = X, New = X * Orig = X, Curr = X, New = X
* *
@ -232,15 +231,11 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp,
rv = 1; rv = 1;
break; break;
} }
free(sha256_cur);
sha256_cur = NULL;
} }
out: out:
if (sha256_orig) if (sha256_orig)
free(sha256_orig); free(sha256_orig);
if (sha256_cur)
free(sha256_cur);
xbps_object_iterator_release(iter); xbps_object_iterator_release(iter);

View File

@ -41,7 +41,8 @@ xbps_register_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkgrd)
struct tm tm; struct tm tm;
struct tm *tmp; struct tm *tmp;
const char *pkgver; const char *pkgver;
char *buf, *sha256; char sha256[XBPS_SHA256_SIZE];
char *buf;
int rv = 0; int rv = 0;
bool autoinst = false; bool autoinst = false;
@ -104,9 +105,8 @@ xbps_register_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkgrd)
* Create a hash for the pkg's metafile if it exists. * Create a hash for the pkg's metafile if it exists.
*/ */
buf = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname); buf = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname);
if ((sha256 = xbps_file_hash(buf))) { if (xbps_file_sha256(sha256, sizeof sha256, buf)) {
xbps_dictionary_set_cstring(pkgd, "metafile-sha256", sha256); xbps_dictionary_set_cstring(pkgd, "metafile-sha256", sha256);
free(sha256);
} }
free(buf); free(buf);
/* /*

View File

@ -79,7 +79,7 @@ verify_binpkg(struct xbps_handle *xhp, xbps_dictionary_t pkgd)
xbps_set_cb_state(xhp, XBPS_STATE_VERIFY, 0, pkgver, xbps_set_cb_state(xhp, XBPS_STATE_VERIFY, 0, pkgver,
"%s: verifying SHA256 hash...", pkgver); "%s: verifying SHA256 hash...", pkgver);
xbps_dictionary_get_cstring_nocopy(pkgd, "filename-sha256", &sha256); xbps_dictionary_get_cstring_nocopy(pkgd, "filename-sha256", &sha256);
if ((rv = xbps_file_hash_check(binfile, sha256)) != 0) { if ((rv = xbps_file_sha256_check(binfile, sha256)) != 0) {
xbps_set_cb_state(xhp, XBPS_STATE_VERIFY_FAIL, rv, pkgver, xbps_set_cb_state(xhp, XBPS_STATE_VERIFY_FAIL, rv, pkgver,
"%s: SHA256 hash is not valid: %s", pkgver, strerror(rv)); "%s: SHA256 hash is not valid: %s", pkgver, strerror(rv));
goto out; goto out;
@ -98,7 +98,7 @@ download_binpkg(struct xbps_handle *xhp, xbps_dictionary_t repo_pkgd)
char buf[PATH_MAX]; char buf[PATH_MAX];
char *sigsuffix; char *sigsuffix;
const char *pkgver, *arch, *fetchstr, *repoloc; const char *pkgver, *arch, *fetchstr, *repoloc;
unsigned char *digest = NULL; unsigned char digest[XBPS_SHA256_DIGEST_SIZE] = {0};
int rv = 0; int rv = 0;
xbps_dictionary_get_cstring_nocopy(repo_pkgd, "repository", &repoloc); xbps_dictionary_get_cstring_nocopy(repo_pkgd, "repository", &repoloc);
@ -129,7 +129,8 @@ download_binpkg(struct xbps_handle *xhp, xbps_dictionary_t repo_pkgd)
xbps_set_cb_state(xhp, XBPS_STATE_DOWNLOAD, 0, pkgver, xbps_set_cb_state(xhp, XBPS_STATE_DOWNLOAD, 0, pkgver,
"Downloading `%s' package (from `%s')...", pkgver, repoloc); "Downloading `%s' package (from `%s')...", pkgver, repoloc);
if ((rv = xbps_fetch_file_digest(xhp, buf, NULL, &digest)) == -1) { if ((rv = xbps_fetch_file_sha256(xhp, buf, NULL, digest,
sizeof digest)) == -1) {
rv = fetchLastErrCode ? fetchLastErrCode : errno; rv = fetchLastErrCode ? fetchLastErrCode : errno;
fetchstr = xbps_fetch_error_string(); fetchstr = xbps_fetch_error_string();
xbps_set_cb_state(xhp, XBPS_STATE_DOWNLOAD_FAIL, rv, xbps_set_cb_state(xhp, XBPS_STATE_DOWNLOAD_FAIL, rv,
@ -156,7 +157,7 @@ download_binpkg(struct xbps_handle *xhp, xbps_dictionary_t repo_pkgd)
* If digest is not set, binary package was not downloaded, * If digest is not set, binary package was not downloaded,
* i.e. 304 not modified, verify by file instead. * i.e. 304 not modified, verify by file instead.
*/ */
if (!digest) { if (*digest) {
*sigsuffix = '\0'; *sigsuffix = '\0';
if (!xbps_verify_file_signature(repo, buf)) { if (!xbps_verify_file_signature(repo, buf)) {
rv = EPERM; rv = EPERM;
@ -175,7 +176,6 @@ download_binpkg(struct xbps_handle *xhp, xbps_dictionary_t repo_pkgd)
*sigsuffix = '\0'; *sigsuffix = '\0';
(void)remove(buf); (void)remove(buf);
} }
free(digest);
} }
if (rv == EPERM) { if (rv == EPERM) {

View File

@ -75,6 +75,7 @@ itemhash(const char *file)
assert(file); assert(file);
/* XXX: runtime error: left shift of negative value -1581911230 */
for (i = 0; file[i]; ++i) for (i = 0; file[i]; ++i)
hv = (hv << 5) ^ (hv >> 23) ^ file[i]; hv = (hv << 5) ^ (hv >> 23) ^ file[i];
@ -321,7 +322,7 @@ collect_obsoletes(struct xbps_handle *xhp)
* Skip unexisting files and keep files with hash mismatch. * Skip unexisting files and keep files with hash mismatch.
*/ */
if (item->old.sha256) { if (item->old.sha256) {
rv = xbps_file_hash_check(item->file, item->old.sha256); rv = xbps_file_sha256_check(item->file, item->old.sha256);
switch (rv) { switch (rv) {
case 0: case 0:
/* hash matches, we can safely delete and/or overwrite it */ /* hash matches, we can safely delete and/or overwrite it */

View File

@ -108,65 +108,93 @@ xbps_mmap_file(const char *file, void **mmf, size_t *mmflen, size_t *filelen)
return true; return true;
} }
unsigned char * bool
xbps_file_hash_raw(const char *file) xbps_file_sha256_raw(unsigned char *dst, size_t dstlen, const char *file)
{ {
int fd; int fd;
ssize_t len; ssize_t len;
unsigned char *digest, buf[65536]; char buf[65536];
SHA256_CTX sha256; SHA256_CTX sha256;
assert(dstlen == SHA256_DIGEST_LENGTH);
if ((fd = open(file, O_RDONLY)) < 0) if ((fd = open(file, O_RDONLY)) < 0)
return NULL; return false;
digest = malloc(SHA256_DIGEST_LENGTH);
assert(digest);
SHA256_Init(&sha256); SHA256_Init(&sha256);
while ((len = read(fd, buf, sizeof(buf))) > 0) while ((len = read(fd, buf, sizeof(buf))) > 0)
SHA256_Update(&sha256, buf, len); SHA256_Update(&sha256, buf, len);
if(len < 0) {
free(digest);
return NULL;
}
SHA256_Final(digest, &sha256);
(void)close(fd); (void)close(fd);
return digest; if(len == -1)
return false;
SHA256_Final(dst, &sha256);
return true;
} }
char * bool
xbps_file_hash(const char *file) xbps_file_sha256(char *dst, size_t dstlen, const char *file)
{ {
char *hash; unsigned char digest[XBPS_SHA256_DIGEST_SIZE];
unsigned char *digest;
if (!(digest = xbps_file_hash_raw(file))) assert(dstlen == XBPS_SHA256_SIZE);
return NULL;
hash = malloc(SHA256_DIGEST_LENGTH * 2 + 1); if (!xbps_file_sha256_raw(digest, sizeof digest, file))
assert(hash); return false;
digest2string(digest, hash, SHA256_DIGEST_LENGTH);
free(digest);
return hash; digest2string(digest, dst, XBPS_SHA256_DIGEST_SIZE);
return true;
}
static bool
sha256_digest_compare(const char *sha256, size_t shalen,
const unsigned char *digest, size_t digestlen)
{
assert(digestlen == XBPS_SHA256_DIGEST_SIZE);
assert(shalen == XBPS_SHA256_SIZE - 1);
if (shalen != XBPS_SHA256_SIZE -1)
return false;
for (; *sha256;) {
if (*digest / 16 < 10) {
if (*sha256++ != '0' + *digest / 16)
return false;
} else {
if (*sha256++ != 'a' + *digest / 16 - 10)
return false;
}
if (*digest % 16 < 10) {
if (*sha256++ != '0' + *digest % 16)
return false;
} else {
if (*sha256++ != 'a' + *digest % 16 - 10)
return false;
}
digest++;
}
return true;
} }
int int
xbps_file_hash_check(const char *file, const char *sha256) xbps_file_sha256_check(const char *file, const char *sha256)
{ {
char *res; unsigned char digest[XBPS_SHA256_DIGEST_SIZE];
assert(file != NULL); assert(file != NULL);
assert(sha256 != NULL); assert(sha256 != NULL);
res = xbps_file_hash(file); if (!xbps_file_sha256_raw(digest, sizeof digest, file))
if (res == NULL)
return errno; return errno;
if (strcmp(sha256, res)) { if (!sha256_digest_compare(sha256, strlen(sha256), digest, sizeof digest))
free(res);
return ERANGE; return ERANGE;
}
free(res);
return 0; return 0;
} }
@ -226,10 +254,10 @@ xbps_file_hash_check_dictionary(struct xbps_handle *xhp,
} }
if (strcmp(xhp->rootdir, "/") == 0) { if (strcmp(xhp->rootdir, "/") == 0) {
rv = xbps_file_hash_check(file, sha256d); rv = xbps_file_sha256_check(file, sha256d);
} else { } else {
buf = xbps_xasprintf("%s/%s", xhp->rootdir, file); buf = xbps_xasprintf("%s/%s", xhp->rootdir, file);
rv = xbps_file_hash_check(buf, sha256d); rv = xbps_file_sha256_check(buf, sha256d);
free(buf); free(buf);
} }
if (rv == 0) if (rv == 0)

View File

@ -137,10 +137,10 @@ bool
xbps_verify_file_signature(struct xbps_repo *repo, const char *fname) xbps_verify_file_signature(struct xbps_repo *repo, const char *fname)
{ {
char sig[PATH_MAX]; char sig[PATH_MAX];
unsigned char *digest = NULL; unsigned char digest[XBPS_SHA256_DIGEST_SIZE];
bool val = false; bool val = false;
if (!(digest = xbps_file_hash_raw(fname))) { if (!xbps_file_sha256_raw(digest, sizeof digest, fname)) {
xbps_dbg_printf(repo->xhp, "can't open file %s: %s\n", fname, strerror(errno)); xbps_dbg_printf(repo->xhp, "can't open file %s: %s\n", fname, strerror(errno));
return false; return false;
} }
@ -148,6 +148,5 @@ xbps_verify_file_signature(struct xbps_repo *repo, const char *fname)
snprintf(sig, sizeof sig, "%s.sig", fname); snprintf(sig, sizeof sig, "%s.sig", fname);
val = xbps_verify_signature(repo, sig, digest); val = xbps_verify_signature(repo, sig, digest);
free(digest);
return val; return val;
} }