libxbps: ABI/API break due to hash function changes
This commit is contained in:
		@@ -55,7 +55,8 @@ struct xentry {
 | 
			
		||||
	TAILQ_ENTRY(xentry) entries;
 | 
			
		||||
	uint64_t mtime;
 | 
			
		||||
	uint64_t size;
 | 
			
		||||
	char *file, *type, *target, *hash;
 | 
			
		||||
	char *file, *type, *target;
 | 
			
		||||
	char sha256[XBPS_SHA256_SIZE];
 | 
			
		||||
	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;
 | 
			
		||||
	const char *filep = NULL;
 | 
			
		||||
	char *buf, *p, *p2, *dname;
 | 
			
		||||
	char sha256[XBPS_SHA256_SIZE];
 | 
			
		||||
	ssize_t r;
 | 
			
		||||
 | 
			
		||||
	/* 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);
 | 
			
		||||
		if ((p = xbps_file_hash(fpath)) == NULL)
 | 
			
		||||
			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)
 | 
			
		||||
		if (!xbps_file_sha256(xe->sha256, sizeof sha256, 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);
 | 
			
		||||
		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);
 | 
			
		||||
		if (xe->target)
 | 
			
		||||
			xbps_dictionary_set_cstring(d, "target", xe->target);
 | 
			
		||||
		if (xe->hash)
 | 
			
		||||
			xbps_dictionary_set_cstring(d, "sha256", xe->hash);
 | 
			
		||||
		if (*xe->sha256)
 | 
			
		||||
			xbps_dictionary_set_cstring(d, "sha256", xe->sha256);
 | 
			
		||||
		if (xe->mtime)
 | 
			
		||||
			xbps_dictionary_set_uint64(d, "mtime", xe->mtime);
 | 
			
		||||
		if (xe->size)
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,7 @@ int
 | 
			
		||||
main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	int c;
 | 
			
		||||
	char *hash = NULL;
 | 
			
		||||
	char sha256[XBPS_SHA256_SIZE];
 | 
			
		||||
	const char *mode = NULL, *progname = argv[0];
 | 
			
		||||
	const struct option longopts[] = {
 | 
			
		||||
		{ NULL, 0, NULL, 0 }
 | 
			
		||||
@@ -84,23 +84,19 @@ main(int argc, char **argv)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (argc < 1) {
 | 
			
		||||
		hash = xbps_file_hash("/dev/stdin");
 | 
			
		||||
		if (hash == NULL)
 | 
			
		||||
		if (!xbps_file_sha256(sha256, sizeof sha256, "/dev/stdin"))
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
 | 
			
		||||
		printf("%s\n", hash);
 | 
			
		||||
		free(hash);
 | 
			
		||||
		printf("%s\n", sha256);
 | 
			
		||||
	} else {
 | 
			
		||||
		for (int i = 0; i < argc; i++) {
 | 
			
		||||
			hash = xbps_file_hash(argv[i]);
 | 
			
		||||
			if (hash == NULL) {
 | 
			
		||||
			if (!xbps_file_sha256(sha256, sizeof sha256, argv[i])) {
 | 
			
		||||
				fprintf(stderr,
 | 
			
		||||
				    "%s: couldn't get hash for %s (%s)\n",
 | 
			
		||||
				progname, argv[i], strerror(errno));
 | 
			
		||||
				exit(EXIT_FAILURE);
 | 
			
		||||
			}
 | 
			
		||||
			printf("%s\n", hash);
 | 
			
		||||
			free(hash);
 | 
			
		||||
			printf("%s\n", sha256);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	exit(EXIT_SUCCESS);
 | 
			
		||||
 
 | 
			
		||||
@@ -138,13 +138,13 @@ main(int argc, char **argv)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < argc; i++) {
 | 
			
		||||
		unsigned char *digest = NULL;
 | 
			
		||||
		unsigned char digest[XBPS_SHA256_DIGEST_SIZE];
 | 
			
		||||
 | 
			
		||||
		if (i > 0 || !filename)
 | 
			
		||||
			filename = fname(argv[i]);
 | 
			
		||||
 | 
			
		||||
		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 {
 | 
			
		||||
			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());
 | 
			
		||||
		} else if (rv == 0) {
 | 
			
		||||
			fprintf(stderr, "%s: file is identical with remote.\n", argv[i]);
 | 
			
		||||
			if (shasum)
 | 
			
		||||
				digest = xbps_file_hash_raw(filename);
 | 
			
		||||
			if (shasum) {
 | 
			
		||||
				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 {
 | 
			
		||||
			rv = 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (digest != NULL) {
 | 
			
		||||
		if (*digest) {
 | 
			
		||||
			print_digest(digest, SHA256_DIGEST_LENGTH);
 | 
			
		||||
			printf("  %s\n", filename);
 | 
			
		||||
			free(digest);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,7 @@ check_pkg_integrity(struct xbps_handle *xhp,
 | 
			
		||||
			free(buf);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
		rv = xbps_file_hash_check(buf, sha256);
 | 
			
		||||
		rv = xbps_file_sha256_check(buf, sha256);
 | 
			
		||||
		free(buf);
 | 
			
		||||
		if (rv == ENOENT) {
 | 
			
		||||
			xbps_dictionary_remove(opkgd, "metafile-sha256");
 | 
			
		||||
 
 | 
			
		||||
@@ -99,9 +99,9 @@ check_pkg_files(struct xbps_handle *xhp, const char *pkgname, void *arg)
 | 
			
		||||
			if (xhp->noextract && xbps_patterns_match(xhp->noextract, file))
 | 
			
		||||
				continue;
 | 
			
		||||
			path = xbps_xasprintf("%s/%s", xhp->rootdir, file);
 | 
			
		||||
                        xbps_dictionary_get_cstring_nocopy(obj,
 | 
			
		||||
                            "sha256", &sha256);
 | 
			
		||||
			rv = xbps_file_hash_check(path, sha256);
 | 
			
		||||
			xbps_dictionary_get_cstring_nocopy(obj,
 | 
			
		||||
				"sha256", &sha256);
 | 
			
		||||
			rv = xbps_file_sha256_check(path, sha256);
 | 
			
		||||
			switch (rv) {
 | 
			
		||||
			case 0:
 | 
			
		||||
				if (check_file_mtime(obj, pkgname, path)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ cleaner_cb(struct xbps_handle *xhp, xbps_object_t obj,
 | 
			
		||||
	if (repo_pkgd) {
 | 
			
		||||
		xbps_dictionary_get_cstring_nocopy(repo_pkgd,
 | 
			
		||||
		    "filename-sha256", &rsha256);
 | 
			
		||||
		if (xbps_file_hash_check(binpkg, rsha256) == 0) {
 | 
			
		||||
		if (xbps_file_sha256_check(binpkg, rsha256) == 0) {
 | 
			
		||||
			/* hash matched */
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -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++) {
 | 
			
		||||
		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];
 | 
			
		||||
 | 
			
		||||
		assert(pkg);
 | 
			
		||||
@@ -331,7 +332,7 @@ index_add(struct xbps_handle *xhp, int args, int argmax, char **argv, bool force
 | 
			
		||||
		 * 	- filename-size
 | 
			
		||||
		 * 	- filename-sha256
 | 
			
		||||
		 */
 | 
			
		||||
		if ((sha256 = xbps_file_hash(pkg)) == NULL) {
 | 
			
		||||
		if (!xbps_file_sha256(sha256, sizeof sha256, pkg)) {
 | 
			
		||||
			xbps_object_release(binpkgd);
 | 
			
		||||
			free(pkgver);
 | 
			
		||||
			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)) {
 | 
			
		||||
			xbps_object_release(binpkgd);
 | 
			
		||||
			free(sha256);
 | 
			
		||||
			free(pkgver);
 | 
			
		||||
			rv = EINVAL;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		free(sha256);
 | 
			
		||||
		if (stat(pkg, &st) == -1) {
 | 
			
		||||
			xbps_object_release(binpkgd);
 | 
			
		||||
			free(pkgver);
 | 
			
		||||
 
 | 
			
		||||
@@ -77,7 +77,7 @@ idx_cleaner_cb(struct xbps_handle *xhp,
 | 
			
		||||
		 */
 | 
			
		||||
		xbps_dictionary_get_cstring_nocopy(obj,
 | 
			
		||||
				"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))
 | 
			
		||||
				goto out;
 | 
			
		||||
			xbps_dictionary_remove(dest, pkgname);
 | 
			
		||||
 
 | 
			
		||||
@@ -97,25 +97,26 @@ static bool
 | 
			
		||||
rsa_sign_file(RSA *rsa, const char *file,
 | 
			
		||||
	 unsigned char **sigret, unsigned int *siglen)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char *sha256;
 | 
			
		||||
	unsigned char digest[XBPS_SHA256_DIGEST_SIZE];
 | 
			
		||||
 | 
			
		||||
	sha256 = xbps_file_hash_raw(file);
 | 
			
		||||
	if(!sha256)
 | 
			
		||||
	if (!xbps_file_sha256_raw(digest, sizeof digest, file))
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	if ((*sigret = calloc(1, RSA_size(rsa) + 1)) == NULL) {
 | 
			
		||||
		free(sha256);
 | 
			
		||||
		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)) {
 | 
			
		||||
		free(sha256);
 | 
			
		||||
		free(*sigret);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	free(sha256);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -285,19 +285,20 @@ main(int argc, char **argv)
 | 
			
		||||
 | 
			
		||||
		printf("%s\n", XBPS_SYSDEFCONF_PATH);
 | 
			
		||||
	} else if (strcmp(argv[0], "digest") == 0) {
 | 
			
		||||
		char sha256[XBPS_SHA256_SIZE];
 | 
			
		||||
 | 
			
		||||
		/* Prints SHA256 hashes for specified files */
 | 
			
		||||
		if (argc < 2)
 | 
			
		||||
			usage();
 | 
			
		||||
 | 
			
		||||
		for (int i = 1; i < argc; i++) {
 | 
			
		||||
			filename = xbps_file_hash(argv[i]);
 | 
			
		||||
			if (filename == NULL) {
 | 
			
		||||
			if (!xbps_file_sha256(sha256, sizeof sha256, argv[i])) {
 | 
			
		||||
				fprintf(stderr,
 | 
			
		||||
				    "E: couldn't get hash for %s (%s)\n",
 | 
			
		||||
				    argv[i], strerror(errno));
 | 
			
		||||
				exit(EXIT_FAILURE);
 | 
			
		||||
			}
 | 
			
		||||
			printf("%s\n", filename);
 | 
			
		||||
			printf("%s\n", sha256);
 | 
			
		||||
		}
 | 
			
		||||
	} else if (strcmp(argv[0], "fetch") == 0) {
 | 
			
		||||
		/* Fetch a file from specified URL */
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 * This header documents the full API for the XBPS Library.
 | 
			
		||||
 */
 | 
			
		||||
#define XBPS_API_VERSION	"20200208"
 | 
			
		||||
#define XBPS_API_VERSION	"20200210"
 | 
			
		||||
 | 
			
		||||
#ifndef XBPS_VERSION
 | 
			
		||||
 #define XBPS_VERSION		"UNSET"
 | 
			
		||||
@@ -258,6 +258,9 @@
 | 
			
		||||
 */
 | 
			
		||||
#define XBPS_FETCH_TIMEOUT		30
 | 
			
		||||
 | 
			
		||||
#define XBPS_SHA256_DIGEST_SIZE 32
 | 
			
		||||
#define XBPS_SHA256_SIZE 64+1
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#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
 | 
			
		||||
 * do not match) and 1 if downloaded successfully.
 | 
			
		||||
 **/
 | 
			
		||||
int xbps_fetch_file_digest(struct xbps_handle *xhp, const char *uri,
 | 
			
		||||
		    const char *flags, unsigned char **digestp);
 | 
			
		||||
int xbps_fetch_file_sha256(struct xbps_handle *xhp, const char *uri,
 | 
			
		||||
		    const char *flags, unsigned char *digest, size_t digestlen);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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
 | 
			
		||||
 * do not match) and 1 if downloaded successfully.
 | 
			
		||||
 **/
 | 
			
		||||
int xbps_fetch_file_dest_digest(struct xbps_handle *xhp, const char *uri,
 | 
			
		||||
		    const char *filename, const char *flags, unsigned char **digestp);
 | 
			
		||||
int xbps_fetch_file_dest_sha256(struct xbps_handle *xhp, const char *uri,
 | 
			
		||||
		    const char *filename, const char *flags,
 | 
			
		||||
			unsigned char *digest, size_t digestlen);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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
 | 
			
		||||
 * 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
 | 
			
		||||
@@ -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
 | 
			
		||||
 * 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
 | 
			
		||||
@@ -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
 | 
			
		||||
 * 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
 | 
			
		||||
 
 | 
			
		||||
@@ -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