Beispiel #1
0
static void hmac_compute_key(const char *filename,
			     const struct update_stat *updt_stat,
			     char *key, size_t *key_len, bool use_xattrs)
{
	char *xattrs_blob = (void *)0xdeadcafe;
	size_t xattrs_blob_len = 0;

	if (use_xattrs) {
		xattrs_get_blob(filename, &xattrs_blob, &xattrs_blob_len);
	}

	hmac_sha256_for_data(key, (const unsigned char *)updt_stat,
			     sizeof(struct update_stat),
			     (const unsigned char *)xattrs_blob,
			     xattrs_blob_len);

	if (hash_is_zeros(key)) {
		*key_len = 0;
	} else {
		*key_len = SWUPD_HASH_LEN - 1;
	}

	if (xattrs_blob_len != 0) {
		free(xattrs_blob);
	}
}
Beispiel #2
0
static char *hmac_sha256_for_string(const unsigned char *key, size_t key_len, const char *str)
{
	if (str == NULL) {
		LOG_ERROR(NULL, "refusing to hmac NULL string", class_hash, "");
		return NULL;
	}

	return hmac_sha256_for_data(key, key_len, (const unsigned char *)str, strlen(str));
}
Beispiel #3
0
static void hmac_sha256_for_string(char *hash,
				   const unsigned char *key, size_t key_len,
				   const char *str)
{
	if (str == NULL) {
		hash_set_zeros(hash);
		return;
	}

	hmac_sha256_for_data(hash, key, key_len, (const unsigned char *)str, strlen(str));
}
Beispiel #4
0
static void hmac_compute_key(const char *file,
			     const struct update_stat *updt_stat,
			     char **key, size_t *key_len, bool use_xattrs)
{
	char *xattrs_blob = (void *)0xdeadcafe;
	size_t xattrs_blob_len = 0;

	if (use_xattrs)
		xattrs_get_blob(file, &xattrs_blob, &xattrs_blob_len);
	*key = hmac_sha256_for_data((const unsigned char *)updt_stat,
				    sizeof(struct update_stat),
				    (const unsigned char *)xattrs_blob,
				    xattrs_blob_len);

	if (*key == NULL)
		*key_len = 0;
	else
		*key_len = strlen((const char*)*key);

	if (xattrs_blob_len != 0)
		free(xattrs_blob);
}
Beispiel #5
0
/* TODO: how should we properly handle compute_hash() failures? */
int compute_hash(struct file *file, char *filename)
{
	int ret;
	char key[SWUPD_HASH_LEN];
	size_t key_len;
	unsigned char *blob;
	FILE *fl;

	if (file->is_deleted) {
		hash_set_zeros(file->hash);
		return 0;
	}

	hash_set_zeros(key);

	if (file->is_link) {
		char link[PATH_MAXLEN];
		memset(link, 0, PATH_MAXLEN);

		ret = readlink(filename, link, PATH_MAXLEN - 1);

		if (ret >= 0) {
			hmac_compute_key(filename, &file->stat, key, &key_len, file->use_xattrs);
			hmac_sha256_for_string(file->hash,
					       (const unsigned char *)key,
					       key_len,
					       link);
			return 0;
		} else {
			return -1;
		}
	}

	if (file->is_dir) {
		hmac_compute_key(filename, &file->stat, key, &key_len, file->use_xattrs);
		hmac_sha256_for_string(file->hash,
				       (const unsigned char *)key,
				       key_len,
				       SWUPD_HASH_DIRNAME); //Make independent of dirname
		return 0;
	}

	/* if we get here, this is a regular file */
	fl = fopen(filename, "r");
	if (!fl) {
		return -1;
	}
	blob = mmap(NULL, file->stat.st_size, PROT_READ, MAP_PRIVATE, fileno(fl), 0);
	if (blob == MAP_FAILED && file->stat.st_size != 0) {
		abort();
	}

	hmac_compute_key(filename, &file->stat, key, &key_len, file->use_xattrs);
	hmac_sha256_for_data(file->hash,
			     (const unsigned char *)key,
			     key_len,
			     blob,
			     file->stat.st_size);
	munmap(blob, file->stat.st_size);
	fclose(fl);
	return 0;
}
Beispiel #6
0
/* this function MUST be kept in sync with the server
 * return is NULL if there was an error. If the file does not exist,
 * a "0000000..." hash is returned as is our convention in the manifest
 * for deleted files */
char *compute_hash(struct file *file, char *filename)
{
	struct stat stat;
	int ret;
	unsigned char *blob;
	char *key = NULL;
	size_t key_len;
	FILE *fl;
	struct update_stat tfstat;
	char *hash = NULL;

	memset(&stat, 0, sizeof(stat));
	memset(&tfstat, 0, sizeof(tfstat));
	ret = lstat(filename, &stat);
	if (ret < 0) {
		if (errno == ENOENT) {
			LOG_DEBUG(NULL, "File does not exist, mark as deleted", class_file_misc, "%s", filename);
			file->is_deleted = 1;
			hash = strdup("0000000000000000000000000000000000000000000000000000000000000000");
			if (!hash)
				abort();
			return hash;
		}

		LOG_ERROR(NULL, "stat error ", class_file_io, "\\*filename=\"%s\",strerror=\"%s\"*\\",
				filename, strerror(errno));
		return NULL;
	}
	tfstat.st_mode = stat.st_mode;
	tfstat.st_uid = stat.st_uid;
	tfstat.st_gid = stat.st_gid;
	tfstat.st_rdev = stat.st_rdev;
	tfstat.st_size = stat.st_size;
	/* just server does this:
	file->size = stat.st_size;
	 */
	if ((file->is_link) || (S_ISLNK(stat.st_mode))) {
		char link[PATH_MAXLEN];
		memset(link, 0, PATH_MAXLEN);

		file->is_file = 0;
		file->is_dir = 0;
		file->is_link = 1;

		ret = readlink(filename, link, PATH_MAXLEN - 1);

		memset(&tfstat.st_mode, 0, sizeof(tfstat.st_mode));

		if (ret >= 0) {
			hmac_compute_key(filename, &tfstat, &key, &key_len, file->use_xattrs);
			hash = hmac_sha256_for_string(
					(const unsigned char *)key,
					key_len,
					link);
			if (!hash)
				abort();
			free(key);
			return hash;
		} else {
			LOG_ERROR(NULL, "readlink error ", class_file_io, "\\*ret=\"%i\",errno=\"%i\",strerror=\"%s\"*\\",
					ret, errno, strerror(errno));
			return NULL;
		}
	}

	if ((file->is_dir) || (S_ISDIR(stat.st_mode))) {
		file->is_file = 0;
		file->is_dir = 1;
		file->is_link = 0;

		tfstat.st_size = 0;

		hmac_compute_key(filename, &tfstat, &key, &key_len, file->use_xattrs);
		hash = hmac_sha256_for_string(
					(const unsigned char *)key,
					key_len,
					file->filename);	//file->filename not filename
		if (!hash)
			abort();
		free(key);
		return hash;
	}

	/* if we get here, this is a regular file */
	file->is_file = 1;
	file->is_dir = 0;
	file->is_link = 0;

	fl = fopen(filename, "r");
	if (!fl) {
		LOG_ERROR(NULL, "file open error ", class_file_io, "\\*filename=\"%s\",strerror=\"%s\"*\\",
				filename, strerror(errno));
		return NULL;
	}
	blob = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fileno(fl), 0);
	if (blob == MAP_FAILED && stat.st_size != 0)
		abort();

	hmac_compute_key(filename, &tfstat, &key, &key_len, file->use_xattrs);
	hash = hmac_sha256_for_data(
				(const unsigned char *)key,
				key_len,
				blob,
				stat.st_size);
	munmap(blob, stat.st_size);
	fclose(fl);
	if (!hash)
		abort();
	free(key);
	return hash;
}