libxbps: ABI/API break due to hash function changes
This commit is contained in:
		@@ -93,7 +93,7 @@ xbps_fetch_error_string(void)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 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];
 | 
			
		||||
	int fd = -1, rv = 0;
 | 
			
		||||
	bool refetch = false, restart = false;
 | 
			
		||||
	unsigned char *digest = NULL;
 | 
			
		||||
	SHA256_CTX sha256;
 | 
			
		||||
 | 
			
		||||
	assert(xhp);
 | 
			
		||||
	assert(uri);
 | 
			
		||||
 | 
			
		||||
	if (digestp) {
 | 
			
		||||
		digest = malloc(SHA256_DIGEST_LENGTH);
 | 
			
		||||
		if (!digest)
 | 
			
		||||
			return -1;
 | 
			
		||||
	if (digest) {
 | 
			
		||||
		assert(digestlen != XBPS_SHA256_DIGEST_SIZE);
 | 
			
		||||
		SHA256_Init(&sha256);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -317,10 +314,8 @@ rename_file:
 | 
			
		||||
	}
 | 
			
		||||
	rv = 1;
 | 
			
		||||
 | 
			
		||||
	if (digest) {
 | 
			
		||||
	if (digest)
 | 
			
		||||
		SHA256_Final(digest, &sha256);
 | 
			
		||||
		*digestp = digest;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
fetch_file_out:
 | 
			
		||||
	if (fio != NULL)
 | 
			
		||||
@@ -339,12 +334,12 @@ int
 | 
			
		||||
xbps_fetch_file_dest(struct xbps_handle *xhp, const char *uri,
 | 
			
		||||
		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
 | 
			
		||||
xbps_fetch_file_digest(struct xbps_handle *xhp, const char *uri,
 | 
			
		||||
		const char *flags, unsigned char **digestp)
 | 
			
		||||
xbps_fetch_file_sha256(struct xbps_handle *xhp, const char *uri,
 | 
			
		||||
		const char *flags, unsigned char *digest, size_t digestlen)
 | 
			
		||||
{
 | 
			
		||||
	const char *filename;
 | 
			
		||||
	/*
 | 
			
		||||
@@ -354,11 +349,12 @@ xbps_fetch_file_digest(struct xbps_handle *xhp, const char *uri,
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -69,7 +69,7 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp,
 | 
			
		||||
	xbps_object_t obj, obj2;
 | 
			
		||||
	xbps_object_iterator_t iter, iter2;
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	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)) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		sha256_cur = xbps_file_hash(buf);
 | 
			
		||||
		xbps_dictionary_get_cstring_nocopy(obj, "sha256", &sha256_new);
 | 
			
		||||
		if (sha256_cur == NULL) {
 | 
			
		||||
		if (!xbps_file_sha256(sha256_cur, sizeof sha256_cur, buf)) {
 | 
			
		||||
			if (errno == ENOENT) {
 | 
			
		||||
				/*
 | 
			
		||||
				 * File not installed, install new one.
 | 
			
		||||
@@ -155,6 +153,7 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp,
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		xbps_dictionary_get_cstring_nocopy(obj, "sha256", &sha256_new);
 | 
			
		||||
		/*
 | 
			
		||||
		 * Orig = X, Curr = X, New = X
 | 
			
		||||
		 *
 | 
			
		||||
@@ -232,15 +231,11 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp,
 | 
			
		||||
			rv = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		free(sha256_cur);
 | 
			
		||||
		sha256_cur = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	if (sha256_orig)
 | 
			
		||||
		free(sha256_orig);
 | 
			
		||||
	if (sha256_cur)
 | 
			
		||||
		free(sha256_cur);
 | 
			
		||||
 | 
			
		||||
	xbps_object_iterator_release(iter);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,8 @@ xbps_register_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkgrd)
 | 
			
		||||
	struct tm tm;
 | 
			
		||||
	struct tm *tmp;
 | 
			
		||||
	const char *pkgver;
 | 
			
		||||
	char *buf, *sha256;
 | 
			
		||||
	char sha256[XBPS_SHA256_SIZE];
 | 
			
		||||
	char *buf;
 | 
			
		||||
	int rv = 0;
 | 
			
		||||
	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.
 | 
			
		||||
	 */
 | 
			
		||||
	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);
 | 
			
		||||
		free(sha256);
 | 
			
		||||
	}
 | 
			
		||||
	free(buf);
 | 
			
		||||
	/*
 | 
			
		||||
 
 | 
			
		||||
@@ -79,7 +79,7 @@ verify_binpkg(struct xbps_handle *xhp, xbps_dictionary_t pkgd)
 | 
			
		||||
		xbps_set_cb_state(xhp, XBPS_STATE_VERIFY, 0, pkgver,
 | 
			
		||||
			"%s: verifying SHA256 hash...", pkgver);
 | 
			
		||||
		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,
 | 
			
		||||
				"%s: SHA256 hash is not valid: %s", pkgver, strerror(rv));
 | 
			
		||||
			goto out;
 | 
			
		||||
@@ -98,7 +98,7 @@ download_binpkg(struct xbps_handle *xhp, xbps_dictionary_t repo_pkgd)
 | 
			
		||||
	char buf[PATH_MAX];
 | 
			
		||||
	char *sigsuffix;
 | 
			
		||||
	const char *pkgver, *arch, *fetchstr, *repoloc;
 | 
			
		||||
	unsigned char *digest = NULL;
 | 
			
		||||
	unsigned char digest[XBPS_SHA256_DIGEST_SIZE] = {0};
 | 
			
		||||
	int rv = 0;
 | 
			
		||||
 | 
			
		||||
	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,
 | 
			
		||||
		"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;
 | 
			
		||||
		fetchstr = xbps_fetch_error_string();
 | 
			
		||||
		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,
 | 
			
		||||
	 * i.e. 304 not modified, verify by file instead.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!digest) {
 | 
			
		||||
	if (*digest) {
 | 
			
		||||
		*sigsuffix = '\0';
 | 
			
		||||
		if (!xbps_verify_file_signature(repo, buf)) {
 | 
			
		||||
			rv = EPERM;
 | 
			
		||||
@@ -175,7 +176,6 @@ download_binpkg(struct xbps_handle *xhp, xbps_dictionary_t repo_pkgd)
 | 
			
		||||
			*sigsuffix = '\0';
 | 
			
		||||
			(void)remove(buf);
 | 
			
		||||
		}
 | 
			
		||||
		free(digest);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (rv == EPERM) {
 | 
			
		||||
 
 | 
			
		||||
@@ -75,6 +75,7 @@ itemhash(const char *file)
 | 
			
		||||
 | 
			
		||||
	assert(file);
 | 
			
		||||
 | 
			
		||||
	/* XXX: runtime error: left shift of negative value -1581911230 */
 | 
			
		||||
	for (i = 0; file[i]; ++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.
 | 
			
		||||
		 */
 | 
			
		||||
		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) {
 | 
			
		||||
			case 0:
 | 
			
		||||
				/* hash matches, we can safely delete and/or overwrite it */
 | 
			
		||||
 
 | 
			
		||||
@@ -108,65 +108,93 @@ xbps_mmap_file(const char *file, void **mmf, size_t *mmflen, size_t *filelen)
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned char *
 | 
			
		||||
xbps_file_hash_raw(const char *file)
 | 
			
		||||
bool
 | 
			
		||||
xbps_file_sha256_raw(unsigned char *dst, size_t dstlen, const char *file)
 | 
			
		||||
{
 | 
			
		||||
	int fd;
 | 
			
		||||
	ssize_t len;
 | 
			
		||||
	unsigned char *digest, buf[65536];
 | 
			
		||||
	char buf[65536];
 | 
			
		||||
	SHA256_CTX sha256;
 | 
			
		||||
 | 
			
		||||
	assert(dstlen == SHA256_DIGEST_LENGTH);
 | 
			
		||||
 | 
			
		||||
	if ((fd = open(file, O_RDONLY)) < 0)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	digest = malloc(SHA256_DIGEST_LENGTH);
 | 
			
		||||
	assert(digest);
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	SHA256_Init(&sha256);
 | 
			
		||||
 | 
			
		||||
	while ((len = read(fd, buf, sizeof(buf))) > 0)
 | 
			
		||||
		SHA256_Update(&sha256, buf, len);
 | 
			
		||||
	if(len < 0) {
 | 
			
		||||
		free(digest);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	SHA256_Final(digest, &sha256);
 | 
			
		||||
 | 
			
		||||
	(void)close(fd);
 | 
			
		||||
 | 
			
		||||
	return digest;
 | 
			
		||||
	if(len == -1)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	SHA256_Final(dst, &sha256);
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *
 | 
			
		||||
xbps_file_hash(const char *file)
 | 
			
		||||
bool
 | 
			
		||||
xbps_file_sha256(char *dst, size_t dstlen, const char *file)
 | 
			
		||||
{
 | 
			
		||||
	char *hash;
 | 
			
		||||
	unsigned char *digest;
 | 
			
		||||
	unsigned char digest[XBPS_SHA256_DIGEST_SIZE];
 | 
			
		||||
 | 
			
		||||
	if (!(digest = xbps_file_hash_raw(file)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
	assert(dstlen == XBPS_SHA256_SIZE);
 | 
			
		||||
 | 
			
		||||
	hash = malloc(SHA256_DIGEST_LENGTH * 2 + 1);
 | 
			
		||||
	assert(hash);
 | 
			
		||||
	digest2string(digest, hash, SHA256_DIGEST_LENGTH);
 | 
			
		||||
	free(digest);
 | 
			
		||||
	if (!xbps_file_sha256_raw(digest, sizeof digest, file))
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
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(sha256 != NULL);
 | 
			
		||||
 | 
			
		||||
	res = xbps_file_hash(file);
 | 
			
		||||
	if (res == NULL)
 | 
			
		||||
	if (!xbps_file_sha256_raw(digest, sizeof digest, file))
 | 
			
		||||
		return errno;
 | 
			
		||||
 | 
			
		||||
	if (strcmp(sha256, res)) {
 | 
			
		||||
		free(res);
 | 
			
		||||
	if (!sha256_digest_compare(sha256, strlen(sha256), digest, sizeof digest))
 | 
			
		||||
		return ERANGE;
 | 
			
		||||
	}
 | 
			
		||||
	free(res);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -226,10 +254,10 @@ xbps_file_hash_check_dictionary(struct xbps_handle *xhp,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (strcmp(xhp->rootdir, "/") == 0) {
 | 
			
		||||
		rv = xbps_file_hash_check(file, sha256d);
 | 
			
		||||
		rv = xbps_file_sha256_check(file, sha256d);
 | 
			
		||||
	} else {
 | 
			
		||||
		buf = xbps_xasprintf("%s/%s", xhp->rootdir, file);
 | 
			
		||||
		rv = xbps_file_hash_check(buf, sha256d);
 | 
			
		||||
		rv = xbps_file_sha256_check(buf, sha256d);
 | 
			
		||||
		free(buf);
 | 
			
		||||
	}
 | 
			
		||||
	if (rv == 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -137,10 +137,10 @@ bool
 | 
			
		||||
xbps_verify_file_signature(struct xbps_repo *repo, const char *fname)
 | 
			
		||||
{
 | 
			
		||||
	char sig[PATH_MAX];
 | 
			
		||||
	unsigned char *digest = NULL;
 | 
			
		||||
	unsigned char digest[XBPS_SHA256_DIGEST_SIZE];
 | 
			
		||||
	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));
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
@@ -148,6 +148,5 @@ xbps_verify_file_signature(struct xbps_repo *repo, const char *fname)
 | 
			
		||||
	snprintf(sig, sizeof sig, "%s.sig", fname);
 | 
			
		||||
	val = xbps_verify_signature(repo, sig, digest);
 | 
			
		||||
 | 
			
		||||
	free(digest);
 | 
			
		||||
	return val;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user