コード例 #1
0
ファイル: add_image.c プロジェクト: ChloeTigre/wimlib
/* Creates and appends a 'struct wim_image_metadata' for an empty image.
 *
 * The resulting image will be the last in the WIM, so its index will be
 * the new value of wim->hdr.image_count.  */
static int
add_empty_image_metadata(WIMStruct *wim)
{
	int ret;
	struct wim_lookup_table_entry *metadata_lte;
	struct wim_security_data *sd;
	struct wim_image_metadata *imd;

	/* Create lookup table entry for this metadata resource (for now really
	 * just a dummy entry).  */
	ret = WIMLIB_ERR_NOMEM;
	metadata_lte = new_lookup_table_entry();
	if (!metadata_lte)
		goto out;

	metadata_lte->flags = WIM_RESHDR_FLAG_METADATA;
	metadata_lte->unhashed = 1;

	/* Create empty security data (no security descriptors).  */
	sd = new_wim_security_data();
	if (!sd)
		goto out_free_metadata_lte;

	imd = new_image_metadata();
	if (!imd)
		goto out_free_security_data;

	/* A NULL root_dentry indicates a completely empty image, without even a
	 * root directory.  */
	imd->root_dentry = NULL;
	imd->metadata_lte = metadata_lte;
	imd->security_data = sd;
	imd->modified = 1;

	/* Append as next image index.  */
	ret = append_image_metadata(wim, imd);
	if (ret)
		put_image_metadata(imd, NULL);
	goto out;

out_free_security_data:
	free_wim_security_data(sd);
out_free_metadata_lte:
	free_lookup_table_entry(metadata_lte);
out:
	return ret;
}
コード例 #2
0
ファイル: wim.c プロジェクト: twwbond/wimlib
static void
destroy_image_metadata(struct wim_image_metadata *imd,
                       struct blob_table *table,
                       bool free_metadata_blob_descriptor)
{
    free_dentry_tree(imd->root_dentry, table);
    imd->root_dentry = NULL;
    free_wim_security_data(imd->security_data);
    imd->security_data = NULL;

    if (free_metadata_blob_descriptor) {
        free_blob_descriptor(imd->metadata_blob);
        imd->metadata_blob = NULL;
    }
    if (!table) {
        struct blob_descriptor *blob, *tmp;
        list_for_each_entry_safe(blob, tmp, &imd->unhashed_blobs, unhashed_list)
        free_blob_descriptor(blob);
    }
    INIT_LIST_HEAD(&imd->unhashed_blobs);
    INIT_HLIST_HEAD(&imd->inode_list);
}
コード例 #3
0
/*
 * Reads and parses a metadata resource for an image in the WIM file.
 *
 * @imd:
 *	Pointer to the image metadata structure for the image whose metadata
 *	resource we are reading.  Its `metadata_blob' member specifies the blob
 *	table entry for the metadata resource.  The rest of the image metadata
 *	entry will be filled in by this function.
 *
 * Return values:
 *	WIMLIB_ERR_SUCCESS (0)
 *	WIMLIB_ERR_INVALID_METADATA_RESOURCE
 *	WIMLIB_ERR_NOMEM
 *	WIMLIB_ERR_READ
 *	WIMLIB_ERR_UNEXPECTED_END_OF_FILE
 *	WIMLIB_ERR_DECOMPRESSION
 */
int
read_metadata_resource(struct wim_image_metadata *imd)
{
	const struct blob_descriptor *metadata_blob;
	void *buf;
	int ret;
	u8 hash[SHA1_HASH_SIZE];
	struct wim_security_data *sd;
	struct wim_dentry *root;

	metadata_blob = imd->metadata_blob;

	/* Read the metadata resource into memory.  (It may be compressed.)  */
	ret = read_blob_into_alloc_buf(metadata_blob, &buf);
	if (ret)
		return ret;

	/* Checksum the metadata resource.  */
	sha1_buffer(buf, metadata_blob->size, hash);
	if (!hashes_equal(metadata_blob->hash, hash)) {
		ERROR("Metadata resource is corrupted "
		      "(invalid SHA-1 message digest)!");
		ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
		goto out_free_buf;
	}

	/* Parse the metadata resource.
	 *
	 * Notes: The metadata resource consists of the security data, followed
	 * by the directory entry for the root directory, followed by all the
	 * other directory entries in the filesystem.  The subdir offset field
	 * of each directory entry gives the start of its child entries from the
	 * beginning of the metadata resource.  An end-of-directory is signaled
	 * by a directory entry of length '0', really of length 8, because
	 * that's how long the 'length' field is.  */

	ret = read_wim_security_data(buf, metadata_blob->size, &sd);
	if (ret)
		goto out_free_buf;

	ret = read_dentry_tree(buf, metadata_blob->size, sd->total_length, &root);
	if (ret)
		goto out_free_security_data;

	/* We have everything we need from the buffer now.  */
	FREE(buf);
	buf = NULL;

	/* Calculate and validate inodes.  */

	ret = dentry_tree_fix_inodes(root, &imd->inode_list);
	if (ret)
		goto out_free_dentry_tree;

	fix_security_ids(imd, sd->num_entries);

	/* Success; fill in the image_metadata structure.  */
	imd->root_dentry = root;
	imd->security_data = sd;
	INIT_LIST_HEAD(&imd->unhashed_blobs);
	return 0;

out_free_dentry_tree:
	free_dentry_tree(root, NULL);
out_free_security_data:
	free_wim_security_data(sd);
out_free_buf:
	FREE(buf);
	return ret;
}
コード例 #4
0
ファイル: security.c プロジェクト: APBaltic/wimlib
/*
 * Reads the security data from the metadata resource of a WIM image.
 *
 * @buf
 *	Buffer containing an uncompressed WIM metadata resource.
 * @buf_len
 *	Length of the uncompressed metadata resource, in bytes.
 * @sd_ret
 *	On success, a pointer to the resulting security data structure will be
 *	returned here.
 *
 * Note: There is no `offset' argument because the security data is located at
 * the beginning of the metadata resource.
 *
 * Return values:
 *	WIMLIB_ERR_SUCCESS (0)
 *	WIMLIB_ERR_INVALID_METADATA_RESOURCE
 *	WIMLIB_ERR_NOMEM
 */
int
read_wim_security_data(const u8 *buf, size_t buf_len,
		       struct wim_security_data **sd_ret)
{
	struct wim_security_data *sd;
	int ret;
	u64 total_len;
	u64 sizes_size;
	u64 size_no_descriptors;
	const struct wim_security_data_disk *sd_disk;
	const u8 *p;

	if (buf_len < 8)
		return WIMLIB_ERR_INVALID_METADATA_RESOURCE;

	sd = new_wim_security_data();
	if (!sd)
		goto out_of_memory;

	sd_disk = (const struct wim_security_data_disk *)buf;
	sd->total_length = le32_to_cpu(sd_disk->total_length);
	sd->num_entries = le32_to_cpu(sd_disk->num_entries);

	DEBUG("Reading security data: num_entries=%u, total_length=%u",
	      sd->num_entries, sd->total_length);

	/* Length field of 0 is a special case that really means length
	 * of 8. */
	if (sd->total_length == 0)
		sd->total_length = 8;

	/* The security_id field of each dentry is a signed 32-bit integer, so
	 * the possible indices into the security descriptors table are 0
	 * through 0x7fffffff.  Which means 0x80000000 security descriptors
	 * maximum.  Not like you should ever have anywhere close to that many
	 * security descriptors! */
	if (sd->num_entries > 0x80000000)
		goto out_invalid_sd;

	/* Verify the listed total length of the security data is big enough to
	 * include the sizes array, verify that the file data is big enough to
	 * include it as well, then allocate the array of sizes.
	 *
	 * Note: The total length of the security data must fit in a 32-bit
	 * integer, even though each security descriptor size is a 64-bit
	 * integer.  This is stupid, and we need to be careful not to actually
	 * let the security descriptor sizes be over 0xffffffff.  */
	if (sd->total_length > buf_len)
		goto out_invalid_sd;

	sizes_size = (u64)sd->num_entries * sizeof(u64);
	size_no_descriptors = 8 + sizes_size;
	if (size_no_descriptors > sd->total_length)
		goto out_invalid_sd;

	total_len = size_no_descriptors;

	/* Return immediately if no security descriptors. */
	if (sd->num_entries == 0)
		goto out_align_total_length;

	/* Allocate a new buffer for the sizes array */
	sd->sizes = MALLOC(sizes_size);
	if (!sd->sizes)
		goto out_of_memory;

	/* Copy the sizes array into the new buffer */
	for (u32 i = 0; i < sd->num_entries; i++) {
		sd->sizes[i] = le64_to_cpu(sd_disk->sizes[i]);
		if (sd->sizes[i] > 0xffffffff)
			goto out_invalid_sd;
	}

	p = (const u8*)sd_disk + size_no_descriptors;

	/* Allocate the array of pointers to the security descriptors, then read
	 * them into separate buffers. */
	sd->descriptors = CALLOC(sd->num_entries, sizeof(sd->descriptors[0]));
	if (!sd->descriptors)
		goto out_of_memory;

	for (u32 i = 0; i < sd->num_entries; i++) {
		if (sd->sizes[i] == 0)
			continue;
		total_len += sd->sizes[i];
		if (total_len > (u64)sd->total_length)
			goto out_invalid_sd;
		sd->descriptors[i] = memdup(p, sd->sizes[i]);
		if (!sd->descriptors[i])
			goto out_of_memory;
		p += sd->sizes[i];
	}
out_align_total_length:
	total_len = (total_len + 7) & ~7;
	sd->total_length = (sd->total_length + 7) & ~7;
	if (total_len != sd->total_length) {
		WARNING("Expected WIM security data total length of "
			"%u bytes, but calculated %u bytes",
			sd->total_length, (unsigned)total_len);
	}
	*sd_ret = sd;
	ret = 0;
	goto out;
out_invalid_sd:
	ERROR("WIM security data is invalid!");
	ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
	goto out_free_sd;
out_of_memory:
	ERROR("Out of memory while reading WIM security data!");
	ret = WIMLIB_ERR_NOMEM;
out_free_sd:
	free_wim_security_data(sd);
out:
	return ret;
}