コード例 #1
0
ファイル: hash.c プロジェクト: bradTpeters/swupd-client
static void hmac_sha256_for_data(char *hash,
				 const unsigned char *key, size_t key_len,
				 const unsigned char *data, size_t data_len)
{
	unsigned char digest[EVP_MAX_MD_SIZE];
	unsigned int digest_len = 0;
	char *digest_str;
	unsigned int i;

	if (data == NULL) {
		hash_set_zeros(hash);
		return;
	}

	if (HMAC(EVP_sha256(), (const void *)key, key_len, data, data_len, digest, &digest_len) == NULL) {
		hash_set_zeros(hash);
		return;
	}

	digest_str = calloc((digest_len * 2) + 1, sizeof(char));
	if (digest_str == NULL) {
		abort();
	}

	for (i = 0; i < digest_len; i++) {
		sprintf(&digest_str[i * 2], "%02x", (unsigned int)digest[i]);
	}

	hash_assign(digest_str, hash);
	free(digest_str);
}
コード例 #2
0
ファイル: hash.c プロジェクト: bradTpeters/swupd-client
/* provide a wrapper for compute_hash() because we want a cheap-out option in
 * case we are looking for missing files only:
 *   zeros hash: file missing
 *   ones hash:  file present */
int compute_hash_lazy(struct file *file, char *filename)
{
	struct stat sb;
	if (lstat(filename, &sb) == 0) {
		hash_set_ones(file->hash);
	} else {
		hash_set_zeros(file->hash);
	}
	return 0;
}
コード例 #3
0
ファイル: hash.c プロジェクト: bradTpeters/swupd-client
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));
}
コード例 #4
0
ファイル: hash.c プロジェクト: bradTpeters/swupd-client
/* 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;
}
コード例 #5
0
ファイル: manifest.c プロジェクト: bryteise/swupd-server
int match_manifests(struct manifest *m1, struct manifest *m2)
{
	GList *list1, *list2;
	struct file *file1, *file2;
	int must_sort = 0;
	int count = 0;
	int first = 1;

	if (!m1) {
		printf("Matching manifests up failed: No old manifest!\n");
		return -1;
	}

	if (!m2) {
		printf("Matching manifests up failed: No new manifest!\n");
		return -1;
	}

	m1->files = g_list_sort(m1->files, file_sort_filename);
	m2->files = g_list_sort(m2->files, file_sort_filename);

	list1 = g_list_first(m1->files);
	list2 = g_list_first(m2->files);

	while (list1 && list2) {
		int ret;
		file1 = list1->data;
		file2 = list2->data;

		file1->peer = NULL;
		file2->peer = NULL;

		ret = strcmp(file1->filename, file2->filename);
		if (ret == 0) {
			if (file1->is_deleted && file2->is_deleted && file1->is_rename) {
				file2->is_rename = file1->is_rename;
				hash_assign(file1->hash, file2->hash);
			}

			if (hash_compare(file1->hash, file2->hash) &&
			    file1->is_dir == file2->is_dir &&
			    file1->is_link == file2->is_link &&
			    file1->is_deleted == file2->is_deleted &&
			    file1->is_file == file2->is_file &&
			    file1->is_config == file2->is_config &&
			    file1->is_state == file2->is_state &&
			    file1->is_boot == file2->is_boot &&
			    file1->last_change >= minversion) {
				file2->last_change = file1->last_change;
				file2->is_rename = file1->is_rename;
			} else {
				account_changed_file();
				if (first) {
					LOG(file1, "file changed", "");
					first = 0;
				}
				count++;
			}

			if (!file1->is_deleted || file2->is_deleted) {
				file1->peer = file2;
				file2->peer = file1;
			}

			list1 = g_list_next(list1);
			list2 = g_list_next(list2);
			continue;
		}
		if (first) {
			LOG(file1, "file added? ", "(file2 is %s)", file2->filename);
			first = 0;
		}
		if (ret < 0) {
			struct file *file3;
			/*
			 * if we get here, file1 got deleted... what we must do
			 * is add a file entry for it in the target list.
			 * However, since we're currently walking the list we
			 * HAVE to prepend the entry.. and mark for sort at the
			 * end.
			 */
			file3 = calloc(1, sizeof(struct file));
			if (file3 == NULL) {
				assert(0);
			}

			file3->filename = strdup(file1->filename);
			hash_set_zeros(file3->hash);
			file3->is_deleted = 1;
			file3->is_config = file1->is_config;
			file3->is_state = file1->is_state;
			file3->is_boot = file1->is_boot;

			if (!file1->is_deleted) {
				file3->last_change = m2->version;
			} else {
				file3->last_change = file1->last_change;
				file3->is_rename = file1->is_rename;
				hash_assign(file1->hash, file3->hash);
			}

			file3->peer = file1;
			file1->peer = file3;

			list1 = g_list_next(list1);
			m2->files = g_list_prepend(m2->files, file3);
			m2->count++;
			if (!file1->is_deleted) {
				account_deleted_file();
				count++;
				if (first) {
					LOG(file1, "file got deleted", "");
					first = 0;
				}
			}
			must_sort = 1;
			continue;
		}
		/* if we get here, ret is > 0, which means this is a new file added */
		/* all we do is advance the pointer */
		account_new_file();
		list2 = g_list_next(list2);
		count++;
	}

	/* now deal with the tail ends */
	while (list1) {
		file1 = list1->data;

		struct file *file3;

		if (first) {
			LOG(file1, "file changed tail", "");
			first = 0;
		}
		count++;
		/*
		 * if we get here, file1 got deleted... what we must do is add
		 * a file entry for it in the target list.  However, since
		 * we're currently walking the list we HAVE to prepend the
		 * entry.. and mark for sort at the end.
		 */
		file3 = calloc(1, sizeof(struct file));
		if (file3 == NULL) {
			assert(0);
		}

		file3->filename = strdup(file1->filename);
		hash_set_zeros(file3->hash);
		file3->is_deleted = 1;
		file3->is_config = file1->is_config;
		file3->is_state = file1->is_state;
		file3->is_boot = file1->is_boot;

		if (!file1->is_deleted) {
			file3->last_change = m2->version;
		} else {
			file3->last_change = file1->last_change;
			file3->is_rename = file1->is_rename;
			hash_assign(file1->hash, file3->hash);
		}

		file3->peer = file1;
		file1->peer = file3;

		list1 = g_list_next(list1);
		m2->files = g_list_prepend(m2->files, file3);
		m2->count++;
		if (!file1->is_deleted) {
			account_deleted_file();
		}
		must_sort = 1;
	}

	while (list2) {
		account_new_file();
		list2 = g_list_next(list2);
		if (first) {
			first = 0;
		}
		count++;
	}
	if (must_sort) {
		m2->files = g_list_sort(m2->files, file_sort_filename);
	}

	return count;
}