/* Reads the security descriptor values
 * Returns 1 if successful or -1 on error
 */
int libfsntfs_security_descriptor_values_read(
     libfsntfs_security_descriptor_values_t *security_descriptor_values,
     const uint8_t *data,
     size_t data_size,
     libcerror_error_t **error )
{
	static char *function = "libfsntfs_security_descriptor_values_read";

	if( security_descriptor_values == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid security descriptor values.",
		 function );

		return( -1 );
	}
	if( data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: invalid data.",
		 function );

		return( -1 );
	}
	if( data_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: invalid data size value out of bounds.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: security descriptor data:\n",
		 function );
		libcnotify_print_data(
		 data,
		 data_size,
		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
	}
#endif
	/* TODO use libfwnt to print the security descriptor */

	return( 1 );
}
/* Reads an index node
 * Returns 1 if successful or -1 on error
 */
int libpff_index_node_read(
     libpff_index_node_t *index_node,
     libpff_io_handle_t *io_handle,
     libbfio_handle_t *file_io_handle,
     off64_t node_offset,
     libcerror_error_t **error )
{
	uint8_t *index_node_footer_data              = NULL;
	static char *function                        = "libpff_index_node_read";
	ssize_t read_count                           = 0;
	uint32_t calculated_checksum                 = 0;
	uint32_t stored_checksum                     = 0;
	uint8_t calculated_entry_size                = 0;
	uint8_t calculated_maximum_number_of_entries = 0;
	uint8_t index_node_type_copy                 = 0;
	int result                                   = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	uint8_t *index_node_entry_data               = NULL;
	uint64_t value_64bit                         = 0;
	uint32_t value_32bit                         = 0;
	uint16_t entry_index                         = 0;
	uint16_t index_node_entry_data_size          = 0;
	uint16_t value_16bit                         = 0;
#endif

	if( index_node == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid index node.",
		 function );

		return( -1 );
	}
	if( index_node->data != NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
		 "%s: invalid index node - data already set.",
		 function );

		return( -1 );
	}
	if( io_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid IO handle.",
		 function );

		return( -1 );
	}
	if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
	 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
	 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported file type.",
		 function );

		return( -1 );
	}
	if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
	{
		index_node->data_size                 = 512;
		index_node->maximum_entries_data_size = 512 - sizeof( pff_index_node_32bit_footer_t );
	}
	else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
	{
		index_node->data_size                 = 512;
		index_node->maximum_entries_data_size = 512 - sizeof( pff_index_node_64bit_footer_t );
	}
	else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
	{
		index_node->data_size                 = 4096;
		index_node->maximum_entries_data_size = 4096 - sizeof( pff_index_node_64bit_4k_page_footer_t );
	}
	index_node->data = (uint8_t *) memory_allocate(
	                                sizeof( uint8_t ) * index_node->data_size );

	if( index_node->data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
		 "%s: unable to create index node data.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: reading index node data at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
		 function,
		 node_offset,
		 node_offset );
	}
#endif
	if( libbfio_handle_seek_offset(
	     file_io_handle,
	     node_offset,
	     SEEK_SET,
	     error ) == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_SEEK_FAILED,
		 "%s: unable to seek node offset: %" PRIi64 ".",
		 function,
		 node_offset );

		goto on_error;
	}
	read_count = libbfio_handle_read_buffer(
	              file_io_handle,
	              index_node->data,
	              index_node->data_size,
	              error );

	if( read_count != (ssize_t) index_node->data_size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read index node data.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: index node data:\n",
		 function );
		libcnotify_print_data(
		 index_node->data,
		 index_node->data_size,
		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
	}
#endif
	index_node_footer_data = &( index_node->data[ index_node->maximum_entries_data_size ] );

	if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
	{
		index_node->type     = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->type;
		index_node_type_copy = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->type_copy;

		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->back_pointer,
		 index_node->back_pointer );
		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->checksum,
		 stored_checksum );

		index_node->number_of_entries         = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->number_of_entries;
		index_node->maximum_number_of_entries = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->maximum_number_of_entries;
		index_node->entry_size                = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->entry_size;
		index_node->level                     = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->level;

		if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
		 && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) )
		{
			calculated_entry_size                = 16;
			calculated_maximum_number_of_entries = 496 / 16;
		}
		else
		{
			calculated_entry_size                = 12;
			calculated_maximum_number_of_entries = 496 / 12;
		}
	}
	else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
	{
		index_node->type     = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->type;
		index_node_type_copy = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->type_copy;

		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->checksum,
		 stored_checksum );
		byte_stream_copy_to_uint64_little_endian(
		 ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->back_pointer,
		 index_node->back_pointer );

		index_node->number_of_entries         = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->number_of_entries;
		index_node->maximum_number_of_entries = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->maximum_number_of_entries;
		index_node->entry_size                = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->entry_size;
		index_node->level                     = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->level;

		if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
		 && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) )
		{
			calculated_entry_size                = 32;
			calculated_maximum_number_of_entries = 488 / 32;
		}
		else
		{
			calculated_entry_size                = 24;
			calculated_maximum_number_of_entries = 488 / 24;
		}
	}
	else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
	{
		index_node->type     = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->type;
		index_node_type_copy = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->type_copy;

		byte_stream_copy_to_uint32_little_endian(
		 ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->checksum,
		 stored_checksum );
		byte_stream_copy_to_uint64_little_endian(
		 ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->back_pointer,
		 index_node->back_pointer );

		byte_stream_copy_to_uint16_little_endian(
		 ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->number_of_entries,
		 index_node->number_of_entries );
		byte_stream_copy_to_uint16_little_endian(
		 ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->maximum_number_of_entries,
		 index_node->maximum_number_of_entries );

		index_node->entry_size = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->entry_size;
		index_node->level      = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->level;

		if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
		 && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) )
		{
			calculated_entry_size                = 32;
			calculated_maximum_number_of_entries = 4056 / 32;
		}
		else
		{
			calculated_entry_size                = 24;
			calculated_maximum_number_of_entries = 4056 / 24;
		}
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: number of entries\t\t\t\t: %" PRIu16 "\n",
		 function,
		 index_node->number_of_entries );

		libcnotify_printf(
		 "%s: maximum number of entries\t\t\t: %" PRIu16 "\n",
		 function,
		 index_node->maximum_number_of_entries );

		libcnotify_printf(
		 "%s: entry size\t\t\t\t\t: %" PRIu8 "\n",
		 function,
		 index_node->entry_size );

		libcnotify_printf(
		 "%s: node level\t\t\t\t\t: %" PRIu8 "\n",
		 function,
		 index_node->level );

		if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
		{
			libcnotify_printf(
			 "%s: padding:\n",
			 function );
			libcnotify_print_data(
			 ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->padding1,
			 4,
			 0 );
		}
		else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
		{
			libcnotify_printf(
			 "%s: padding:\n",
			 function );
			libcnotify_print_data(
			 ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->padding1,
			 10,
			 0 );
		}
		libcnotify_printf(
		 "%s: index node type\t\t\t\t\t: 0x%02" PRIx8 "\n",
		 function,
		 index_node->type );
		libcnotify_printf(
		 "%s: index node type copy\t\t\t\t: 0x%02" PRIx8 "\n",
		 function,
		 index_node_type_copy );

		if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
		{
			byte_stream_copy_to_uint16_little_endian(
			 ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->signature,
			 value_16bit );
			libcnotify_printf(
			 "%s: signature\t\t\t\t\t: 0x%04" PRIx16 "\n",
			 function,
			 value_16bit );

			libcnotify_printf(
			 "%s: back pointer\t\t\t\t\t: 0x%08" PRIx64 "\n",
			 function,
			 index_node->back_pointer );
			libcnotify_printf(
			 "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
			 function,
			 stored_checksum );
		}
		else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
		{
			byte_stream_copy_to_uint16_little_endian(
			 ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->signature,
			 value_16bit );
			libcnotify_printf(
			 "%s: signature\t\t\t\t\t: 0x%04" PRIx16 "\n",
			 function,
			 value_16bit );

			libcnotify_printf(
			 "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
			 function,
			 stored_checksum );
			libcnotify_printf(
			 "%s: back pointer\t\t\t\t\t: 0x%08" PRIx64 "\n",
			 function,
			 index_node->back_pointer );
		}
		else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
		{
			byte_stream_copy_to_uint16_little_endian(
			 ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->signature,
			 value_16bit );
			libcnotify_printf(
			 "%s: signature\t\t\t\t\t: 0x%04" PRIx16 "\n",
			 function,
			 value_16bit );

			libcnotify_printf(
			 "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
			 function,
			 stored_checksum );
			libcnotify_printf(
			 "%s: back pointer\t\t\t\t\t: 0x%08" PRIx64 "\n",
			 function,
			 index_node->back_pointer );

			byte_stream_copy_to_uint64_little_endian(
			 ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->unknown1,
			 value_64bit );
			libcnotify_printf(
			 "%s: unknown1\t\t\t\t\t: 0x%08" PRIx64 "\n",
			 function,
			 value_64bit );
		}
		libcnotify_printf(
		 "\n" );
	}
#endif

	if( index_node->type != index_node_type_copy )
	{
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: mismatch in index node type (0x%02" PRIx8 " != 0x%02" PRIx8 ").\n",
			 function,
			 index_node->type,
			 index_node_type_copy );
		}
#endif
		if( ( index_node->type != LIBPFF_INDEX_TYPE_DESCRIPTOR )
		 && ( index_node->type != LIBPFF_INDEX_TYPE_OFFSET )
		 && ( ( index_node_type_copy == LIBPFF_INDEX_TYPE_DESCRIPTOR )
		   || ( index_node_type_copy == LIBPFF_INDEX_TYPE_OFFSET ) ) )
		{
			index_node->type = index_node_type_copy;
		}
	}
	if( ( index_node->type != LIBPFF_INDEX_TYPE_DESCRIPTOR )
	 && ( index_node->type != LIBPFF_INDEX_TYPE_OFFSET ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported index node type: 0x%02" PRIx8 ".",
		 function,
		 index_node->type );

		goto on_error;
	}
	if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
	{
		result = libfmapi_checksum_calculate_weak_crc32(
		          &calculated_checksum,
		          index_node->data,
		          500,
		          0,
		          error );
	}
	else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
	{
		result = libfmapi_checksum_calculate_weak_crc32(
		          &calculated_checksum,
		          index_node->data,
		          496,
		          0,
		          error );
	}
	else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
	{
		result = libfmapi_checksum_calculate_weak_crc32(
		          &calculated_checksum,
		          index_node->data,
		          4072,
		          0,
		          error );
	}
	if( result != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
		 "%s: unable to calculate weak CRC-32.",
		 function );

		goto on_error;
	}
	if( stored_checksum != calculated_checksum )
	{
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n",
			 function,
			 stored_checksum,
			 calculated_checksum );
		}
#endif
		/* TODO smart error handling */
	}
	if( ( index_node->entry_size != 0 )
	 && ( index_node->entry_size != calculated_entry_size ) )
	{
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: entry size mismatch (calculated: %" PRIu8 ", stored: %" PRIu8 ").\n",
			 function,
			 calculated_entry_size,
			 index_node->entry_size );
		}
#endif
		index_node->entry_size = calculated_entry_size;
	}
	if( ( index_node->maximum_number_of_entries != 0 )
	 && ( index_node->maximum_number_of_entries != calculated_maximum_number_of_entries ) )
	{
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: maximum number of entries mismatch (calculated: %" PRIu8 ", stored: %" PRIu8 ").\n",
			 function,
			 calculated_maximum_number_of_entries,
			 index_node->maximum_number_of_entries );
		}
#endif
		index_node->maximum_number_of_entries = calculated_maximum_number_of_entries;
	}
	if( index_node->number_of_entries > index_node->maximum_number_of_entries )
	{
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: number of entries: %" PRIu8 ", exceeds maximum: %" PRIu8 ".",
			 function,
			 index_node->number_of_entries,
			 index_node->maximum_number_of_entries );
		}
#endif
		index_node->number_of_entries = index_node->maximum_number_of_entries;
	}
	if( ( (uint16_t) index_node->number_of_entries * (uint16_t) index_node->entry_size ) > index_node->maximum_entries_data_size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: size of entries: %" PRIu16 ", exceeds maximum: %" PRIu16 ".",
		 function,
		 index_node->number_of_entries * index_node->entry_size,
		 index_node->maximum_entries_data_size );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		index_node_entry_data      = index_node->data;
		index_node_entry_data_size = index_node->maximum_entries_data_size;

		/* Print all the entries
		 */
		for( entry_index = 0;
		     entry_index < index_node->maximum_number_of_entries;
		     entry_index++ )
		{
			if( entry_index == index_node->number_of_entries )
			{
				result = libpff_index_node_check_for_empty_block(
					  index_node_entry_data,
					  index_node_entry_data_size,
					  error );

				if( result == -1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
					 "%s: unable to determine if remaining index nodes are empty.",
					 function );

					return( -1 );
				}
				else if( result != 0 )
				{
					break;
				}
				libcnotify_printf(
				 "\n" );
				libcnotify_printf(
				 "%s: remaining node entries\n",
				 function );
			}
			if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
			{
				byte_stream_copy_to_uint32_little_endian(
				 index_node_entry_data,
				 value_64bit );
			}
			else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
			      || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
			{
				byte_stream_copy_to_uint64_little_endian(
				 index_node_entry_data,
				 value_64bit );
			}
			libcnotify_printf(
			 "%s: entry: %03" PRIu16 " index node identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
			 function,
			 entry_index,
			 value_64bit,
			 value_64bit );

			/* Process descriptor index node leaf nodes
			 */
			if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
			 && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) )
			{
				if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
				{
					byte_stream_copy_to_uint32_little_endian(
					 ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->data_identifier,
					 value_64bit );
				}
				else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
				      || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
				{
					byte_stream_copy_to_uint64_little_endian(
					 ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->data_identifier,
					 value_64bit );
				}
				libcnotify_printf(
				 "%s: entry: %03" PRIu16 " data identifier\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
				 function,
				 entry_index,
				 value_64bit,
				 value_64bit );

				if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
				{
					byte_stream_copy_to_uint32_little_endian(
					 ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->local_descriptors_identifier,
					 value_64bit );
				}
				else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
				      || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
				{
					byte_stream_copy_to_uint64_little_endian(
					 ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->local_descriptors_identifier,
					 value_64bit );
				}
				libcnotify_printf(
				 "%s: entry: %03" PRIu16 " local descriptors identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
				 function,
				 entry_index,
				 value_64bit,
				 value_64bit );

				if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
				{
					byte_stream_copy_to_uint32_little_endian(
					 ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->parent_identifier,
					 value_32bit );
				}
				else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
				      || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
				{
					byte_stream_copy_to_uint32_little_endian(
					 ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->parent_identifier,
					 value_32bit );
				}
				libcnotify_printf(
				 "%s: entry: %03" PRIu16 " parent identifier\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n",
				 function,
				 entry_index,
				 value_32bit,
				 value_32bit );

				if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
				 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
				{
					byte_stream_copy_to_uint32_little_endian(
					 ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->unknown1,
					 value_32bit );

					libcnotify_printf(
					 "%s: entry: %03" PRIu16 " unknown1\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n",
					 function,
					 entry_index,
					 value_32bit,
					 value_32bit );
				}
			}
			/* Process offset and descriptor index node branch nodes and offset index node leaf nodes
			 */
			else
			{
				if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
				{
					if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
					{
						byte_stream_copy_to_uint32_little_endian(
						 ( (pff_index_node_branch_entry_32bit_t *) index_node_entry_data )->back_pointer,
						 value_64bit );
					}
					else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
					      || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
					{
						byte_stream_copy_to_uint64_little_endian(
						 ( (pff_index_node_branch_entry_64bit_t *) index_node_entry_data )->back_pointer,
						 value_64bit );
					}
					libcnotify_printf(
					 "%s: entry: %03" PRIu16 " back pointer\t\t\t\t: 0x%08" PRIx64 "\n",
					 function,
					 entry_index,
					 value_64bit );
				}
				if( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF )
				{
					if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
					{
						byte_stream_copy_to_uint32_little_endian(
						 ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->file_offset,
						 value_64bit );
					}
					else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
					      || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
					{
						byte_stream_copy_to_uint64_little_endian(
						 ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->file_offset,
						 value_64bit );
					}
				}
				else
				{
					if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
					{
						byte_stream_copy_to_uint32_little_endian(
						 ( (pff_index_node_branch_entry_32bit_t *) index_node_entry_data )->file_offset,
						 value_64bit );
					}
					else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
					      || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
					{
						byte_stream_copy_to_uint64_little_endian(
						 ( (pff_index_node_branch_entry_64bit_t *) index_node_entry_data )->file_offset,
						 value_64bit );
					}
				}
				libcnotify_printf(
				 "%s: entry: %03" PRIu16 " file offset\t\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
				 function,
				 entry_index,
				 value_64bit,
				 value_64bit );

				if( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF )
				{
					if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
					{
						byte_stream_copy_to_uint16_little_endian(
						 ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->data_size,
						 value_16bit );
					}
					else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
					      || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
					{
						byte_stream_copy_to_uint16_little_endian(
						 ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->data_size,
						 value_16bit );
					}
					libcnotify_printf(
					 "%s: entry: %03" PRIu16 " data size\t\t\t\t: %" PRIu16 "\n",
					 function,
					 entry_index,
					 value_16bit );

					if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
					{
						byte_stream_copy_to_uint16_little_endian(
						 ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->reference_count,
						 value_16bit );
					}
					else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
					      || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
					{
						byte_stream_copy_to_uint16_little_endian(
						 ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->reference_count,
						 value_16bit );
					}
					libcnotify_printf(
					 "%s: entry: %03" PRIu16 " reference count\t\t\t: %" PRIu16 "\n",
					 function,
					 entry_index,
					 value_16bit );

					if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
					 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
					{
						byte_stream_copy_to_uint32_little_endian(
						 ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->data_allocation_table_file_offset,
						 value_32bit );

						libcnotify_printf(
						 "%s: entry: %03" PRIu16 " data allocation table offset\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n",
						 function,
						 entry_index,
						 value_32bit,
						 value_32bit );
					}
				}
			}
			index_node_entry_data      += index_node->entry_size;
			index_node_entry_data_size -= index_node->entry_size;
		}
		libcnotify_printf(
		 "\n" );
	}
#endif
	index_node->entries_data = index_node->data;

	return( 1 );

on_error:
	if( index_node->data != NULL )
	{
		memory_free(
		 index_node->data );

		index_node->data = NULL;
	}
	return( -1 );
}
Beispiel #3
0
/* Sends a ATA DEVICE CONFIGURATION IDENTIFY to the file descriptor
 * Returns 1 if successful, 0 if not or -1 on error
 */
int libsmdev_ata_get_device_configuration(
     libcfile_file_t *device_file,
     struct hd_driveid *device_configuration,
     libcerror_error_t **error )
{
	static char *function = "libsmdev_ata_get_device_configuration";
	int read_count        = 0;

	if( device_configuration == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid device configuration.",
		 function );

		return( -1 );
	}
#if defined( HDIO_GET_IDENTITY )
	read_count = libcfile_file_io_control_read(
	              device_file,
	              HDIO_GET_IDENTITY,
	              NULL,
	              0,
	              (uint8_t *) device_configuration,
	              sizeof( struct hd_driveid ),
	              error );

	if( read_count == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_IOCTL_FAILED,
		 "%s: unable to query device file for: HDIO_GET_IDENTITY.",
		 function );

#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			if( ( error != NULL )
			 && ( *error != NULL ) )
			{
				libcnotify_print_error_backtrace(
				 *error );
			}
		}
#endif
		libcerror_error_free(
		 error );

		return( 0 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: HDIO_GET_IDENTITY:\n",
		 function );
		libcnotify_print_data(
		 (uint8_t *) device_configuration,
		 sizeof( struct hd_driveid ),
		 0 );

		libcnotify_printf(
		 "Feature sets:\n" );

		libcnotify_printf(
		 "SMART:\t\t\t%d\n",
		 ( device_configuration->command_set_1 & 0x0001 ) );

		libcnotify_printf(
		 "Security Mode:\t\t%d (%d)\n",
		 ( device_configuration->command_set_1 & 0x0002 ) >> 1,
		 ( device_configuration->dlf & 0x0001 ) );

		libcnotify_printf(
		 "Security Mode enabled:\t%d\n",
		 ( device_configuration->dlf & 0x0002 ) >> 1 );

		libcnotify_printf(
		 "Removable Media:\t%d\n",
		 ( device_configuration->command_set_1 & 0x0004 ) >> 2 );

		libcnotify_printf(
		 "HPA:\t\t\t%d\n",
		 ( device_configuration->command_set_1 & 0x0400 ) >> 10 );

		libcnotify_printf(
		 "DCO:\t\t\t%d\n",
		 ( device_configuration->command_set_2 & 0x0800 ) >> 11 );

		libcnotify_printf(
		 "Media serial:\t\t%d\n",
		 ( device_configuration->cfsse & 0x0004 ) >> 2 );

		libcnotify_printf(
		 "\n" );
	}
Beispiel #4
0
/* De- or encrypts a block of data
 * Returns 1 if successful or -1 on error
 */
int libbde_encryption_crypt(
     libbde_encryption_context_t *context,
     int mode,
     const uint8_t *input_data,
     size_t input_data_size,
     uint8_t *output_data,
     size_t output_data_size,
     uint64_t block_key,
     libcerror_error_t **error )
{
	uint8_t block_key_data[ 16 ];
	uint8_t initialization_vector[ 16 ];
	uint8_t sector_key_data[ 32 ];

	static char *function        = "libbde_encryption_crypt";
	size_t data_index            = 0;
	size_t sector_key_data_index = 0;

	if( context == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid context.",
		 function );

		return( -1 );
	}
	if( ( mode != LIBBDE_ENCRYPTION_CRYPT_MODE_DECRYPT )
	 && ( mode != LIBBDE_ENCRYPTION_CRYPT_MODE_ENCRYPT ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported mode.",
		 function );

		return( -1 );
	}
	if( memory_set(
	     initialization_vector,
	     0,
	     16 ) == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
		 "%s: unable to clear initialization vector.",
		 function );

		return( -1 );
	}
	if( memory_set(
	     block_key_data,
	     0,
	     16 ) == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
		 "%s: unable to clear block key data.",
		 function );

		return( -1 );
	}
	if( memory_set(
	     sector_key_data,
	     0,
	     32 ) == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
		 "%s: unable to clear sector key data.",
		 function );

		return( -1 );
	}
	if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC )
	 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER )
	 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC )
	 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) )
	{
		byte_stream_copy_from_uint64_little_endian(
		 block_key_data,
		 block_key );

		/* The block key for the initialization vector is encrypted
		 * with the FVEK
		 */
		if( libcaes_crypt_ecb(
		     context->fvek_encryption_context,
		     LIBCAES_CRYPT_MODE_ENCRYPT,
		     block_key_data,
		     16,
		     initialization_vector,
		     16,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
			 LIBCERROR_ENCRYPTION_ERROR_GENERIC,
			 "%s: unable to encrypt initialization vector.",
			 function );

			return( -1 );
		}
		if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER )
		 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) )
		{
			/* The block key for the sector key data is encrypted
			 * with the TWEAK key
			 */
			if( libcaes_crypt_ecb(
			     context->tweak_encryption_context,
			     LIBCAES_CRYPT_MODE_ENCRYPT,
			     block_key_data,
			     16,
			     sector_key_data,
			     16,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
				 LIBCERROR_ENCRYPTION_ERROR_GENERIC,
				 "%s: unable to encrypt sector key data.",
				 function );

				return( -1 );
			}
			/* Set the last byte to contain 0x80 (128)
			 */
			block_key_data[ 15 ] = 0x80;

			if( libcaes_crypt_ecb(
			     context->tweak_encryption_context,
			     LIBCAES_CRYPT_MODE_ENCRYPT,
			     block_key_data,
			     16,
			     &( sector_key_data[ 16 ] ),
			     16,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
				 LIBCERROR_ENCRYPTION_ERROR_GENERIC,
				 "%s: unable to encrypt sector key data.",
				 function );

				return( -1 );
			}
		}
	}
	else if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_XTS )
	      || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_XTS ) )
	{
		byte_stream_copy_from_uint64_little_endian(
		 initialization_vector,
		 block_key );

/* TODO: implement */
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: initialization vector:\n",
		 function );
		libcnotify_print_data(
		 initialization_vector,
		 16,
		 0 );
	}
#endif
	if( mode == LIBBDE_ENCRYPTION_CRYPT_MODE_ENCRYPT )
	{
/* TODO safe guard input data ? */
		if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER )
		 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) )
		{
			sector_key_data_index = 0;

			for( data_index = 0;
			     data_index < input_data_size;
			     data_index++ )
			{
				output_data[ data_index ] ^= sector_key_data[ sector_key_data_index ];

				sector_key_data_index++;

				if( sector_key_data_index >= 32 )
				{
					sector_key_data_index -= 32;
				}
			}
			if( libbde_diffuser_encrypt(
			     output_data,
			     output_data_size,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
				 LIBCERROR_ENCRYPTION_ERROR_ENCRYPT_FAILED,
				 "%s: unable to encrypt data using Diffuser.",
				 function );

				return( -1 );
			}
		}
		if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC )
		 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER )
		 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC )
		 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) )
		{
			if( libcaes_crypt_cbc(
			     context->fvek_encryption_context,
			     LIBCAES_CRYPT_MODE_ENCRYPT,
			     initialization_vector,
			     16,
			     input_data,
			     input_data_size,
			     output_data,
			     output_data_size,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
				 LIBCERROR_ENCRYPTION_ERROR_GENERIC,
				 "%s: unable to AES-CBC encrypt output data.",
				 function );

				return( -1 );
			}
		}
		else if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_XTS )
		      || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_XTS ) )
		{
			if( libcaes_crypt_xts(
			     context->fvek_decryption_tweaked_context,
			     LIBCAES_CRYPT_MODE_ENCRYPT,
			     initialization_vector,
			     16,
			     input_data,
			     input_data_size,
			     output_data,
			     output_data_size,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
				 LIBCERROR_ENCRYPTION_ERROR_GENERIC,
				 "%s: unable to AES-XTS decrypt output data.",
				 function );

				return( -1 );
			}
		}
	}
	else
	{
		if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC )
		 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER )
		 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC )
		 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) )
		{
			if( libcaes_crypt_cbc(
			     context->fvek_decryption_context,
			     LIBCAES_CRYPT_MODE_DECRYPT,
			     initialization_vector,
			     16,
			     input_data,
			     input_data_size,
			     output_data,
			     output_data_size,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
				 LIBCERROR_ENCRYPTION_ERROR_GENERIC,
				 "%s: unable to AES-CBC decrypt output data.",
				 function );

				return( -1 );
			}
		}
		else if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_XTS )
		      || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_XTS ) )
		{
			if( libcaes_crypt_xts(
			     context->fvek_decryption_tweaked_context,
			     LIBCAES_CRYPT_MODE_DECRYPT,
			     initialization_vector,
			     16,
			     input_data,
			     input_data_size,
			     output_data,
			     output_data_size,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
				 LIBCERROR_ENCRYPTION_ERROR_GENERIC,
				 "%s: unable to AES-XTS decrypt output data.",
				 function );

				return( -1 );
			}
		}
		if( ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_128_CBC_DIFFUSER )
		 || ( context->method == LIBBDE_ENCRYPTION_METHOD_AES_256_CBC_DIFFUSER ) )
		{
			if( libbde_diffuser_decrypt(
			     output_data,
			     output_data_size,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
				 LIBCERROR_ENCRYPTION_ERROR_DECRYPT_FAILED,
				 "%s: unable to decrypt data using Diffuser.",
				 function );

				return( -1 );
			}
			sector_key_data_index = 0;

			for( data_index = 0;
			     data_index < input_data_size;
			     data_index++ )
			{
				output_data[ data_index ] ^= sector_key_data[ sector_key_data_index ];

				sector_key_data_index++;

				if( sector_key_data_index >= 32 )
				{
					sector_key_data_index -= 32;
				}
			}
		}
	}
	return( 1 );
}
Beispiel #5
0
/* Reads the channel
 * Returns 1 if successful or -1 on error
 */
int libfwevt_channel_read(
     libfwevt_channel_t *channel,
     const uint8_t *data,
     size_t data_size,
     size_t data_offset,
     libcerror_error_t **error )
{
	libfwevt_internal_channel_t *internal_channel = NULL;
	fwevt_template_channel_t *wevt_channel        = NULL;
	static char *function                         = "libfwevt_channel_read";
	uint32_t channel_data_offset                  = 0;
	uint32_t channel_data_size                    = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	system_character_t *value_string              = NULL;
	size_t value_string_size                      = 0;
	uint32_t value_32bit                          = 0;
	int result                                    = 0;
#endif

	if( channel == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid channel.",
		 function );

		return( -1 );
	}
	internal_channel = (libfwevt_internal_channel_t *) channel;

	if( data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid data.",
		 function );

		return( -1 );
	}
	if( data_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid data size value exceeds maximum.",
		 function );

		return( -1 );
	}
	if( data_offset >= data_size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: invalid data offset value out of bounds.",
		 function );

		return( -1 );
	}
	if( ( data_size < sizeof( fwevt_template_channel_t ) )
	 || ( data_offset > ( data_size - sizeof( fwevt_template_channel_t ) ) ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
		 "%s: invalid data value too small.",
		 function );

		return( -1 );
	}
	wevt_channel = (fwevt_template_channel_t *) &( data[ data_offset ] );

#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: channel data:\n",
		 function );
		libcnotify_print_data(
		 (uint8_t *) wevt_channel,
		 sizeof( fwevt_template_channel_t ),
		 0 );
	}
#endif /* defined( HAVE_DEBUG_OUTPUT ) */

	byte_stream_copy_to_uint32_little_endian(
	 wevt_channel->identifier,
	 internal_channel->identifier );

	byte_stream_copy_to_uint32_little_endian(
	 wevt_channel->data_offset,
	 channel_data_offset );

#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: identifier\t\t\t\t\t: %" PRIu32 "\n",
		 function,
		 internal_channel->identifier );

		libcnotify_printf(
		 "%s: data offset\t\t\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 channel_data_offset );

		byte_stream_copy_to_uint32_little_endian(
		 wevt_channel->unknown1,
		 value_32bit );
		libcnotify_printf(
		 "%s: unknown1\t\t\t\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 value_32bit );

		byte_stream_copy_to_uint32_little_endian(
		 wevt_channel->message_identifier,
		 value_32bit );
		libcnotify_printf(
		 "%s: message identifier\t\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 value_32bit );
	}
#endif /* defined( HAVE_DEBUG_OUTPUT ) */

	if( channel_data_offset > 0 )
	{
		if( channel_data_offset >= ( data_size - 4 ) )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
			 "%s: invalid channel data offset value out of bounds.",
			 function );

			return( -1 );
		}
		byte_stream_copy_to_uint32_little_endian(
		 &( data[ channel_data_offset ] ),
		 channel_data_size );

		if( ( data_size < channel_data_size )
		 || ( channel_data_offset > ( data_size - channel_data_size ) ) )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
			 "%s: invalid channel data size value out of bounds.",
			 function );

			return( -1 );
		}
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: data:\n",
			 function );
			libcnotify_print_data(
			 &( data[ channel_data_offset ] ),
			 channel_data_size,
			 0 );
		}
#endif /* defined( HAVE_DEBUG_OUTPUT ) */

#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: data size\t\t\t\t\t: %" PRIu32 "\n",
			 function,
			 channel_data_size );
		}
#endif /* defined( HAVE_DEBUG_OUTPUT ) */

		if( channel_data_size >= 4 )
		{
			channel_data_offset += 4;
			channel_data_size   -= 4;

#if defined( HAVE_DEBUG_OUTPUT )
			if( libcnotify_verbose != 0 )
			{
				if( libfwevt_debug_print_utf16_string_value(
				     function,
				     "name\t\t\t\t\t\t",
				     &( data[ channel_data_offset ] ),
				     channel_data_size,
				     LIBUNA_ENDIAN_LITTLE,
				     error ) != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
					 "%s: unable to print UTF-16 string value.",
					 function );

					return( -1 );
				}
			}
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
		}
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "\n" );
	}
#endif
	return( 1 );
}
/* Reads the property set from the property set stream
 * Returns 1 if successful or -1 on error
 */
int libolecf_property_set_read(
     libolecf_property_set_t *property_set,
     libolecf_io_handle_t *io_handle,
     libolecf_item_t *property_set_stream,
     libcerror_error_t **error )
{
	olecf_property_set_header_t property_set_header;

	libolecf_internal_property_set_t *internal_property_set = NULL;
	libolecf_property_section_t *property_section           = NULL;
	static char *function                                   = "libolecf_property_set_read";
	off64_t section_list_entry_offset                       = 0;
	ssize_t read_count                                      = 0;
	uint32_t section_header_offset                          = 0;
	uint16_t number_of_sections                             = 0;
	uint16_t section_index                                  = 0;
	int sections_entry                                      = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	libcstring_system_character_t guid_string[ 48 ];

	libfguid_identifier_t *guid                             = NULL;
	int result                                              = 0;
#endif

	if( property_set == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid property set.",
		 function );

		return( -1 );
	}
	internal_property_set = (libolecf_internal_property_set_t *) property_set;

	if( libolecf_stream_seek_offset(
	     property_set_stream,
	     0,
	     SEEK_SET,
	     error ) == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_SEEK_FAILED,
		 "%s: unable to seek property set header offset: 0.",
		 function );

		goto on_error;
	}
	read_count = libolecf_stream_read_buffer(
	              property_set_stream,
	              (uint8_t *) &property_set_header,
	              sizeof( olecf_property_set_header_t ),
	              error );

	if( read_count != (ssize_t) sizeof( olecf_property_set_header_t ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read property set header.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: property set header:\n",
		 function );
		libcnotify_print_data(
		 (uint8_t *) &property_set_header,
		 sizeof( olecf_property_set_header_t ),
		 0 );
	}
#endif
	if( ( property_set_header.byte_order[ 0 ] == 0xfe )
	 && ( property_set_header.byte_order[ 1 ] == 0xff ) )
	{
		internal_property_set->byte_order = LIBOLECF_ENDIAN_LITTLE;
	}
	else if( ( property_set_header.byte_order[ 0 ] == 0xff )
	      && ( property_set_header.byte_order[ 1 ] == 0xfe ) )
	{
		internal_property_set->byte_order = LIBOLECF_ENDIAN_BIG;
	}
	else
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported byte order: 0x%02" PRIx8 " 0x%02" PRIx8 ".",
		 function,
		 property_set_header.byte_order[ 0 ],
		 property_set_header.byte_order[ 1 ] );

		goto on_error;
	}
	if( internal_property_set->byte_order == LIBOLECF_ENDIAN_LITTLE )
	{
		byte_stream_copy_to_uint16_little_endian(
		 property_set_header.format,
		 internal_property_set->format );

		byte_stream_copy_to_uint32_little_endian(
		 property_set_header.system_version,
		 internal_property_set->system_version );

		byte_stream_copy_to_uint16_little_endian(
		 property_set_header.number_of_sections,
		 number_of_sections );
	}
	else if( internal_property_set->byte_order == LIBOLECF_ENDIAN_BIG )
	{
		byte_stream_copy_to_uint16_big_endian(
		 property_set_header.format,
		 internal_property_set->format );

		byte_stream_copy_to_uint32_big_endian(
		 property_set_header.system_version,
		 internal_property_set->system_version );

		byte_stream_copy_to_uint16_big_endian(
		 property_set_header.number_of_sections,
		 number_of_sections );
	}
	if( memory_copy(
	     internal_property_set->class_identifier,
	     property_set_header.class_identifier,
	     16 ) == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
		 "%s: unable to copy class identifier.",
		 function );

		goto on_error;
	}
/* TODO make sure the class identifier is set in little endian */

#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: property set header byte order\t\t: 0x%02" PRIx8 " 0x%02" PRIx8 "\n",
		 function,
		 property_set_header.byte_order[ 0 ],
		 property_set_header.byte_order[ 1 ] );

		libcnotify_printf(
		 "%s: property set header format\t\t\t: %" PRIu16 "\n",
		 function,
		 internal_property_set->format );
		
		libcnotify_printf(
		 "%s: property set header system version\t\t: 0x%08" PRIx32 "\n",
		 function,
		 internal_property_set->system_version );

		if( libfguid_identifier_initialize(
		     &guid,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create GUID.",
			 function );

			goto on_error;
		}
		if( libfguid_identifier_copy_from_byte_stream(
		     guid,
		     internal_property_set->class_identifier,
		     16,
		     internal_property_set->byte_order,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
			 "%s: unable to copy byte stream to GUID.",
			 function );

			goto on_error;
		}
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
		result = libfguid_identifier_copy_to_utf16_string(
			  guid,
			  (uint16_t *) guid_string,
			  48,
			  LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
			  error );
#else
		result = libfguid_identifier_copy_to_utf8_string(
			  guid,
			  (uint8_t *) guid_string,
			  48,
			  LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
			  error );
#endif
		if( result != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
			 "%s: unable to copy GUID to string.",
			 function );

			goto on_error;
		}
		libcnotify_printf(
		 "%s: property set header class identifier\t: %" PRIs_LIBCSTRING_SYSTEM " (%s : %s)\n",
		 function,
		 guid_string,
		 libfwps_format_class_identifier_get_identifier(
		  internal_property_set->class_identifier ),
		 libfwps_format_class_identifier_get_description(
		  internal_property_set->class_identifier ) );

		if( libfguid_identifier_free(
		     &guid,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
			 "%s: unable to free GUID.",
			 function );

			goto on_error;
		}
		libcnotify_printf(
		 "%s: property set header number of sections\t: %" PRIu16 "\n",
		 function,
		 number_of_sections );

		libcnotify_printf(
		 "\n" );
	}
#endif
	section_list_entry_offset = sizeof( olecf_property_set_header_t );

	for( section_index = 0;
	     section_index < (int) number_of_sections;
	     section_index++ )
	{
		if( libolecf_property_section_initialize(
		     &property_section,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create property section: %d.",
			 function,
			 section_index );

			goto on_error;
		}
		if( libolecf_stream_seek_offset(
		     property_set_stream,
		     section_list_entry_offset,
		     SEEK_SET,
		     error ) == -1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_IO,
			 LIBCERROR_IO_ERROR_SEEK_FAILED,
			 "%s: unable to seek property section list entry: %d offset: %" PRIi64 ".",
			 function,
			 section_index,
			 section_list_entry_offset );

			goto on_error;
		}
		if( libolecf_property_section_read_list_entry(
		     (libolecf_internal_property_section_t *) property_section,
		     property_set_stream,
		     internal_property_set->byte_order,
		     &section_header_offset,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_IO,
			 LIBCERROR_IO_ERROR_READ_FAILED,
			 "%s: unable to read property section list entry: %d.",
			 function,
			 section_index );

			goto on_error;
		}
		if( libolecf_stream_get_offset(
		     property_set_stream,
		     &section_list_entry_offset,
		     error ) == -1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_IO,
			 LIBCERROR_IO_ERROR_SEEK_FAILED,
			 "%s: unable to retrieve property section list entry offset.",
			 function );

			goto on_error;
		}
		if( libolecf_property_section_read(
		     (libolecf_internal_property_section_t *) property_section,
		     io_handle,
		     property_set_stream,
		     section_header_offset,
		     internal_property_set->byte_order,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_IO,
			 LIBCERROR_IO_ERROR_READ_FAILED,
			 "%s: unable to read property section: %d at offset: %" PRIu32 ".",
			 function,
			 section_index,
			 section_header_offset );

			goto on_error;
		}
		if( libcdata_array_append_entry(
		     internal_property_set->sections,
		     &sections_entry,
		     (intptr_t *) property_section,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
			 "%s: unable to append property section: %d to sections array.",
			 function,
			 section_index );

			goto on_error;
		}
		property_section = NULL;
	}
	return( 1 );

on_error:
#if defined( HAVE_DEBUG_OUTPUT )
	if( guid != NULL )
	{
		libfguid_identifier_free(
		 &guid,
		 NULL );
	}
#endif
	if( property_section != NULL )
	{
		libolecf_property_section_free(
		 &property_section,
		 NULL );
	}
	return( -1 );
}
Beispiel #7
0
/* Reads the page tags
 * Returns 1 if successful or -1 on error
 */
int libesedb_page_read_tags(
     libcdata_array_t *page_tags_array,
     libesedb_io_handle_t *io_handle,
     uint16_t number_of_page_tags,
     uint8_t *page_data,
     size_t page_data_size,
     libcerror_error_t **error )
{
	libesedb_page_tags_value_t *page_tags_value = NULL;
	uint8_t *page_tags_data                     = NULL;
	static char *function                       = "libesedb_page_read_tags";
	uint16_t page_tag_offset                    = 0;
	uint16_t page_tag_size                      = 0;
	uint16_t page_tags_index                    = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	size_t page_tags_data_size                  = 0;
#endif

	if( page_tags_array == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid page tags array.",
		 function );

		return( -1 );
	}
	if( io_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid IO handle.",
		 function );

		return( -1 );
	}
	if( page_data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid page data.",
		 function );

		return( -1 );
	}
	if( page_data_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid page data size value exceeds maximum.",
		 function );

		return( -1 );
	}
	if( libcdata_array_resize(
	     page_tags_array,
	     number_of_page_tags,
	     (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_tags_value_free,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
		 "%s: unable to resize page tags array.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		page_tags_data_size = 4 * number_of_page_tags;

		libcnotify_printf(
		 "%s: page tags:\n",
		 function );
		libcnotify_print_data(
		 &( page_data[ page_data_size - page_tags_data_size ] ),
		 page_tags_data_size,
		 0 );
	}
#endif
	/* Read the page tags back to front
	 */
	page_tags_data = &( page_data[ page_data_size - 2 ] );

	for( page_tags_index = 0;
	     page_tags_index < number_of_page_tags;
	     page_tags_index++ )
	{
		if( libesedb_page_tags_value_initialize(
		     &page_tags_value,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create page tags value.",
			 function );

			goto on_error;
		}
		byte_stream_copy_to_uint16_little_endian(
		 page_tags_data,
		 page_tag_offset );

		page_tags_data -= 2;

		byte_stream_copy_to_uint16_little_endian(
		 page_tags_data,
		 page_tag_size );

		page_tags_data -= 2;

		if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
		 && ( io_handle->page_size >= 16384 ) )
		{
			page_tags_value->flags  = 0;
			page_tags_value->offset = page_tag_offset & 0x7fff;
			page_tags_value->size   = page_tag_size & 0x7fff;;
		}
		else
		{
			page_tags_value->flags  = page_tag_offset >> 13;
			page_tags_value->offset = page_tag_offset & 0x1fff;
			page_tags_value->size   = page_tag_size & 0x1fff;
		}
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: page tag: %03" PRIu16 " offset\t\t\t\t: %" PRIu16 " (0x%04" PRIx16 ")\n",
			 function,
			 page_tags_index,
			 page_tags_value->offset,
			 page_tag_offset );

			libcnotify_printf(
			 "%s: page tag: %03" PRIu16 " size\t\t\t\t: %" PRIu16 " (0x%04" PRIx16 ")\n",
			 function,
			 page_tags_index,
			 page_tags_value->size,
			 page_tag_size );

			if( ( io_handle->format_revision < LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
			 && ( io_handle->page_size < 16384 ) )
			{
				libcnotify_printf(
				 "%s: page tag: %03" PRIu16 " flags\t\t\t\t: 0x%02" PRIx8 "",
				 function,
				 page_tags_index,
				 page_tags_value->flags );
				libesedb_debug_print_page_tag_flags(
				 page_tags_value->flags );
				libcnotify_printf(
				 "\n" );
			}
		}
#endif
		if( libcdata_array_set_entry_by_index(
		     page_tags_array,
		     (int) page_tags_index,
		     (intptr_t *) page_tags_value,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
			 "%s: unable to set page tag: %" PRIu16 ".",
			 function,
			 page_tags_index );

			goto on_error;
		}
		page_tags_value = NULL;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "\n" );
	}
#endif
	return( 1 );

on_error:
	if( page_tags_value != NULL )
	{
		libesedb_page_tags_value_free(
		 &page_tags_value,
		 NULL );
	}
	return( -1 );
}
Beispiel #8
0
/* Calculates the SHA256 hash of an UTF-8 formatted password
 * Returns 1 if successful or -1 on error
 */
int libbde_utf8_password_calculate_hash(
     const uint8_t *utf8_string,
     size_t utf8_string_length,
     uint8_t *password_hash,
     size_t password_hash_size,
     libcerror_error_t **error )
{
	uint8_t *utf16_stream    = NULL;
	static char *function    = "libbde_utf8_password_calculate_hash";
	size_t utf16_stream_size = 0;

	if( password_hash == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid password hash.",
		 function );

		return( -1 );
	}
	if( password_hash_size != 32 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: password hash size value out of bounds.",
		 function );

		return( -1 );
	}
	if( libuna_utf16_stream_size_from_utf8(
	     utf8_string,
	     utf8_string_length,
	     &utf16_stream_size,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to determine UTF-16 stream size.",
		 function );

		goto on_error;
	}
	utf16_stream = (uint8_t *) memory_allocate(
	                            sizeof( uint8_t ) * utf16_stream_size );

	if( utf16_stream == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
		 "%s: unable to create UTF-16 stream.",
		 function );

		goto on_error;
	}
	if( libuna_utf16_stream_copy_from_utf8(
	     utf16_stream,
	     utf16_stream_size,
	     LIBUNA_ENDIAN_LITTLE,
	     utf8_string,
	     utf8_string_length,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
		 "%s: unable to copy UTF-8 string to UTF-16 stream size.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: password:\n",
			 function );
			libcnotify_print_data(
			 utf16_stream,
			 utf16_stream_size,
			 0 );
		}
#endif
	/* Ignore the byte-order mark in the UTF16 stream
	 */
	if( libhmac_sha256_calculate(
	     &( utf16_stream[ 2 ] ),
	     utf16_stream_size - 2,
	     password_hash,
	     password_hash_size,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
		 "%s: unable to calculate password hash.",
		 function );

		goto on_error;
	}
	if( libhmac_sha256_calculate(
	     password_hash,
	     password_hash_size,
	     password_hash,
	     password_hash_size,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
		 "%s: unable to calculate password hash.",
		 function );

		goto on_error;
	}
	if( memory_set(
	     utf16_stream,
	     0,
	     utf16_stream_size ) == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
		 "%s: unable to clear UTF-16 stream.",
		 function );

		goto on_error;
	}
	memory_free(
	 utf16_stream );

	return( 1 );

on_error:
	if( utf16_stream != NULL )
	{
		memory_set(
		 utf16_stream,
		 0,
		 utf16_stream_size );
		memory_free(
		 utf16_stream );
	}
	return( -1 );
}
Beispiel #9
0
int main( int argc, char * const argv[] )
#endif
{
	libcerror_error_t *error                 = NULL;
	libcfile_file_t *destination_file        = NULL;
	libcfile_file_t *source_file             = NULL;
	system_character_t *option_target_path   = NULL;
	system_character_t *options_string       = NULL;
	system_character_t *source               = NULL;
	uint8_t *buffer                          = NULL;
	uint8_t *uncompressed_data               = NULL;
	char *program                            = "lzxpressdecompress";
	system_integer_t option                  = 0;
	size64_t source_size                     = 0;
	size_t buffer_size                       = 0;
	size_t uncompressed_data_size            = 0;
	ssize_t read_count                       = 0;
	ssize_t write_count                      = 0;
	off_t source_offset                      = 0;
	int decompression_method                 = 1;
	int result                               = 0;
	int verbose                              = 0;

#if defined( WINAPI )
	void *workspace                          = NULL;
	unsigned short winapi_compression_method = 0;
#endif

	assorted_output_version_fprint(
	 stdout,
	 program );

#if defined( WINAPI )
	options_string = _SYSTEM_STRING( "d:ho:s:t:vV1234" );
#else
	options_string = _SYSTEM_STRING( "d:ho:s:t:vV12" );
#endif
	while( ( option = assorted_getopt(
	                   argc,
	                   argv,
	                   options_string ) ) != (system_integer_t) -1 )
	{
		switch( option )
		{
			case (system_integer_t) '?':
			default:
				fprintf(
				 stderr,
				 "Invalid argument: %" PRIs_SYSTEM "\n",
				 argv[ optind ] );

				usage_fprint(
				 stdout );

				return( EXIT_FAILURE );

			case (system_integer_t) '1':
				decompression_method = 1;

				break;

			case (system_integer_t) '2':
				decompression_method = 2;

				break;

#if defined( WINAPI )
			case (system_integer_t) '3':
				decompression_method = 3;

				break;

			case (system_integer_t) '4':
				decompression_method = 4;

				break;

#endif
			case (system_integer_t) 'd':
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
				uncompressed_data_size = _wtol( optarg );
#else
				uncompressed_data_size = atol( optarg );
#endif
				break;

			case (system_integer_t) 'h':
				usage_fprint(
				 stdout );

				return( EXIT_SUCCESS );

			case (system_integer_t) 'o':
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
				source_offset = _wtol( optarg );
#else
				source_offset = atol( optarg );
#endif
				break;

			case (system_integer_t) 's':
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
				source_size = _wtol( optarg );
#else
				source_size = atol( optarg );
#endif
				break;

			case (system_integer_t) 't':
				option_target_path = optarg;

				break;

			case (system_integer_t) 'v':
				verbose = 1;

				break;

			case (system_integer_t) 'V':
				assorted_output_copyright_fprint(
				 stdout );

				return( EXIT_SUCCESS );
		}
	}
	if( optind == argc )
	{
		fprintf(
		 stderr,
		 "Missing source file.\n" );

		usage_fprint(
		 stdout );

		return( EXIT_FAILURE );
	}
	source = argv[ optind ];

	libcnotify_stream_set(
	 stderr,
	 NULL );
	libcnotify_verbose_set(
	 verbose );

	/* Open the source file
	 */
	if( libcfile_file_initialize(
	     &source_file,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to create source file.\n" );

		goto on_error;
	}
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
	result = libcfile_file_open_wide(
	          source_file,
	          source,
	          LIBCFILE_OPEN_READ,
	          &error );
#else
	result = libcfile_file_open(
	          source_file,
	          source,
	          LIBCFILE_OPEN_READ,
	          &error );
#endif
 	if( result != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to open source file.\n" );

		goto on_error;
	}
	if( source_size == 0 )
	{
		if( libcfile_file_get_size(
		     source_file,
		     &source_size,
		     &error ) == -1 )
		{
			fprintf(
			 stderr,
			 "Unable to determine size of source file.\n" );

			goto on_error;
		}
		if( source_size <= (size64_t) source_offset )
		{
			fprintf(
			 stderr,
			 "Invalid source size value is less equal than source offset.\n" );

			goto on_error;
		}
		source_size -= source_offset;
	}
	if( source_size == 0 )
	{
		fprintf(
		 stderr,
		 "Invalid source size value is zero.\n" );

		goto on_error;
	}
	if( source_size > (size_t) SSIZE_MAX )
	{
		fprintf(
		 stderr,
		 "Invalid source size value exceeds maximum.\n" );

		goto on_error;
	}
	/* Create the input buffer
	 */
	buffer_size = source_size;

	buffer = (uint8_t *) memory_allocate(
	                      sizeof( uint8_t ) * buffer_size );

	if( buffer == NULL )
	{
		fprintf(
		 stderr,
		 "Unable to create buffer.\n" );

		goto on_error;
	}
	if( uncompressed_data_size == 0 )
	{
		uncompressed_data_size = 65536;
	}
	uncompressed_data = (uint8_t *) memory_allocate(
	                                 sizeof( uint8_t ) * uncompressed_data_size );

	if( uncompressed_data == NULL )
	{
		fprintf(
		 stderr,
		 "Unable to create uncompressed data buffer.\n" );

		goto on_error;
	}
	if( memory_set(
             uncompressed_data,
	     0,
	     uncompressed_data_size ) == NULL )
	{
		fprintf(
		 stderr,
		 "Unable to clear uncompressed data buffer.\n" );

		goto on_error;
	}
	/* Position the source file at the right offset
	 */
	if( libcfile_file_seek_offset(
	     source_file,
	     source_offset,
	     SEEK_SET,
	     &error ) == -1 )
	{
		fprintf(
		 stderr,
		 "Unable to seek offset in source file.\n" );

		goto on_error;
	}
	fprintf(
	 stdout,
	 "Starting LZXPRESS decompression of: %" PRIs_SYSTEM " at offset: %" PRIjd " (0x%08" PRIjx ").\n",
	 source,
	 source_offset,
	 source_offset );

	read_count = libcfile_file_read_buffer(
		      source_file,
		      buffer,
		      source_size,
	              &error );

	if( read_count != (ssize_t) source_size )
	{
		fprintf(
		 stderr,
		 "Unable to read from source file.\n" );

		goto on_error;
	}
	/* Decompress the data
	 */
	if( option_target_path == NULL )
	{
		fprintf(
		 stderr,
		 "Compressed data:\n" );

		libcnotify_print_data(
		 buffer,
		 source_size,
		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
	}
	if( decompression_method == 1 )
	{
		result = libfwnt_lzxpress_decompress(
		          buffer,
		          (size_t) source_size,
		          uncompressed_data,
		          &uncompressed_data_size,
		          &error );
	}
	else if( decompression_method == 2 )
	{
		result = libfwnt_lzxpress_huffman_decompress(
		          buffer,
		          (size_t) source_size,
		          uncompressed_data,
		          &uncompressed_data_size,
		          &error );
	}
#if defined( WINAPI )
	else if( ( decompression_method == 3 )
	      || ( decompression_method == 4 ) )
	{
		if( decompression_method == 3 )
		{
			winapi_compression_method = COMPRESSION_FORMAT_XPRESS;
		}
		else if( decompression_method == 4 )
		{
			winapi_compression_method = COMPRESSION_FORMAT_XPRESS_HUFF;
		}
/* TODO: determine workspace size: RtlGetCompressionWorkSpaceSize */
		workspace = (void *) memory_allocate(
		                      16 * 1024 * 1024 );

		if( workspace == NULL )
		{
			fprintf(
			 stderr,
			 "Unable to create workspace.\n" );

			goto on_error;
		}
		result = lzxpresscompress_RtlDecompressBufferEx(
		          winapi_compression_method,
		          (unsigned char *) uncompressed_data,
		          (unsigned long) uncompressed_data_size,
		          (unsigned char *) buffer,
		          (unsigned long) source_size,
		          (unsigned long *) &uncompressed_data_size,
		          workspace );

		memory_free(
		 workspace );

		if( result != 0 )
		{
			result = -1;
		}
		else
		{
			result = 1;
		}
	}
#endif
	if( result == -1 )
	{
		fprintf(
		 stderr,
		 "Unable to decompress data.\n" );

		libcnotify_print_data(
		 uncompressed_data,
		 uncompressed_data_size,
		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );

		goto on_error;
	}
	if( option_target_path == NULL )
	{
		fprintf(
		 stderr,
		 "Uncompressed data:\n" );

		libcnotify_print_data(
		 uncompressed_data,
		 uncompressed_data_size,
		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
	}
	else
	{
		if( libcfile_file_initialize(
		     &destination_file,
		     &error ) != 1 )
		{
			fprintf(
			 stderr,
			 "Unable to create destination file.\n" );

			goto on_error;
		}
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
		result = libcfile_file_open_wide(
		          destination_file,
		          option_target_path,
		          LIBCFILE_OPEN_WRITE,
		          &error );
#else
		result = libcfile_file_open(
		          destination_file,
		          option_target_path,
		          LIBCFILE_OPEN_WRITE,
		          &error );
#endif
	 	if( result != 1 )
		{
			fprintf(
			 stderr,
			 "Unable to open destination file.\n" );

			goto on_error;
		}
		write_count = libcfile_file_write_buffer(
			       destination_file,
			       uncompressed_data,
			       uncompressed_data_size,
			       &error );

		if( write_count != (ssize_t) uncompressed_data_size )
		{
			fprintf(
			 stderr,
			 "Unable to write to destination file.\n" );

			goto on_error;
		}
		if( libcfile_file_close(
		     destination_file,
		     &error ) != 0 )
		{
			fprintf(
			 stderr,
			 "Unable to close destination file.\n" );

			goto on_error;
		}
		if( libcfile_file_free(
		     &destination_file,
		     &error ) != 1 )
		{
			fprintf(
			 stderr,
			 "Unable to free destination file.\n" );

			goto on_error;
		}
	}
	/* Clean up
	 */
	if( libcfile_file_close(
	     source_file,
	     &error ) != 0 )
	{
		fprintf(
		 stderr,
		 "Unable to close source file.\n" );

		goto on_error;
	}
	if( libcfile_file_free(
	     &source_file,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to free source file.\n" );

		goto on_error;
	}
	memory_free(
	 uncompressed_data );

	uncompressed_data = NULL;

	memory_free(
	 buffer );

	buffer = NULL;

	fprintf(
	 stdout,
	 "LZXPRESS decompression:\tSUCCESS\n" );

	return( EXIT_SUCCESS );

on_error:
	if( error != NULL )
	{
		libcnotify_print_error_backtrace(
		 error );
		libcerror_error_free(
		 &error );
	}
	if( destination_file != NULL )
	{
		libcfile_file_free(
		 &destination_file,
		 NULL );
	}
	if( uncompressed_data != NULL )
	{
		memory_free(
		 uncompressed_data );
	}
	if( buffer != NULL )
	{
		memory_free(
		 buffer );
	}
	if( source_file != NULL )
	{
		libcfile_file_free(
		 &source_file,
		 NULL );
	}
	fprintf(
	 stdout,
	 "LZXPRESS decompression:\tFAILURE\n" );

	return( EXIT_FAILURE );
}
/* Reads cluster block
 * Returns 1 if successful or -1 on error
 */
int libqcow_cluster_block_read(
     libqcow_cluster_block_t *cluster_block,
     libbfio_handle_t *file_io_handle,
     off64_t cluster_block_offset,
     libcerror_error_t **error )
{
	static char *function = "libqcow_cluster_block_read";
	ssize_t read_count    = 0;

	if( cluster_block == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid cluster block.",
		 function );

		return( -1 );
	}
	if( cluster_block->data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: invalid cluster block - missing data.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: reading cluster block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
		 function,
		 cluster_block_offset,
		 cluster_block_offset );
	}
#endif
	if( libbfio_handle_seek_offset(
	     file_io_handle,
	     cluster_block_offset,
	     SEEK_SET,
	     error ) == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_SEEK_FAILED,
		 "%s: unable to seek cluster block offset: %" PRIi64 " (0x%08" PRIx64 ").",
		 function,
		 cluster_block_offset,
		 cluster_block_offset );

		return( -1 );
	}
	read_count = libbfio_handle_read_buffer(
		      file_io_handle,
		      cluster_block->data,
		      cluster_block->data_size,
		      error );

	if( read_count != (ssize_t) cluster_block->data_size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read cluster block.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: cluster block:\n",
		 function );
		libcnotify_print_data(
		 cluster_block->data,
		 cluster_block->data_size,
		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
	}
#endif
	return( 1 );
}
/* Reads a data block strings
 * Returns the number of bytes read if successful or -1 on error
 */
int liblnk_data_block_strings_read(
     liblnk_data_string_t *data_string,
     liblnk_data_block_t *data_block,
     liblnk_io_handle_t *io_handle,
     libcerror_error_t **error )
{
	lnk_data_block_strings_t *data_block_strings_data = NULL;
	static char *function                             = "liblnk_data_block_strings_read";
	size_t string_size                                = 0;
	size_t unicode_string_size                        = 0;

	if( data_string == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid data string.",
		 function );

		return( -1 );
	}
	if( data_string->data != NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
		 "%s: invalid data string - data already set.",
		 function );

		return( -1 );
	}
	if( data_block == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid data block.",
		 function );

		return( -1 );
	}
	if( data_block->data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: invalid data block - missing data.",
		 function );

		return( -1 );
	}
	if( data_block->data_size < sizeof( lnk_data_block_strings_t ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: invalid data block - data size too small.",
		 function );

		return( -1 );
	}
	data_block_strings_data = (lnk_data_block_strings_t *) data_block->data;

	if( io_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid IO handle.",
		 function );

		return( -1 );
	}
	for( string_size = 0;
	     string_size < 260;
	     string_size++ )
	{
		if( data_block_strings_data->string[ string_size ] == 0 )
		{
			break;
		}
	}
	if( ( string_size == 260 )
	 || ( data_block_strings_data->string[ string_size ] != 0 ) )
	{
#if defined( HAVE_VERBOSE_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: unsupported data block strings\n" );
		}
#endif
		string_size = 0;
	}
	else
	{
		string_size += 1;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: string data:\n",
		 function );
		libcnotify_print_data(
		 data_block_strings_data->string,
		 260,
		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );

		if( liblnk_debug_print_string_value(
		     function,
		     "string\t\t\t\t\t",
		     data_block_strings_data->string,
		     260,
		     io_handle->ascii_codepage,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
			 "%s: unable to print string value.",
			 function );

			goto on_error;
		}
	}
#endif
	for( unicode_string_size = 0;
	     unicode_string_size < 520;
	     unicode_string_size += 2 )
	{
		if( ( data_block_strings_data->unicode_string[ unicode_string_size ] == 0 )
		 && ( data_block_strings_data->unicode_string[ unicode_string_size + 1 ] == 0 ) )
		{
			break;
		}
	}
	if( ( unicode_string_size == 520 )
	 || ( data_block_strings_data->unicode_string[ unicode_string_size ] != 0 )
	 || ( data_block_strings_data->unicode_string[ unicode_string_size + 1 ] != 0 ) )
	{
#if defined( HAVE_VERBOSE_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: unsupported unicode string\n" );
		}
#endif
		unicode_string_size = 0;
	}
	else
	{
		unicode_string_size += 2;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: unicode string data:\n",
		 function );
		libcnotify_print_data(
		 data_block_strings_data->unicode_string,
		 520,
		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );

		if( liblnk_debug_print_utf16_string_value(
		     function,
		     "unicode string\t\t\t\t",
		     data_block_strings_data->unicode_string,
		     520,
		     LIBUNA_ENDIAN_LITTLE,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
			 "%s: unable to print UTF-16 string value.",
			 function );

			goto on_error;
		}
		libcnotify_printf(
		 "\n" );
	}
#endif
	if( unicode_string_size > 0 )
	{
		data_string->data_size = unicode_string_size;

		data_string->data = (uint8_t *) memory_allocate(
		                                 sizeof( uint8_t ) * data_string->data_size );

		if( data_string->data == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_MEMORY,
			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
			 "%s: unable to create data string data.",
			 function );

			goto on_error;
		}
		if( memory_copy(
		     data_string->data,
		     data_block_strings_data->unicode_string,
		     data_string->data_size ) == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_MEMORY,
			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
			 "%s: unable to copy unicode string data.",
			 function );

			goto on_error;
		}
		data_string->is_unicode = 1;
	}
	else if( string_size > 0 )
	{
		data_string->data_size = string_size;

		data_string->data = (uint8_t *) memory_allocate(
		                                 sizeof( uint8_t ) * data_string->data_size );

		if( data_string->data == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_MEMORY,
			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
			 "%s: unable to create data string data.",
			 function );

			goto on_error;
		}
		if( memory_copy(
		     data_string->data,
		     data_block_strings_data->string,
		     data_string->data_size ) == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_MEMORY,
			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
			 "%s: unable to copy string data.",
			 function );

			goto on_error;
		}
		data_string->is_unicode = 0;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		if( data_block->data_size > sizeof( lnk_data_block_strings_t ) )
		{
			libcnotify_printf(
			 "%s: trailing data:\n",
			 function );
			libcnotify_print_data(
			 &( data_block->data[ sizeof( lnk_data_block_strings_t ) ] ),
			 data_block->data_size - sizeof( lnk_data_block_strings_t ),
			 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
		}
	}
#endif
	return( 1 );

on_error:
	if( data_string->data != NULL )
	{
		memory_free(
		 data_string->data );

		data_string->data = NULL;
	}
	data_string->data_size = 0;

	return( -1 );
}
/* Reads the metadata area
 * Returns 1 if successful or -1 on error
 */
int libvslvm_metadata_area_read(
     libvslvm_metadata_area_t *metadata_area,
     libbfio_handle_t *file_io_handle,
     off64_t file_offset,
     libcerror_error_t **error )
{
	vslvm_raw_location_descriptor_t raw_location_descriptor_data;
	vslvm_metadata_area_header_t metadata_area_header;

	libvslvm_raw_location_descriptor_t *raw_location_descriptor = NULL;
	static char *function                                       = "libvslvm_metadata_area_read";
	ssize_t read_count                                          = 0;
	uint64_t offset                                             = 0;
	uint64_t size                                               = 0;
	uint32_t checksum                                           = 0;
	uint32_t flags                                              = 0;
	int entry_index                                             = 0;
	int result                                                  = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	uint64_t value_64bit                                        = 0;
	uint32_t value_32bit                                        = 0;
#endif

	if( metadata_area == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid metadata area.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: reading metadata area at offset: %" PRIi64 "\n",
		 function,
		 file_offset );
	}
#endif
	if( libbfio_handle_seek_offset(
	     file_io_handle,
	     file_offset,
	     SEEK_SET,
	     error ) == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_SEEK_FAILED,
		 "%s: unable to seek offset: %" PRIi64 " (0x%08" PRIx64 ").",
		 function,
		 file_offset,
		 file_offset );

		goto on_error;
	}
	read_count = libbfio_handle_read_buffer(
	              file_io_handle,
	              (uint8_t *) &metadata_area_header,
	              sizeof( vslvm_metadata_area_header_t ),
	              error );

	if( read_count != (ssize_t) sizeof( vslvm_metadata_area_header_t ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read metadata area header.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: metadata area header data:\n",
		 function );
		libcnotify_print_data(
		 (uint8_t *) &metadata_area_header,
		 sizeof( vslvm_metadata_area_header_t ),
		 0 );
	}
#endif
	if( memory_compare(
	     metadata_area_header.signature,
	     vslvm_metadata_area_signature,
	     8 ) != 0 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported metadata area signature.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		byte_stream_copy_to_uint32_little_endian(
		 metadata_area_header.checksum,
		 value_32bit );
		libcnotify_printf(
		 "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 value_32bit );

		libcnotify_printf(
		 "%s: signature\t\t\t\t\t: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
		 function,
		 metadata_area_header.signature[ 0 ],
		 metadata_area_header.signature[ 1 ],
		 metadata_area_header.signature[ 2 ],
		 metadata_area_header.signature[ 3 ],
		 metadata_area_header.signature[ 4 ],
		 metadata_area_header.signature[ 5 ],
		 metadata_area_header.signature[ 6 ],
		 metadata_area_header.signature[ 7 ],
		 metadata_area_header.signature[ 8 ],
		 metadata_area_header.signature[ 9 ],
		 metadata_area_header.signature[ 10 ],
		 metadata_area_header.signature[ 11 ],
		 metadata_area_header.signature[ 12 ],
		 metadata_area_header.signature[ 13 ],
		 metadata_area_header.signature[ 14 ],
		 metadata_area_header.signature[ 15 ] );

		byte_stream_copy_to_uint32_little_endian(
		 metadata_area_header.version,
		 value_32bit );
		libcnotify_printf(
		 "%s: version\t\t\t\t\t: %" PRIu32 "\n",
		 function,
		 value_32bit );

		byte_stream_copy_to_uint64_little_endian(
		 metadata_area_header.data_offset,
		 value_64bit );
		libcnotify_printf(
		 "%s: data offset\t\t\t\t: 0x%08" PRIx64 "\n",
		 function,
		 value_64bit );

		byte_stream_copy_to_uint64_little_endian(
		 metadata_area_header.data_size,
		 value_64bit );
		libcnotify_printf(
		 "%s: data size\t\t\t\t\t: %" PRIu64 "\n",
		 function,
		 value_64bit );

		libcnotify_printf(
		 "\n" );
	}
#endif
/* TODO calculate checksum */

	do
	{
		read_count = libbfio_handle_read_buffer(
		              file_io_handle,
		              (uint8_t *) &raw_location_descriptor_data,
		              sizeof( vslvm_raw_location_descriptor_t ),
		              error );

		if( read_count != (ssize_t) sizeof( vslvm_raw_location_descriptor_t ) )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_IO,
			 LIBCERROR_IO_ERROR_READ_FAILED,
			 "%s: unable to read raw location descriptor.",
			 function );

			goto on_error;
		}
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: raw location descriptor data:\n",
			 function );
			libcnotify_print_data(
			 (uint8_t *) &raw_location_descriptor_data,
			 sizeof( vslvm_raw_location_descriptor_t ),
			 0 );
		}
#endif
		result = memory_compare(
		          (uint8_t *) &raw_location_descriptor_data,
		          vslvm_empty_raw_location_descriptor,
		          sizeof( vslvm_raw_location_descriptor_t ) );

		if( result != 0 )
		{
			byte_stream_copy_to_uint64_little_endian(
			 raw_location_descriptor_data.offset,
			 offset );

			byte_stream_copy_to_uint64_little_endian(
			 raw_location_descriptor_data.size,
			 size );

			byte_stream_copy_to_uint32_little_endian(
			 raw_location_descriptor_data.checksum,
			 checksum );

			byte_stream_copy_to_uint32_little_endian(
			 raw_location_descriptor_data.flags,
			 flags );

#if defined( HAVE_DEBUG_OUTPUT )
			if( libcnotify_verbose != 0 )
			{
				libcnotify_printf(
				 "%s: offset\t\t\t\t\t: 0x%08" PRIx64 "\n",
				 function,
				 offset );

				libcnotify_printf(
				 "%s: size\t\t\t\t\t: %" PRIu64 "\n",
				 function,
				 size );

				libcnotify_printf(
				 "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
				 function,
				 checksum );

				libcnotify_printf(
				 "%s: flags\t\t\t\t\t: 0x%08" PRIx32 "\n",
				 function,
				 flags );

				libcnotify_printf(
				 "\n" );
			}
#endif
			if( ( flags & LIBVSLVM_RAW_LOCATION_DESCRIPTOR_FLAG_IGNORE ) == 0 )
			{
				if( libvslvm_raw_location_descriptor_initialize(
				     &raw_location_descriptor,
				     error ) != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
					 "%s: unable to create raw location descriptor.",
					 function );

					goto on_error;
				}
				if( libvslvm_raw_location_descriptor_set(
				     raw_location_descriptor,
				     (off64_t) ( file_offset + offset ),
				     (size64_t) size,
				     checksum,
				     flags,
				     error ) != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
					 "%s: unable to set raw location descriptor.",
					 function );

					goto on_error;
				}
				if( libcdata_array_append_entry(
				     metadata_area->raw_location_descriptors_array,
				     &entry_index,
				     (intptr_t *) raw_location_descriptor,
				     error ) != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
					 "%s: unable to append entry to raw location descriptors array.",
					 function );

					goto on_error;
				}
				raw_location_descriptor = NULL;
			}
		}
	}
	while( result != 0 );

	return( 1 );

on_error:
	if( raw_location_descriptor != NULL )
	{
		libvslvm_raw_location_descriptor_free(
		 &raw_location_descriptor,
		 NULL );
	}
	libcdata_array_empty(
	 metadata_area->raw_location_descriptors_array,
	 (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_raw_location_descriptor_free,
	 NULL );

	return( -1 );
}
/* Reads key hierarchy entry data
 * Returns 1 if successful or -1 on error
 */
int libcreg_key_hierarchy_entry_read_data(
     libcreg_key_hierarchy_entry_t *key_hierarchy_entry,
     const uint8_t *data,
     size_t data_size,
     size_t data_offset LIBCREG_ATTRIBUTE_UNUSED,
     libcerror_error_t **error )
{
	static char *function = "libcreg_key_hierarchy_entry_read_data";

#if defined( HAVE_DEBUG_OUTPUT )
	uint32_t value_32bit  = 0;
#else
	LIBCREG_UNREFERENCED_PARAMETER( data_offset );
#endif

	if( key_hierarchy_entry == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid key hierarchy entry.",
		 function );

		return( -1 );
	}
	if( data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid data.",
		 function );

		return( -1 );
	}
	if( data_size < sizeof( creg_key_hierarchy_entry_t ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
		 "%s: invalid data size value too small.",
		 function );

		return( -1 );
	}
	if( data_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid data size value exceeds maximum.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: key hierarchy entry:\n",
		 function );
		libcnotify_print_data(
		 data,
		 sizeof( creg_key_hierarchy_entry_t ),
		 0 );
	}
#endif
	byte_stream_copy_to_uint32_little_endian(
	 ( (creg_key_hierarchy_entry_t *) data )->name_hash,
	 key_hierarchy_entry->name_hash );

	byte_stream_copy_to_uint32_little_endian(
	 ( (creg_key_hierarchy_entry_t *) data )->parent_key_offset,
	 key_hierarchy_entry->parent_key_offset );

	byte_stream_copy_to_uint32_little_endian(
	 ( (creg_key_hierarchy_entry_t *) data )->sub_key_offset,
	 key_hierarchy_entry->sub_key_offset );

	byte_stream_copy_to_uint32_little_endian(
	 ( (creg_key_hierarchy_entry_t *) data )->next_key_offset,
	 key_hierarchy_entry->next_key_offset );

	byte_stream_copy_to_uint16_little_endian(
	 ( (creg_key_hierarchy_entry_t *) data )->key_name_entry_number,
	 key_hierarchy_entry->key_name_entry_number );

	byte_stream_copy_to_uint16_little_endian(
	 ( (creg_key_hierarchy_entry_t *) data )->data_block_number,
	 key_hierarchy_entry->data_block_number );

#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: offset\t\t\t\t: 0x%08" PRIzx "\n",
		 function,
		 data_offset );

		byte_stream_copy_to_uint32_little_endian(
		 ( (creg_key_hierarchy_entry_t *) data )->unknown1,
		 value_32bit );
		libcnotify_printf(
		 "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 value_32bit );

		libcnotify_printf(
		 "%s: name hash\t\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 key_hierarchy_entry->name_hash );

		byte_stream_copy_to_uint32_little_endian(
		 ( (creg_key_hierarchy_entry_t *) data )->unknown2,
		 value_32bit );
		libcnotify_printf(
		 "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 value_32bit );

		libcnotify_printf(
		 "%s: parent key offset\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 key_hierarchy_entry->parent_key_offset );

		libcnotify_printf(
		 "%s: sub key offset\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 key_hierarchy_entry->sub_key_offset );

		libcnotify_printf(
		 "%s: next key offset\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 key_hierarchy_entry->next_key_offset );

		libcnotify_printf(
		 "%s: key name entry number\t\t\t: %" PRIi16 "\n",
		 function,
		 (int16_t) key_hierarchy_entry->key_name_entry_number );

		libcnotify_printf(
		 "%s: data block number\t\t\t: %" PRIi16 "\n",
		 function,
		 (int16_t) key_hierarchy_entry->data_block_number );

		libcnotify_printf(
		 "\n" );
	}
#endif
	return( 1 );
}
Beispiel #14
0
/* Copies the sector data to the buffer
 * Returns the number of bytes copied if successful or -1 on error
 */
ssize_t libodraw_io_handle_copy_sector_data_to_buffer(
         libodraw_io_handle_t *io_handle,
         const uint8_t *sector_data,
         size_t sector_data_size,
         uint32_t bytes_per_sector,
         uint8_t track_type,
         uint8_t *buffer,
         size_t buffer_size,
         uint32_t sector_index,
         uint32_t sector_offset,
         libcerror_error_t **error )
{
	static char *function     = "libodraw_io_handle_copy_sector_data_to_buffer";
	size_t buffer_offset      = 0;
	size_t read_size          = 0;
	size_t sector_data_offset = 0;
	uint32_t sector_lba       = 0;

#if defined( HAVE_DEBUG_OUTPUT ) || defined( HAVE_VERBOSE_OUTPUT )
	uint8_t sector_mode       = 0;
#endif

	if( io_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid IO handle.",
		 function );

		return( -1 );
	}
	if( sector_data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid sector data.",
		 function );

		return( -1 );
	}
	if( sector_data_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid sector data size value exceeds maximum.",
		 function );

		return( -1 );
	}
	if( buffer == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid buffer.",
		 function );

		return( -1 );
	}
	if( buffer_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid buffer size value exceeds maximum.",
		 function );

		return( -1 );
	}
	if( ( (size_t) sector_offset >= sector_data_size )
	 || ( sector_offset >= io_handle->bytes_per_sector ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: invalid sector offset value out of bounds.",
		 function );

		return( -1 );
	}
	while( sector_data_offset < sector_data_size )
	{
		if( io_handle->bytes_per_sector == 2048 )
		{
			if( ( track_type == LIBODRAW_TRACK_TYPE_MODE1_2352 )
			 || ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) )
			{
				if( ( sector_data_offset + 16 ) >= sector_data_size )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
					 "%s: sector data too small.",
					 function );

					return( -1 );
				}
#if defined( HAVE_DEBUG_OUTPUT )
				if( libcnotify_verbose != 0 )
				{
					libcnotify_printf(
				 	 "%s: sector: %" PRIu32 " header:\n",
					 function,
					 sector_index );
					libcnotify_print_data(
					 &( sector_data[ sector_data_offset ] ),
					 16,
					 0 );
				}
#endif
				if( memory_compare(
				     &( sector_data[ sector_data_offset ] ),
				     libodraw_sector_synchronisation_data,
				     12 ) != 0 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_INPUT,
					 LIBCERROR_INPUT_ERROR_VALUE_MISMATCH,
					 "%s: unsupported sector synchronisation data.",
					 function );

					return( -1 );
				}
#if defined( HAVE_DEBUG_OUTPUT )
				if( libcnotify_verbose != 0 )
				{
					libcnotify_printf(
				 	 "%s: sector: %" PRIu32 " synchronisation data:\n",
					 function,
					 sector_index );
					libcnotify_print_data(
					 &( sector_data[ sector_data_offset ] ),
					 12,
					 0 );
				}
#endif
				sector_data_offset += 12;

				libodraw_optical_disk_copy_msf_to_lba(
				 sector_data[ sector_data_offset ],
				 sector_data[ sector_data_offset + 1 ],
				 sector_data[ sector_data_offset + 2 ],
				 sector_lba );

#if defined( HAVE_DEBUG_OUTPUT ) || defined( HAVE_VERBOSE_OUTPUT )
				sector_mode = sector_data[ sector_data_offset + 3 ] & 0x03;
#endif

#if defined( HAVE_DEBUG_OUTPUT )
				if( libcnotify_verbose != 0 )
				{
					libcnotify_printf(
				 	 "%s: sector: %" PRIu32 " MSF\t\t: %02" PRIu8 ":%02" PRIu8 ":%02" PRIu8 " (%" PRIu32 ")\n",
					 function,
					 sector_index,
					 sector_data[ sector_data_offset ],
					 sector_data[ sector_data_offset + 1 ],
					 sector_data[ sector_data_offset + 2 ],
					 sector_lba );

					libcnotify_printf(
				 	 "%s: sector: %" PRIu32 " mode bits\t: 0x%02" PRIx8 "\n",
					 function,
					 sector_index,
					 sector_data[ sector_data_offset + 3 ] );
				}
#endif
#if defined( HAVE_VERBOSE_OUTPUT )
				if( sector_lba != sector_index )
				{
					libcnotify_printf(
					 "%s: sector MSF (LBA) does not match current.\n",
					 function );
				}
				if( ( ( track_type == LIBODRAW_TRACK_TYPE_MODE1_2352 )
				  &&  ( sector_mode != 1 ) )
				 || ( ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 )
				  &&  ( sector_mode != 2 ) ) )
				{
					libcnotify_printf(
					 "%s: sector mode does not match table of contents.\n",
					 function );
				}
#endif
				sector_data_offset += 4;
			}
			else if( bytes_per_sector == 2352 )
			{
				sector_data_offset += 16;
			}
			if( ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2336 )
			 || ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) )
			{
				if( ( sector_data[ sector_data_offset     ] != sector_data[ sector_data_offset + 4 ] )
				 || ( sector_data[ sector_data_offset + 1 ] != sector_data[ sector_data_offset + 5 ] )
				 || ( sector_data[ sector_data_offset + 2 ] != sector_data[ sector_data_offset + 6 ] )
				 || ( sector_data[ sector_data_offset + 3 ] != sector_data[ sector_data_offset + 7 ] ) )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_INPUT,
					 LIBCERROR_INPUT_ERROR_VALUE_MISMATCH,
					 "%s: unsupported or corrupt XA sub-header.",
					 function );

					return( -1 );
				}
				if( sector_data[ sector_data_offset + 1 ] >= 32 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_INPUT,
					 LIBCERROR_INPUT_ERROR_VALUE_MISMATCH,
					 "%s: unsupported XA sub-header channel number.",
					 function );

					return( -1 );
				}
#if defined( HAVE_VERBOSE_OUTPUT )
				if( libcnotify_verbose != 0 )
				{
					if( ( sector_data[ sector_data_offset + 2 ] & 0x08 ) != 0 )
					{
						libcnotify_printf(
						 "%s: data flag not set in XA sub-header sub-mode flags.\n",
						 function );
					}
				}
#endif

/* TODO some writers seem to ignore these flags
				if( ( sector_data[ sector_data_offset + 2 ] & 0x08 ) != 0 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_INPUT,
					 LIBCERROR_INPUT_ERROR_VALUE_MISMATCH,
					 "%s: unsupported XA sub-header sub-mode flags - data flag not set.",
					 function );

					return( -1 );
				}
*/
				sector_data_offset += 8;
			}
		}
		else if( io_handle->bytes_per_sector == 2352 )
		{
			if( sector_offset == 0 )
			{
/* TODO what about run-out and lead-out data (have argument indicate non-track data) */
				if( ( io_handle->mode == 1 )
				 || ( io_handle->mode == 2 ) )
				{
					read_size = 12;

					if( ( read_size + buffer_offset ) > buffer_size )
					{
						read_size = buffer_size - buffer_offset;
					}
					if( memory_copy(
					     &( buffer[ buffer_offset ] ),
					     libodraw_sector_synchronisation_data,
					     read_size ) != 0 )
					{
						libcerror_error_set(
						 error,
						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
						 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
						 "%s: unsupported copy sector synchronisation data to buffer.",
						 function );

						return( -1 );
					}
					buffer_offset += read_size;

					if( buffer_offset >= buffer_size )
					{
						break;
					}
/* TODO set MSF requires current sector */
					buffer[ buffer_offset++ ] = 0;

					if( buffer_offset >= buffer_size )
					{
						break;
					}
					buffer[ buffer_offset++ ] = 0;

					if( buffer_offset >= buffer_size )
					{
						break;
					}
					buffer[ buffer_offset++ ] = 0;

					if( buffer_offset >= buffer_size )
					{
						break;
					}
					if( io_handle->mode == 1 )
					{
						buffer[ buffer_offset++ ] = 1;
					}
					else if ( io_handle->mode == 2 )
					{
						buffer[ buffer_offset++ ] = 2;
					}
					if( buffer_offset >= buffer_size )
					{
						break;
					}
				}
				else
				{
					read_size = 16;

					if( ( read_size + buffer_offset ) > buffer_size )
					{
						read_size = buffer_size - buffer_offset;
					}
					if( memory_set(
					     &( buffer[ buffer_offset ] ),
					     0,
					     read_size ) == NULL )
					{
						libcerror_error_set(
						 error,
						 LIBCERROR_ERROR_DOMAIN_MEMORY,
						 LIBCERROR_MEMORY_ERROR_SET_FAILED,
						 "%s: unable to set sector data in buffer.",
						 function );

						return( -1 );
					}
					buffer_offset += read_size;

					if( buffer_offset >= buffer_size )
					{
						break;
					}
				}
				if( io_handle->mode == 2 )
				{
/* TODO what about XA sub-header */
				}
			}
		}
		read_size = io_handle->bytes_per_sector;

		if( sector_offset != 0 )
		{
			sector_data_offset += sector_offset;
			read_size          -= (size_t) sector_offset;
			sector_offset       = 0;
		}
		if( ( read_size + buffer_offset ) > buffer_size )
		{
			read_size = buffer_size - buffer_offset;
		}
		if( ( track_type == LIBODRAW_TRACK_TYPE_AUDIO )
		 && ( io_handle->bytes_per_sector != 2352 ) )
		{
			/* If the sector size is not 2352 just return 0 bytes
			 * for audio data
			 */
			if( memory_set(
			     &( buffer[ buffer_offset ] ),
			     0,
			     read_size ) == NULL )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_MEMORY,
				 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
				 "%s: unable to set sector data to buffer.",
				 function );

				return( -1 );
			}
		}
		else
		{
			if( memory_copy(
			     &( buffer[ buffer_offset ] ),
			     &( sector_data[ sector_data_offset ] ),
			     read_size ) == NULL )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_MEMORY,
				 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
				 "%s: unable to copy sector data to buffer.",
				 function );

				return( -1 );
			}
		}
		buffer_offset      += read_size;
		sector_data_offset += read_size;

		if( buffer_offset >= buffer_size )
		{
			break;
		}
		if( io_handle->bytes_per_sector == 2048 )
		{
			if( track_type == LIBODRAW_TRACK_TYPE_MODE1_2352 )
			{
/* TODO calculate checksum, what about read errors ?*/
				sector_data_offset += 4;

/* TODO check padding */
				sector_data_offset += 8;

/* TODO check ECC data if necessary, what about read errors ? */
				sector_data_offset += 276;
			}
			else if( ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2336 )
			      || ( track_type == LIBODRAW_TRACK_TYPE_MODE2_2352 ) )
			{
/* TODO calculate checksum, what about read errors ?*/
				sector_data_offset += 4;

/* TODO check ECC data if necessary, what about read errors ? */
				sector_data_offset += 276;
			}
			else if( bytes_per_sector == 2352 )
			{
				sector_data_offset += 288;
			}
		}
		else if( io_handle->bytes_per_sector == 2352 )
		{
/* TODO what about run-out and lead-out data (have argument indicate non-track data) */
			if( ( io_handle->mode == 1 )
			 || ( io_handle->mode == 2 ) )
			{
				read_size = 4;

				if( ( read_size + buffer_offset ) > buffer_size )
				{
					read_size = buffer_size - buffer_offset;
				}
/* TODO determine missing data instead of 0 fill */
				if( memory_set(
				     &( buffer[ buffer_offset ] ),
				     0,
				     read_size ) == NULL )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_MEMORY,
					 LIBCERROR_MEMORY_ERROR_SET_FAILED,
					 "%s: unable to set sector checksum in buffer.",
					 function );

					return( -1 );
				}
				buffer_offset += read_size;

				if( buffer_offset >= buffer_size )
				{
					break;
				}
			}
			if( io_handle->mode == 1 )
			{
				read_size = 8;

				if( ( read_size + buffer_offset ) > buffer_size )
				{
					read_size = buffer_size - buffer_offset;
				}
				if( memory_set(
				     &( buffer[ buffer_offset ] ),
				     0,
				     read_size ) == NULL )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_MEMORY,
					 LIBCERROR_MEMORY_ERROR_SET_FAILED,
					 "%s: unable to set sector reserved in buffer.",
					 function );

					return( -1 );
				}
				buffer_offset += read_size;

				if( buffer_offset >= buffer_size )
				{
					break;
				}
			}
			if( ( io_handle->mode == 1 )
			 || ( io_handle->mode == 2 ) )
			{
				read_size = 276;

				if( ( read_size + buffer_offset ) > buffer_size )
				{
					read_size = buffer_size - buffer_offset;
				}
/* TODO determine missing data instead of 0 fill */
				if( memory_set(
				     &( buffer[ buffer_offset ] ),
				     0,
				     read_size ) == NULL )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_MEMORY,
					 LIBCERROR_MEMORY_ERROR_SET_FAILED,
					 "%s: unable to set sector error correction data in buffer.",
					 function );

					return( -1 );
				}
				buffer_offset += read_size;

				if( buffer_offset >= buffer_size )
				{
					break;
				}
			}
			else
			{
				read_size = 288;

				if( ( read_size + buffer_offset ) > buffer_size )
				{
					read_size = buffer_size - buffer_offset;
				}
				if( memory_set(
				     &( buffer[ buffer_offset ] ),
				     0,
				     read_size ) == NULL )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_MEMORY,
					 LIBCERROR_MEMORY_ERROR_SET_FAILED,
					 "%s: unable to set sector data in buffer.",
					 function );

					return( -1 );
				}
				buffer_offset += read_size;

				if( buffer_offset >= buffer_size )
				{
					break;
				}
			}
		}
		sector_index++;
	}
	return( (ssize_t) buffer_offset );
}
/* Reads the volume name values
 * Returns 1 if successful or -1 on error
 */
int libfsntfs_volume_name_values_read(
     libfsntfs_volume_name_values_t *volume_name_values,
     const uint8_t *data,
     size_t data_size,
     libcerror_error_t **error )
{
	static char *function                       = "libfsntfs_volume_name_values_read";

#if defined( HAVE_DEBUG_OUTPUT )
	libcstring_system_character_t *value_string = NULL;
	size_t value_string_size                    = 0;
	int result                                  = 0;
#endif

	if( volume_name_values == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid volume name values.",
		 function );

		return( -1 );
	}
	/* The size of the data can be 0 if the name is not set.
	 */
	if( data_size == 0 )
	{
		return( 1 );
	}
	if( data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: invalid data.",
		 function );

		goto on_error;
	}
	if( data_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: invalid data size value out of bounds.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: volume name data:\n",
		 function );
		libcnotify_print_data(
		 data,
		 data_size,
		 0 );
	}
#endif
	if( data_size > 0 )
	{
		volume_name_values->name = (uint8_t *) memory_allocate(
		                                        sizeof( uint8_t ) * data_size );

		if( volume_name_values->name == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_MEMORY,
			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
			 "%s: unable to create name.",
			 function );

			goto on_error;
		}
		volume_name_values->name_size = data_size;

		if( memory_copy(
		     volume_name_values->name,
		     data,
		     volume_name_values->name_size ) == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_MEMORY,
			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
			 "%s: unable to copy volume name.",
			 function );

			goto on_error;
		}
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
			result = libuna_utf16_string_size_from_utf16_stream(
				  volume_name_values->name,
				  volume_name_values->name_size,
				  LIBUNA_ENDIAN_LITTLE,
				  &value_string_size,
				  error );
#else
			result = libuna_utf8_string_size_from_utf16_stream(
				  volume_name_values->name,
				  volume_name_values->name_size,
				  LIBUNA_ENDIAN_LITTLE,
				  &value_string_size,
				  error );
#endif
			if( result != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
				 "%s: unable to determine size of name string.",
				 function );

				goto on_error;
			}
			value_string = libcstring_system_string_allocate(
			                value_string_size );

			if( value_string == NULL )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_MEMORY,
				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
				 "%s: unable to create name string.",
				 function );

				goto on_error;
			}
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
			result = libuna_utf16_string_copy_from_utf16_stream(
				  (libuna_utf16_character_t *) value_string,
				  value_string_size,
				  volume_name_values->name,
				  volume_name_values->name_size,
				  LIBUNA_ENDIAN_LITTLE,
				  error );
#else
			result = libuna_utf8_string_copy_from_utf16_stream(
				  (libuna_utf8_character_t *) value_string,
				  value_string_size,
				  volume_name_values->name,
				  volume_name_values->name_size,
				  LIBUNA_ENDIAN_LITTLE,
				  error );
#endif
			if( result != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
				 "%s: unable to set name string.",
				 function );

				goto on_error;
			}
			libcnotify_printf(
			 "%s: name\t\t\t\t\t: %" PRIs_LIBCSTRING_SYSTEM "\n",
			 function,
			 value_string );

			memory_free(
			 value_string );

			value_string = NULL;

			libcnotify_printf(
			 "\n" );
		}
#endif
	}
	return( 1 );

on_error:
#if defined( HAVE_DEBUG_OUTPUT )
	if( value_string != NULL )
	{
		memory_free(
		 value_string );
	}
#endif
	if( volume_name_values->name != NULL )
	{
		memory_free(
		 volume_name_values->name );

		volume_name_values->name = NULL;
	}
	volume_name_values->name_size = 0;

	return( -1 );
}
/* Reads the block descriptor
 * Returns 1 if successful, 0 if block list entry is empty or -1 on error
 */
int libvshadow_block_range_descriptor_read(
    libvshadow_block_range_descriptor_t *block_range_descriptor,
    const uint8_t *block_list_entry_data,
    size_t block_list_entry_size,
    int store_index LIBVSHADOW_ATTRIBUTE_UNUSED,
    libcerror_error_t **error )
{
    static char *function = "libvshadow_block_range_descriptor_read";

    LIBVSHADOW_UNREFERENCED_PARAMETER( store_index )

    if( block_range_descriptor == NULL )
    {
        libcerror_error_set(
            error,
            LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
            LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
            "%s: invalid block descriptor.",
            function );

        return( -1 );
    }
    if( block_list_entry_data == NULL )
    {
        libcerror_error_set(
            error,
            LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
            LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
            "%s: invalid block list entry data.",
            function );

        return( -1 );
    }
    if( block_list_entry_size > (size_t) SSIZE_MAX )
    {
        libcerror_error_set(
            error,
            LIBCERROR_ERROR_DOMAIN_RUNTIME,
            LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
            "%s: invalid block list entry size value exceeds maximum.",
            function );

        return( -1 );
    }
    if( memory_compare(
                block_list_entry_data,
                vshadow_empty_store_block_range_list_entry,
                sizeof( vshadow_store_block_range_list_entry_t ) ) == 0 )
    {
        return( 0 );
    }
#if defined( HAVE_DEBUG_OUTPUT )
    if( libcnotify_verbose != 0 )
    {
        libcnotify_printf(
            "%s: store: %02d block range list entry data:\n",
            function,
            store_index );
        libcnotify_print_data(
            block_list_entry_data,
            sizeof( vshadow_store_block_range_list_entry_t ),
            0 );
    }
#endif
    byte_stream_copy_to_uint64_little_endian(
        ( (vshadow_store_block_range_list_entry_t *) block_list_entry_data )->offset,
        block_range_descriptor->offset );

    byte_stream_copy_to_uint64_little_endian(
        ( (vshadow_store_block_range_list_entry_t *) block_list_entry_data )->relative_offset,
        block_range_descriptor->relative_offset );

    byte_stream_copy_to_uint64_little_endian(
        ( (vshadow_store_block_range_list_entry_t *) block_list_entry_data )->size,
        block_range_descriptor->size );

#if defined( HAVE_DEBUG_OUTPUT )
    if( libcnotify_verbose != 0 )
    {
        libcnotify_printf(
            "%s: store: %02d offset\t\t: 0x%08" PRIx64 "\n",
            function,
            store_index,
            block_range_descriptor->offset );

        libcnotify_printf(
            "%s: store: %02d relative offset\t: 0x%08" PRIx64 "\n",
            function,
            store_index,
            block_range_descriptor->relative_offset );

        libcnotify_printf(
            "%s: store: %02d size\t\t\t: %" PRIu64 "\n",
            function,
            store_index,
            block_range_descriptor->size );

        libcnotify_printf(
            "\n" );
    }
#endif
    return( 1 );
}
Beispiel #17
0
/* Reads a external key from the metadata entry
 * Returns 1 if successful or -1 on error
 */
int libbde_external_key_read(
     libbde_external_key_t *external_key,
     libbde_metadata_entry_t *metadata_entry,
     libcerror_error_t **error )
{
	libbde_key_t *key                                = NULL;
	libbde_metadata_entry_t *property_metadata_entry = NULL;
	uint8_t *value_data                              = NULL;
	static char *function                            = "libbde_external_key_read";
	size_t value_data_size                           = 0;
	ssize_t read_count                               = 0;
	int property_metadata_entry_index                = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	libcstring_system_character_t filetime_string[ 32 ];
	libcstring_system_character_t guid_string[ 48 ];

	libfdatetime_filetime_t *filetime                = NULL;
	libfguid_identifier_t *guid                      = NULL;
	int result                                       = 0;
#endif

	if( external_key == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid external key.",
		 function );

		return( -1 );
	}
	if( metadata_entry == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid metadata entry.",
		 function );

		return( -1 );
	}
	if( metadata_entry->value_type != LIBBDE_VALUE_TYPE_EXTERNAL_KEY )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
		 "%s: invalid metadata entry - unsupported value type: 0x%04" PRIx16 ".",
		 function,
		 metadata_entry->value_type );

		return( -1 );
	}
	value_data      = metadata_entry->value_data;
	value_data_size = metadata_entry->value_data_size;

	if( value_data_size < sizeof( bde_metadata_entry_external_key_header_t ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: value data size value out of bounds.",
		 function );

		return( -1 );
	}
	if( memory_copy(
	     external_key->identifier,
	     ( (bde_metadata_entry_external_key_header_t *) value_data )->identifier,
	     16 ) == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
		 "%s: unable to copy volume identifier.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		if( libfguid_identifier_initialize(
		     &guid,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create GUID.",
			 function );

			goto on_error;
		}
		if( libfguid_identifier_copy_from_byte_stream(
		     guid,
		     ( (bde_metadata_entry_external_key_header_t *) value_data )->identifier,
		     16,
		     LIBFGUID_ENDIAN_LITTLE,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
			 "%s: unable to copy byte stream to GUID.",
			 function );

			goto on_error;
		}
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
		result = libfguid_identifier_copy_to_utf16_string(
			  guid,
			  (uint16_t *) guid_string,
			  48,
			  LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
			  error );
#else
		result = libfguid_identifier_copy_to_utf8_string(
			  guid,
			  (uint8_t *) guid_string,
			  48,
			  LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
			  error );
#endif
		if( result != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
			 "%s: unable to copy GUID to string.",
			 function );

			goto on_error;
		}
		libcnotify_printf(
		 "%s: identifier\t\t\t\t\t: %" PRIs_LIBCSTRING_SYSTEM "\n",
		 function,
		 guid_string );

		if( libfguid_identifier_free(
		     &guid,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
			 "%s: unable to free GUID.",
			 function );

			goto on_error;
		}

		if( libfdatetime_filetime_initialize(
		     &filetime,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create filetime.",
			 function );

			goto on_error;
		}
		if( libfdatetime_filetime_copy_from_byte_stream(
		     filetime,
		     ( (bde_metadata_entry_external_key_header_t *) value_data )->modification_time,
		     8,
		     LIBFDATETIME_ENDIAN_LITTLE,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
			 "%s: unable to copy filetime from byte stream.",
			 function );

			goto on_error;
		}
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
		result = libfdatetime_filetime_copy_to_utf16_string(
			  filetime,
			  (uint16_t *) filetime_string,
			  32,
			  LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
			  error );
#else
		result = libfdatetime_filetime_copy_to_utf8_string(
			  filetime,
			  (uint8_t *) filetime_string,
			  32,
			  LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
			  error );
#endif
		if( result != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
			 "%s: unable to copy filetime to string.",
			 function );

			goto on_error;
		}
		libcnotify_printf(
		 "%s: modification time\t\t\t\t: %" PRIs_LIBCSTRING_SYSTEM " UTC\n",
		 function,
		 filetime_string );

		if( libfdatetime_filetime_free(
		     &filetime,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
			 "%s: unable to free filetime.",
			 function );

			goto on_error;
		}
		libcnotify_printf(
		 "\n" );
	}
#endif
	value_data      += sizeof( bde_metadata_entry_external_key_header_t );
	value_data_size -= sizeof( bde_metadata_entry_external_key_header_t );

	while( value_data_size >= sizeof( bde_metadata_entry_v1_t ) )
	{
		if( memory_compare(
		     value_data,
		     libbde_metadata_entry_empty,
		     sizeof( bde_metadata_entry_v1_t ) ) == 0 )
		{
			break;
		}
		if( libbde_metadata_entry_initialize(
		     &property_metadata_entry,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create property metadata entry.",
			 function );

			goto on_error;
		}
		read_count = libbde_metadata_entry_read(
			      property_metadata_entry,
			      value_data,
			      value_data_size,
			      error );

		if( read_count == -1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_IO,
			 LIBCERROR_IO_ERROR_READ_FAILED,
			 "%s: unable to read property metadata entry.",
			 function );

			goto on_error;
		}
		value_data      += read_count;
		value_data_size -= read_count;

		if( property_metadata_entry->value_type == LIBBDE_VALUE_TYPE_KEY )
		{
			if( libbde_key_initialize(
			     &key,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
				 "%s: unable to create key.",
				 function );

				goto on_error;
			}
			if( libbde_key_read(
			     key,
			     property_metadata_entry,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_IO,
				 LIBCERROR_IO_ERROR_READ_FAILED,
				 "%s: unable to read key metadata entry.",
				 function );

				goto on_error;
			}
			if( external_key->key == NULL )
			{
				external_key->key = key;

				key = NULL;
			}
			if( key != NULL )
			{
				if( libbde_key_free(
				     &key,
				     error ) != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
					 "%s: unable to free key.",
					 function );

					goto on_error;
				}
			}
		}
		else if( property_metadata_entry->value_type == LIBBDE_VALUE_TYPE_UNICODE_STRING )
		{
#if defined( HAVE_DEBUG_OUTPUT )
			if( libbde_metadata_entry_read_string(
			     property_metadata_entry,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_IO,
				 LIBCERROR_IO_ERROR_READ_FAILED,
				 "%s: unable to read string from property metadata entry.",
				 function );

				goto on_error;
			}
#endif
			if( external_key->string_entry == NULL )
			{
				external_key->string_entry = property_metadata_entry;
			}
		}
		if( libcdata_array_append_entry(
		     external_key->entries_array,
		     &property_metadata_entry_index,
		     (intptr_t *) property_metadata_entry,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to append property metadata entry to entries array.",
			 function );

			goto on_error;
		}
		property_metadata_entry = NULL;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		if( value_data_size > 0 )
		{
			libcnotify_printf(
			 "%s: trailing data:\n",
			 function );
			libcnotify_print_data(
			 value_data,
			 value_data_size,
			 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
		}
	}
#endif
	return( 1 );

on_error:
#if defined( HAVE_DEBUG_OUTPUT )
	if( guid != NULL )
	{
		libfguid_identifier_free(
		 &guid,
		 NULL );
	}
	if( filetime != NULL )
	{
		libfdatetime_filetime_free(
		 &filetime,
		 NULL );
	}
#endif
	if( key != NULL )
	{
		libbde_key_free(
		 &key,
		 NULL );
	}
	if( property_metadata_entry != NULL )
	{
		libbde_metadata_entry_free(
		 &property_metadata_entry,
		 NULL );
	}
	return( -1 );
}
/* Sets the data of an array of variable sized strings
 * This function will look for a NUL-character as the indicator of
 * the end of the string upto data_size
 * Returns data size of the string array if successful or -1 on error
 */
ssize_t libfvalue_value_type_set_data_strings_array(
         libfvalue_value_t *value,
         const uint8_t *data,
         size_t data_size,
         int encoding,
         libcerror_error_t **error )
{
	static char *function   = "libfvalue_value_type_set_data_strings_array";
	ssize_t data_index      = 0;
	ssize_t last_data_index = 0;
	int value_entry_index   = 0;

	if( value == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid value.",
		 function );

		return( -1 );
	}
	while( (size_t) last_data_index < data_size )
	{
		data_index = libfvalue_value_type_get_string_size(
			      value,
		              &( data[ last_data_index ] ),
		              data_size - last_data_index,
			      error );

		if( data_index == -1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
			 "%s: unable to determine data string size.",
			 function );

			return( -1 );
		}
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: strings array value entry: %d data:\n",
			 function,
			 value_entry_index );
			libcnotify_print_data(
			 &( data[ last_data_index ] ),
			 (size_t) data_index,
			 0 );
		}
#endif
		if( libfvalue_value_append_entry_data(
		     value,
		     &value_entry_index,
		     &( data[ last_data_index ] ),
		     (size_t) data_index,
		     encoding,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
			 "%s: unable to append value entry.",
			 function );

			return( -1 );
		}
		last_data_index += data_index;
	}
	return( last_data_index );
}
Beispiel #19
0
/* Reads a page and its values
 * Returns 1 if successful or -1 on error
 */
int libesedb_page_read(
     libesedb_page_t *page,
     libesedb_io_handle_t *io_handle,
     libbfio_handle_t *file_io_handle,
     off64_t file_offset,
     libcerror_error_t **error )
{
	libcdata_array_t *page_tags_array  = NULL;
	uint8_t *page_values_data          = NULL;
	static char *function              = "libesedb_page_read";
	size_t page_values_data_offset     = 0;
	size_t page_values_data_size       = 0;
	ssize_t read_count                 = 0;
	uint32_t calculated_ecc32_checksum = 0;
	uint32_t calculated_page_number    = 0;
	uint32_t calculated_xor32_checksum = 0;
	uint32_t stored_ecc32_checksum     = 0;
	uint32_t stored_page_number        = 0;
	uint32_t stored_xor32_checksum     = 0;
	uint16_t available_data_size       = 0;
	uint16_t available_page_tag        = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	uint64_t value_64bit               = 0;
	uint16_t value_16bit               = 0;
#endif

	if( page == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid page.",
		 function );

		return( -1 );
	}
	if( page->data != NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
		 "%s: invalid page data already set.",
		 function );

		return( -1 );
	}
	if( io_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid IO handle.",
		 function );

		return( -1 );
	}
	calculated_page_number = (uint32_t) ( ( file_offset - io_handle->page_size ) / io_handle->page_size );

	page->offset = file_offset;

#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: reading page: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
		 function,
		 calculated_page_number,
		 page->offset,
		 page->offset );
	}
#endif
	if( libbfio_handle_seek_offset(
	     file_io_handle,
	     page->offset,
	     SEEK_SET,
	     error ) == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_SEEK_FAILED,
		 "%s: unable to seek page offset: %" PRIi64 ".",
		 function,
		 page->offset );

		goto on_error;
	}
	page->data = (uint8_t *) memory_allocate(
	                          (size_t) io_handle->page_size );

	if( page->data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
		 "%s: unable to create page data.",
		 function );

		goto on_error;
	}
	page->data_size = (size_t) io_handle->page_size;

	read_count = libbfio_handle_read_buffer(
	              file_io_handle,
	              page->data,
	              page->data_size,
	              error );

	if( read_count != (ssize_t) page->data_size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read page data.",
		 function );

		goto on_error;
	}
	page_values_data      = page->data;
	page_values_data_size = page->data_size;

#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: page header:\n",
		 function );
		libcnotify_print_data(
		 page_values_data,
		 sizeof( esedb_page_header_t ),
		 0 );
	}
#endif
	page->page_number = calculated_page_number;

	byte_stream_copy_to_uint16_little_endian(
	 ( (esedb_page_header_t *) page_values_data )->available_data_size,
	 available_data_size );

	byte_stream_copy_to_uint32_little_endian(
	 ( (esedb_page_header_t *) page_values_data )->previous_page,
	 page->previous_page_number );
	byte_stream_copy_to_uint32_little_endian(
	 ( (esedb_page_header_t *) page_values_data )->next_page,
	 page->next_page_number );
	byte_stream_copy_to_uint32_little_endian(
	 ( (esedb_page_header_t *) page_values_data )->father_data_page_object_identifier,
	 page->father_data_page_object_identifier );

	byte_stream_copy_to_uint16_little_endian(
	 ( (esedb_page_header_t *) page_values_data )->available_page_tag,
	 available_page_tag );

	byte_stream_copy_to_uint32_little_endian(
	 ( (esedb_page_header_t *) page_values_data )->page_flags,
	 page->flags );

	/* Make sure to read after the page flags
	 */
	if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
	 && ( io_handle->page_size >= 16384 ) )
	{
		/* TODO handle checksum */
	}
	else
	{
		byte_stream_copy_to_uint32_little_endian(
		 ( (esedb_page_header_t *) page_values_data )->xor_checksum,
		 stored_xor32_checksum );

		if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT )
		 && ( ( page->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) )
		{
			byte_stream_copy_to_uint32_little_endian(
			 ( (esedb_page_header_t *) page_values_data )->ecc_checksum,
			 stored_ecc32_checksum );
		}
		else
		{
			byte_stream_copy_to_uint32_little_endian(
			 ( (esedb_page_header_t *) page_values_data )->page_number,
			 stored_page_number );
		}
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: current page number\t\t\t\t\t: %" PRIu32 "\n",
		 function,
		 calculated_page_number );

		if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
		 && ( io_handle->page_size >= 16384 ) )
		{
			/* TODO handle checksum */

			byte_stream_copy_to_uint64_little_endian(
			 page_values_data,
			 value_64bit );
			libcnotify_printf(
			 "%s: checksum\t\t\t\t\t\t: 0x%08" PRIx64 "\n",
			 function,
			 value_64bit );
		}
		else
		{
			libcnotify_printf(
			 "%s: XOR checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
			 function,
			 stored_xor32_checksum );

			if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT )
			 && ( ( page->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) )
			{
				libcnotify_printf(
				 "%s: ECC checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
				 function,
				 stored_ecc32_checksum );
			}
			else
			{
				libcnotify_printf(
				 "%s: page number\t\t\t\t\t\t: %" PRIu32 "\n",
				 function,
				 stored_page_number );
			}
		}
		libcnotify_printf(
		 "%s: database modification time:\n",
		 function );
		libcnotify_print_data(
		 ( (esedb_page_header_t *) page_values_data )->database_modification_time,
		 8,
		 0 );

		libcnotify_printf(
		 "%s: previous page number\t\t\t\t: %" PRIu32 "\n",
		 function,
		 page->previous_page_number );
		libcnotify_printf(
		 "%s: next page number\t\t\t\t\t: %" PRIu32 "\n",
		 function,
		 page->next_page_number );
		libcnotify_printf(
		 "%s: father data page (FDP) object identifier\t\t: %" PRIu32 "\n",
		 function,
		 page->father_data_page_object_identifier );

		libcnotify_printf(
		 "%s: available data size\t\t\t\t\t: %" PRIu32 "\n",
		 function,
		 available_data_size );

		byte_stream_copy_to_uint16_little_endian(
		 ( (esedb_page_header_t *) page_values_data )->available_uncommitted_data_size,
		 value_16bit );
		libcnotify_printf(
		 "%s: available uncommitted data size\t\t\t: %" PRIu16 "\n",
		 function,
		 value_16bit );

		byte_stream_copy_to_uint16_little_endian(
		 ( (esedb_page_header_t *) page_values_data )->available_data_offset,
		 value_16bit );
		libcnotify_printf(
		 "%s: available data offset\t\t\t\t: %" PRIu16 "\n",
		 function,
		 value_16bit );

		libcnotify_printf(
		 "%s: available page tag\t\t\t\t\t: %" PRIu32 "\n",
		 function,
		 available_page_tag );

		libcnotify_printf(
		 "%s: page flags\t\t\t\t\t\t: 0x%08" PRIx32 "\n",
		 function,
		 page->flags );
		libesedb_debug_print_page_flags(
		 page->flags );
		libcnotify_printf(
		 "\n" );
	}
#endif
	/* TODO for now don't bother calculating a checksum for uninitialized pages */

	if( ( page_values_data[ 0 ] != 0 )
	 || ( page_values_data[ 1 ] != 0 )
	 || ( page_values_data[ 2 ] != 0 )
	 || ( page_values_data[ 3 ] != 0 ) )
	{
		if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
		 && ( io_handle->page_size >= 16384 ) )
		{
			/* TODO handle checksum */
		}
		else if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT )
		      && ( ( page->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) )
		{
			if( libesedb_checksum_calculate_little_endian_ecc32(
			     &calculated_ecc32_checksum,
			     &calculated_xor32_checksum,
			     page_values_data,
			     page_values_data_size,
			     8,
			     calculated_page_number,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
				 "%s: unable to calculate ECC-32 and XOR-32 checksum.",
				 function );

				goto on_error;
			}
		}
		else
		{
			if( libesedb_checksum_calculate_little_endian_xor32(
			     &calculated_xor32_checksum,
			     &( page_values_data[ 4 ] ),
			     page_values_data_size - 4,
			     0x89abcdef,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
				 "%s: unable to calculate XOR-32 checksum.",
				 function );

				goto on_error;
			}
		}
		if( stored_xor32_checksum != calculated_xor32_checksum )
		{
#ifdef TODO
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_INPUT,
			 LIBCERROR_INPUT_ERROR_CRC_MISMATCH,
			 "%s: mismatch in page XOR-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).",
			 function,
			 stored_xor32_checksum,
			 calculated_xor32_checksum );

			goto on_error;
#else
			if( libcnotify_verbose != 0 )
			{
				libcnotify_printf(
				 "%s: mismatch in page XOR-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n",
				 function,
				 stored_xor32_checksum,
				 calculated_xor32_checksum );
			}
#endif
		}
		if( stored_ecc32_checksum != calculated_ecc32_checksum )
		{
#ifdef TODO
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_INPUT,
			 LIBCERROR_INPUT_ERROR_CRC_MISMATCH,
			 "%s: mismatch in page ECC-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).",
			 function,
			 stored_ecc32_checksum,
			 calculated_ecc32_checksum );

			goto on_error;
#else
			if( libcnotify_verbose != 0 )
			{
				libcnotify_printf(
				 "%s: mismatch in page ECC-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n",
				 function,
				 stored_ecc32_checksum,
				 calculated_ecc32_checksum );
			}
#endif
		}
	}
	page_values_data        += sizeof( esedb_page_header_t );
	page_values_data_size   -= sizeof( esedb_page_header_t );
	page_values_data_offset += sizeof( esedb_page_header_t );

	if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
	 && ( io_handle->page_size >= 16384 ) )
	{
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: extended page header:\n",
			 function );
			libcnotify_print_data(
			 page_values_data,
			 40,
			 0 );
		}
#endif
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			byte_stream_copy_to_uint64_little_endian(
			 ( (esedb_extended_page_header_t *) page_values_data )->checksum1,
			 value_64bit );
			libcnotify_printf(
			 "%s: checksum1\t\t\t\t\t\t: 0x%08" PRIx64 "\n",
			 function,
			 value_64bit );

			byte_stream_copy_to_uint64_little_endian(
			 ( (esedb_extended_page_header_t *) page_values_data )->checksum2,
			 value_64bit );
			libcnotify_printf(
			 "%s: checksum2\t\t\t\t\t\t: 0x%08" PRIx64 "\n",
			 function,
			 value_64bit );

			byte_stream_copy_to_uint64_little_endian(
			 ( (esedb_extended_page_header_t *) page_values_data )->checksum3,
			 value_64bit );
			libcnotify_printf(
			 "%s: checksum3\t\t\t\t\t\t: 0x%08" PRIx64 "\n",
			 function,
			 value_64bit );

			byte_stream_copy_to_uint64_little_endian(
			 ( (esedb_extended_page_header_t *) page_values_data )->page_number,
			 value_64bit );
			libcnotify_printf(
			 "%s: page number\t\t\t\t\t\t: %" PRIu64 "\n",
			 function,
			 value_64bit );

			libcnotify_printf(
			 "%s: unknown1:\n",
			 function );
			libcnotify_print_data(
			 ( (esedb_extended_page_header_t *) page_values_data )->unknown1,
			 8,
			 0 );
		}
#endif
		page_values_data        += sizeof( esedb_extended_page_header_t );
		page_values_data_size   -= sizeof( esedb_extended_page_header_t );
		page_values_data_offset += sizeof( esedb_extended_page_header_t );
	}
	if( available_page_tag > 0 )
	{
		/* Create the page tags array
		 */
		if( libcdata_array_initialize(
		     &page_tags_array,
		     0,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create page tags array.",
			 function );

			goto on_error;
		}
		if( libesedb_page_read_tags(
		     page_tags_array,
		     io_handle,
		     available_page_tag,
		     page->data,
		     page->data_size,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_IO,
			 LIBCERROR_IO_ERROR_READ_FAILED,
			 "%s: unable to read page tags.",
			 function );

			goto on_error;
		}
		/* The offsets in the page tags are relative after the page header
		 */
		if( libesedb_page_read_values(
		     page,
		     io_handle,
		     page_tags_array,
		     page_values_data,
		     page_values_data_size,
		     page_values_data_offset,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_IO,
			 LIBCERROR_IO_ERROR_READ_FAILED,
			 "%s: unable to read page values.",
			 function );

			goto on_error;
		}
		if( libcdata_array_free(
		     &page_tags_array,
		     (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_tags_value_free,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
			 "%s: unable to free the page tags array.",
			 function );

			goto on_error;
		}
	}
	return( 1 );

on_error:
	if( page_tags_array != NULL )
	{
		libcdata_array_free(
		 &page_tags_array,
		 (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_tags_value_free,
		 NULL );
	}
	if( page->data != NULL )
	{
		memory_free(
		 page->data );

		page->data = NULL;
	}
	return( -1 );
}
/* Determines the size of a variable sized string
 * This function will look for a end-of-string character as the indicator
 * of the end of the string upto data size
 * Returns data size of the string if successful or -1 on error
 */
ssize_t libfvalue_value_type_get_string_size(
         libfvalue_value_t *value,
         const uint8_t *data,
         size_t data_size,
         libcerror_error_t **error )
{
	libfvalue_internal_value_t *internal_value = NULL;
	static char *function                      = "libfvalue_value_type_get_string_size";
	size_t data_index                          = 0;

	if( value == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid value.",
		 function );

		return( -1 );
	}
	internal_value = (libfvalue_internal_value_t *) value;

	if( ( internal_value->type != LIBFVALUE_VALUE_TYPE_STRING_BYTE_STREAM )
	 && ( internal_value->type != LIBFVALUE_VALUE_TYPE_STRING_UTF8 )
	 && ( internal_value->type != LIBFVALUE_VALUE_TYPE_STRING_UTF16 )
	 && ( internal_value->type != LIBFVALUE_VALUE_TYPE_STRING_UTF32 ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported type: 0x%02" PRIx8 ".",
		 function,
		 internal_value->type );

		return( -1 );
	}
	if( data != NULL )
	{
		if( ( internal_value->type == LIBFVALUE_VALUE_TYPE_STRING_BYTE_STREAM )
		 || ( internal_value->type == LIBFVALUE_VALUE_TYPE_STRING_UTF8 ) )
		{
			while( data_index < data_size )
			{
				if( data[ data_index ] == 0 )
				{
					data_index += 1;

					break;
				}
				data_index += 1;
			}
		}
		else if( internal_value->type == LIBFVALUE_VALUE_TYPE_STRING_UTF16 )
		{
			while( ( data_index + 1 ) < data_size )
			{
				if( ( data[ data_index ] == 0 )
				 && ( data[ data_index + 1 ] == 0 ) )
				{
					data_index += 2;

					break;
				}
				data_index += 2;
			}
		}
		else if( internal_value->type == LIBFVALUE_VALUE_TYPE_STRING_UTF32 )
		{
			while( ( data_index + 3 ) < data_size )
			{
				if( ( data[ data_index ] == 0 )
				 && ( data[ data_index + 1 ] == 0 )
				 && ( data[ data_index + 2 ] == 0 )
				 && ( data[ data_index + 3 ] == 0 ) )
				{
					data_index += 4;

					break;
				}
				data_index += 4;
			}
		}
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: string data:\n",
			 function );
			libcnotify_print_data(
			 data,
			 data_index,
			 0 );
		}
#endif
	}
	return( (ssize_t) data_index );
}
Beispiel #21
0
int main( int argc, char * const argv[] )
#endif
{
	char destination[ 128 ];

	libcerror_error_t *error           = NULL;
	libcfile_file_t *source_file       = NULL;
	uint8_t *buffer                    = NULL;
	uint8_t *uncompressed_data         = NULL;
	char *program                      = "ascii7decompress";
	libcstring_system_integer_t option = 0;
	char *source                       = NULL;
	size64_t source_size               = 0;
	off_t source_offset                = 0;
	size_t buffer_size                 = 0;
	size_t uncompressed_data_size      = 0;
	ssize_t read_count                 = 0;
	int print_count                    = 0;
	int verbose                        = 0;

	assorted_output_version_fprint(
	 stdout,
	 program );

	while( ( option = libcsystem_getopt(
	                   argc,
	                   argv,
	                   _LIBCSTRING_SYSTEM_STRING( "ho:s:vV" ) ) ) != (libcstring_system_integer_t) -1 )
	{
		switch( option )
		{
			case '?':
			default:
				fprintf(
				 stderr,
				 "Invalid argument: %" PRIs_LIBCSTRING_SYSTEM "\n",
				 argv[ optind ] );

				usage_fprint(
				 stdout );

				return( EXIT_FAILURE );

			case 'h':
				usage_fprint(
				 stdout );

				return( EXIT_SUCCESS );

			case 'o':
				source_offset = atol( optarg );

				break;

			case 's':
				source_size = atol( optarg );

				break;

			case 'v':
				verbose = 1;

				break;

			case 'V':
				assorted_output_copyright_fprint(
				 stdout );

				return( EXIT_SUCCESS );
		}
	}
	if( optind == argc )
	{
		fprintf(
		 stderr,
		 "Missing source file.\n" );

		usage_fprint(
		 stdout );

		return( EXIT_FAILURE );
	}
	source = argv[ optind ];

	libcnotify_stream_set(
	 stderr,
	 NULL );
	libcnotify_verbose_set(
	 verbose );

	/* Open the source file
	 */
	if( libcfile_file_initialize(
	     &source_file,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to create source file.\n" );

		goto on_error;
	}
	if( libcfile_file_open(
	     source_file,
	     source,
	     LIBCFILE_OPEN_READ,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to open source file.\n" );

		goto on_error;
	}
	if( source_size == 0 )
	{
		if( libcfile_file_get_size(
		     source_file,
		     &source_size,
		     &error ) == -1 )
		{
			fprintf(
			 stderr,
			 "Unable to determine size of source file.\n" );

			goto on_error;
		}
	}
	if( source_size == 0 )
	{
		fprintf(
		 stderr,
		 "Invalid source size value is zero.\n" );

		goto on_error;
	}
	if( source_size > (size_t) SSIZE_MAX )
	{
		fprintf(
		 stderr,
		 "Invalid source size value exceeds maximum.\n" );

		goto on_error;
	}
	/* Create the input buffer
	 */
	buffer_size = source_size;

	buffer = (uint8_t *) memory_allocate(
	                      sizeof( uint8_t ) * buffer_size );

	if( buffer == NULL )
	{
		fprintf(
		 stderr,
		 "Unable to create buffer.\n" );

		return( EXIT_FAILURE );
	}
	uncompressed_data_size = 1 + ( ( ( source_size - 1 ) * 8 ) / 7 );

	uncompressed_data = (uint8_t *) memory_allocate(
	                                 sizeof( uint8_t ) * uncompressed_data_size );

	if( uncompressed_data == NULL )
	{
		fprintf(
		 stderr,
		 "Unable to create uncompressed data buffer.\n" );

		return( EXIT_FAILURE );
	}
	/* Position the source file at the right offset
	 */
	if( libcfile_file_seek_offset(
	     source_file,
	     source_offset,
	     SEEK_SET,
	     &error ) == -1 )
	{
		fprintf(
		 stderr,
		 "Unable to seek offset in source file.\n" );

		goto on_error;
	}
	print_count = libcstring_narrow_string_snprintf(
	               destination,
	               128,
	               "%s.ascii7decompressed",
	               source );

	if( ( print_count < 0 )
	 || ( print_count > 128 ) )
	{
		fprintf(
		 stderr,
		 "Unable to set destination filename.\n" );

		memory_free(
		 uncompressed_data );
		memory_free(
		 buffer );

		return( EXIT_FAILURE );
	}
	fprintf(
	 stdout,
	 "Starting 7-bit ASCII decompression of: %s at offset: %jd (0x%08jx).\n",
	 source,
	 source_offset,
	 source_offset );

	read_count = libcfile_file_read_buffer(
		      source_file,
		      buffer,
		      source_size,
	              &error );

	if( read_count != (ssize_t) source_size )
	{
		fprintf(
		 stderr,
		 "Unable to read from source file.\n" );

		goto on_error;
	}
	/* Decompress the data
	 */
	fprintf(
	 stderr,
	 "Compressed data:\n" );

	libcnotify_print_data(
	 buffer,
	 source_size,
	 0 );

	if( ascii7_decompress(
	     uncompressed_data,
	     uncompressed_data_size,
	     buffer,
	     source_size,
	     NULL ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to decompress data.\n" );

		goto on_error;
	}
	fprintf(
	 stderr,
	 "Uncompressed data:\n" );

	libcnotify_print_data(
	 uncompressed_data,
	 uncompressed_data_size,
	 0 );

	source_offset += source_size;
	source_size   -= source_size;

#ifdef NOWRITE
	libcfile_file_t *destination_file = NULL;
	ssize_t write_count               = 0;

	if( destination_file == NULL )
	{
		/* Open the destination file
		 */
		if( libcfile_file_initialize(
		     &destination_file,
		     &error ) != 1 )
		{
			fprintf(
			 stderr,
			 "Unable to create destination file.\n" );

			goto on_error;
		}
		if( libcfile_file_open(
		     destination_file,
		     destination,
		     LIBCFILE_OPEN_WRITE,
		     &error ) != 1 )
		{
			fprintf(
			 stderr,
			 "Unable to open destination file.\n" );

			goto on_error;
		}
	}
	write_count = libcfile_file_write_buffer(
		       destination_file,
		       uncompressed_data,
		       uncompressed_data_size,
		       &error );

	if( write_count != (ssize_t) uncompressed_data_size )
	{
		fprintf(
		 stderr,
		 "Unable to write to destination file.\n" );

		goto on_error;
	}
	/* Clean up
	 */
	if( destination_file != NULL )
	{
		if( libcfile_file_close(
		     destination_file,
		     &error ) != 0 )
		{
			fprintf(
			 stderr,
			 "Unable to close destination file.\n" );

			goto on_error;
		}
		if( libcfile_file_free(
		     &destination_file,
		     &error ) != 1 )
		{
			fprintf(
			 stderr,
			 "Unable to free destination file.\n" );

			goto on_error;
		}
	}
#endif
	/* Clean up
	 */
	if( libcfile_file_close(
	     source_file,
	     &error ) != 0 )
	{
		fprintf(
		 stderr,
		 "Unable to close source file.\n" );

		goto on_error;
	}
	if( libcfile_file_free(
	     &source_file,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to free source file.\n" );

		goto on_error;
	}
	fprintf(
	 stdout,
	 "7-bit ASCII decompression:\tSUCCESS\n" );

	memory_free(
	 uncompressed_data );

	memory_free(
	 buffer );

	return( EXIT_SUCCESS );

on_error:
	if( error != NULL )
	{
		libcnotify_print_error_backtrace(
		 error );
		libcerror_error_free(
		 &error );
	}
#ifdef NOWRITE
	if( destination_file != NULL )
	{
		libcfile_file_free(
		 &destination_file,
		 NULL );
	}
#endif
	if( uncompressed_data != NULL )
	{
		memory_free(
		 uncompressed_data );
	}
	if( buffer != NULL )
	{
		memory_free(
		 buffer );
	}
	if( source_file != NULL )
	{
		libcfile_file_free(
		 &source_file,
		 NULL );
	}
	return( EXIT_FAILURE );
}
/* Reads the security descriptor values
 * Returns 1 if successful or -1 on error
 */
int libfsntfs_security_descriptor_values_read(
     libfsntfs_security_descriptor_values_t *security_descriptor_values,
     const uint8_t *data,
     size_t data_size,
     libcerror_error_t **error )
{
	static char *function                              = "libfsntfs_security_descriptor_values_read";

#if defined( HAVE_DEBUG_OUTPUT )
	libfwnt_security_descriptor_t *security_descriptor = NULL;
#endif

	if( security_descriptor_values == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid security descriptor values.",
		 function );

		return( -1 );
	}
	if( data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: invalid data.",
		 function );

		return( -1 );
	}
	if( data_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: invalid data size value out of bounds.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: security descriptor data:\n",
		 function );
		libcnotify_print_data(
		 data,
		 data_size,
		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
	}
#endif
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		if( libfwnt_security_descriptor_initialize(
		     &security_descriptor,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create security descriptor.",
			 function );

			goto on_error;
		}
		if( libfwnt_security_descriptor_copy_from_byte_stream(
		     security_descriptor,
		     data,
		     data_size,
		     LIBFWNT_ENDIAN_LITTLE,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
			 "%s: unable to copy security descriptor from byte stream.",
			 function );

			goto on_error;
		}
		if( libfwnt_security_descriptor_free(
		     &security_descriptor,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
			 "%s: unable to free security descriptor.",
			 function );

			goto on_error;
		}
		libcnotify_printf(
		 "\n" );
	}
#endif
	return( 1 );

on_error:
#if defined( HAVE_DEBUG_OUTPUT )
	if( security_descriptor != NULL )
	{
		libfwnt_security_descriptor_free(
		 &security_descriptor,
		 NULL );
	}
#endif
	return( -1 );
}
/* Reads the debug data
 * Returns 1 if successful or -1 on error
 */
int libexe_debug_data_read(
     libexe_debug_data_t *debug_data,
     libbfio_handle_t *file_io_handle,
     uint32_t file_offset,
     uint32_t size,
     libcerror_error_t **error )
{
	uint8_t *data         = NULL;
	static char *function = "libexe_debug_data_read";
	size_t read_count     = 0;

	if( debug_data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid debug data.",
		 function );

		return( -1 );
	}
#if SIZEOF_SIZE_T <= 4
	if( size > (uint32_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid size value exceeds maximum.",
		 function );

		return( -1 );
	}
#endif
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: reading debug data at offset: %" PRIu32 " (0x%08" PRIx32 ")\n",
		 function,
		 file_offset,
		 file_offset );
	}
#endif
	if( libbfio_handle_seek_offset(
	     file_io_handle,
	     (off64_t) file_offset,
	     SEEK_SET,
	     error ) == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_SEEK_FAILED,
		 "%s: unable to seek debug data offset: %" PRIx32 ".",
		 function,
		 file_offset );

		goto on_error;
	}
	data = (uint8_t *) memory_allocate(
	                    sizeof( uint8_t ) * size );

	if( data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
		 "%s: unable to create debug data.",
		 function );

		goto on_error;
	}
	read_count = libbfio_handle_read_buffer(
	              file_io_handle,
	              data,
	              size,
	              error );

	if( read_count != (ssize_t) size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read debug data.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: debug data:\n",
		 function );
		libcnotify_print_data(
		 data,
		 (size_t) size,
		 0 );
	}
#endif
	/* TODO extract values */

	memory_free(
	 data );

	return( 1 );

on_error:
	if( data != NULL )
	{
		memory_free(
		 data );
	}
	return( -1 );
}
Beispiel #24
0
int main( int argc, char * const argv[] )
#endif
{
	libcerror_error_t *error               = NULL;
	libcfile_file_t *destination_file      = NULL;
	libcfile_file_t *source_file           = NULL;
	libfcrypto_rc4_context_t *context      = NULL;
	system_character_t *option_keys        = NULL;
	system_character_t *option_target_path = NULL;
	system_character_t *source             = NULL;
	uint8_t *buffer                        = NULL;
	uint8_t *decrypted_data                = NULL;
	uint8_t *key_data                      = NULL;
	char *program                          = "rc4crypt";
	system_integer_t option                = 0;
	size64_t source_size                   = 0;
	size_t buffer_size                     = 0;
	size_t decrypted_data_size             = 0;
	size_t key_data_size                   = 0;
	ssize_t read_count                     = 0;
	ssize_t write_count                    = 0;
	off_t source_offset                    = 0;
	int verbose                            = 0;

	libcnotify_stream_set(
	 stderr,
	 NULL );
	libcnotify_verbose_set(
	 1 );

	assorted_output_version_fprint(
	 stdout,
	 program );

	while( ( option = assorted_getopt(
	                   argc,
	                   argv,
	                   _SYSTEM_STRING( "hk:o:s:t:vV" ) ) ) != (system_integer_t) -1 )
	{
		switch( option )
		{
			case (system_integer_t) '?':
			default:
				fprintf(
				 stderr,
				 "Invalid argument: %" PRIs_SYSTEM "\n",
				 argv[ optind ] );

				usage_fprint(
				 stdout );

				return( EXIT_FAILURE );

			case (system_integer_t) 'h':
				usage_fprint(
				 stdout );

				return( EXIT_SUCCESS );

			case (system_integer_t) 'k':
				option_keys = optarg;

				break;

			case (system_integer_t) 'o':
				source_offset = atol( optarg );

				break;

			case (system_integer_t) 's':
				source_size = atol( optarg );

				break;

			case (system_integer_t) 't':
				option_target_path = optarg;

				break;

			case (system_integer_t) 'v':
				verbose = 1;

				break;

			case (system_integer_t) 'V':
				assorted_output_copyright_fprint(
				 stdout );

				return( EXIT_SUCCESS );
		}
	}
	if( optind == argc )
	{
		fprintf(
		 stderr,
		 "Missing source file.\n" );

		usage_fprint(
		 stdout );

		return( EXIT_FAILURE );
	}
	source = argv[ optind ];

	if( option_keys == NULL )
	{
		fprintf(
		 stderr,
		 "Missing key.\n" );

		usage_fprint(
		 stdout );

		return( EXIT_FAILURE );
	}
	libcnotify_stream_set(
	 stderr,
	 NULL );
	libcnotify_verbose_set(
	 verbose );

	/* Open the source file
	 */
	if( libcfile_file_initialize(
	     &source_file,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to create source file.\n" );

		goto on_error;
	}
	if( libcfile_file_open(
	     source_file,
	     source,
	     LIBCFILE_OPEN_READ,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to open source file.\n" );

		goto on_error;
	}
	if( source_size == 0 )
	{
		if( libcfile_file_get_size(
		     source_file,
		     &source_size,
		     &error ) == -1 )
		{
			fprintf(
			 stderr,
			 "Unable to determine size of source file.\n" );

			goto on_error;
		}
	}
	if( source_size == 0 )
	{
		fprintf(
		 stderr,
		 "Invalid source size value is zero.\n" );

		return( EXIT_FAILURE );
	}
	if( source_size > (size_t) SSIZE_MAX )
	{
		fprintf(
		 stderr,
		 "Invalid source size value exceeds maximum.\n" );

		return( EXIT_FAILURE );
	}
	/* Create the input buffer
	 */
	buffer_size = source_size;

	buffer = (uint8_t *) memory_allocate(
	                      sizeof( uint8_t ) * buffer_size );

	if( buffer == NULL )
	{
		fprintf(
		 stderr,
		 "Unable to create buffer.\n" );

		return( EXIT_FAILURE );
	}
	decrypted_data_size = source_size;

	decrypted_data = (uint8_t *) memory_allocate(
	                              sizeof( uint8_t ) * decrypted_data_size );

	if( decrypted_data == NULL )
	{
		fprintf(
		 stderr,
		 "Unable to create decrypted data buffer.\n" );

		goto on_error;
	}
	/* Position the source file at the right offset
	 */
	if( libcfile_file_seek_offset(
	     source_file,
	     source_offset,
	     SEEK_SET,
	     &error ) == -1 )
	{
		fprintf(
		 stderr,
		 "Unable to seek offset in source file.\n" );

		goto on_error;
	}
	if( libfcrypto_rc4_context_initialize(
	     &context,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to create RC4 context.\n" );

		goto on_error;
	}
	fprintf(
	 stdout,
	 "Starting RC4 decrypting data of: %" PRIs_SYSTEM " at offset: %" PRIjd " (0x%08" PRIjx ").\n",
	 source,
	 source_offset,
	 source_offset );

	read_count = libcfile_file_read_buffer(
		      source_file,
		      buffer,
		      source_size,
	              &error );

	if( read_count != (ssize_t) source_size )
	{
		fprintf(
		 stderr,
		 "Unable to read from source file.\n" );

		goto on_error;
	}
	/* Decrypts the data
	 */
	if( rc4crypt_set_keys(
	     option_keys,
	     &key_data,
	     &key_data_size,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to retrieve key data from argument.\n" );

		goto on_error;
	}
	if( libfcrypto_rc4_context_set_key(
	     context,
	     key_data,
	     key_data_size * 8,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to set key in context.\n" );

		goto on_error;
	}
	if( memory_set(
	     key_data,
	     0,
	     key_data_size ) == NULL )
	{
		fprintf(
		 stderr,
		 "Unable to clear key data.\n" );

		goto on_error;
	}
	memory_free(
	 key_data );

	key_data = NULL;

	if( option_target_path == NULL )
	{
		fprintf(
		 stderr,
		 "Encrypted data:\n" );

		libcnotify_print_data(
		 buffer,
		 source_size,
		 0 );
	}
	if( libfcrypto_rc4_crypt(
	     context,
	     buffer,
	     source_size,
	     decrypted_data,
	     decrypted_data_size,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to decode data.\n" );

		goto on_error;
	}
	if( option_target_path == NULL )
	{
		fprintf(
		 stderr,
		 "Decrypted data:\n" );

		libcnotify_print_data(
		 decrypted_data,
		 decrypted_data_size,
		 0 );
	}
	else
	{
		if( libcfile_file_initialize(
		     &destination_file,
		     &error ) != 1 )
		{
			fprintf(
			 stderr,
			 "Unable to create destination file.\n" );

			goto on_error;
		}
		if( libcfile_file_open(
		     destination_file,
		     option_target_path,
		     LIBCFILE_OPEN_WRITE,
		     &error ) != 1 )
		{
			fprintf(
			 stderr,
			 "Unable to open destination file.\n" );

			goto on_error;
		}
		write_count = libcfile_file_write_buffer(
			       destination_file,
			       decrypted_data,
			       decrypted_data_size,
			       &error );

		if( write_count != (ssize_t) decrypted_data_size )
		{
			fprintf(
			 stderr,
			 "Unable to write to destination file.\n" );

			goto on_error;
		}
		if( libcfile_file_close(
		     destination_file,
		     &error ) != 0 )
		{
			fprintf(
			 stderr,
			 "Unable to close destination file.\n" );

			goto on_error;
		}
		if( libcfile_file_free(
		     &destination_file,
		     &error ) != 1 )
		{
			fprintf(
			 stderr,
			 "Unable to free destination file.\n" );

			goto on_error;
		}
	}
	/* Clean up
	 */
	if( libfcrypto_rc4_context_free(
	     &context,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to free RC4 context.\n" );

		goto on_error;
	}
	if( libcfile_file_close(
	     source_file,
	     &error ) != 0 )
	{
		fprintf(
		 stderr,
		 "Unable to close source file.\n" );

		goto on_error;
	}
	if( libcfile_file_free(
	     &source_file,
	     &error ) != 1 )
	{
		fprintf(
		 stderr,
		 "Unable to free source file.\n" );

		goto on_error;
	}
	if( decrypted_data != NULL )
	{
		memory_free(
		 decrypted_data );
	}
	if( buffer != NULL )
	{
		memory_free(
		 buffer );
	}
	fprintf(
	 stdout,
	 "RC4 decryption:\tSUCCESS\n" );

	return( EXIT_SUCCESS );

on_error:
	if( error != NULL )
	{
		libcnotify_print_error_backtrace(
		 error );
		libcerror_error_free(
		 &error );
	}
	if( destination_file != NULL )
	{
		libcfile_file_free(
		 &destination_file,
		 NULL );
	}
	if( decrypted_data != NULL )
	{
		memory_free(
		 decrypted_data );
	}
	if( key_data != NULL )
	{
		memory_set(
		 key_data,
		 0,
		 key_data_size );

		memory_free(
		 key_data );
	}
	if( context != NULL )
	{
		libfcrypto_rc4_context_free(
		 &context,
		 NULL );
	}
	if( buffer != NULL )
	{
		memory_free(
		 buffer );
	}
	if( source_file != NULL )
	{
		libcfile_file_free(
		 &source_file,
		 NULL );
	}
	fprintf(
	 stdout,
	 "RC4 decryption:\tFAILURE\n" );

	return( EXIT_FAILURE );
}
Beispiel #25
0
/* Opens a file for reading
 * Returns 1 if successful or -1 on error
 */
int libevtx_file_open_read(
     libevtx_internal_file_t *internal_file,
     libbfio_handle_t *file_io_handle,
     libcerror_error_t **error )
{
	libevtx_chunk_t *chunk                 = NULL;
	libevtx_record_values_t *record_values = NULL;
	libevtx_chunks_table_t *chunks_table   = NULL;
	static char *function                  = "libevtx_file_open_read";
	off64_t file_offset                    = 0;
	size64_t file_size                     = 0;
	uint16_t chunk_index                   = 0;
	uint16_t number_of_chunks              = 0;
	uint16_t number_of_records             = 0;
	uint16_t record_index                  = 0;
	int element_index                      = 0;
	int result                             = 0;
	int segment_index                      = 0;

#if defined( HAVE_VERBOSE_OUTPUT )
	uint64_t previous_record_identifier    = 0;
#endif
#if defined( HAVE_DEBUG_OUTPUT )
	uint8_t *trailing_data                 = NULL;
	size_t trailing_data_size              = 0;
	ssize_t read_count                     = 0;
#endif

	if( internal_file == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid file.",
		 function );

		return( -1 );
	}
	if( internal_file->io_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: invalid file - missing IO handle.",
		 function );

		return( -1 );
	}
	if( internal_file->chunks_vector != NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
		 "%s: invalid file - chunks vector already set.",
		 function );

		return( -1 );
	}
	if( internal_file->chunks_cache != NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
		 "%s: invalid file - chunks cache already set.",
		 function );

		return( -1 );
	}
	if( internal_file->records_list != NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
		 "%s: invalid file - records list already set.",
		 function );

		return( -1 );
	}
	if( internal_file->recovered_records_list != NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
		 "%s: invalid file - recovered records list already set.",
		 function );

		return( -1 );
	}
	if( internal_file->records_cache != NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
		 "%s: invalid file - records cache already set.",
		 function );

		return( -1 );
	}
	if( libbfio_handle_get_size(
	     file_io_handle,
	     &file_size,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve file size.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "Reading file header:\n" );
	}
#endif
	if( libevtx_io_handle_read_file_header(
	     internal_file->io_handle,
	     file_io_handle,
	     0,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read file header.",
		 function );

		goto on_error;
	}
	internal_file->io_handle->chunks_data_size = file_size
	                                           - internal_file->io_handle->chunks_data_offset;

/* TODO clone function ? */
	if( libfdata_vector_initialize(
	     &( internal_file->chunks_vector ),
	     (size64_t) internal_file->io_handle->chunk_size,
	     (intptr_t *) internal_file->io_handle,
	     NULL,
	     NULL,
	     (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfcache_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_io_handle_read_chunk,
	     NULL,
	     LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
		 "%s: unable to create chunks vector.",
		 function );

		goto on_error;
	}
	if( libfdata_vector_append_segment(
	     internal_file->chunks_vector,
	     &segment_index,
	     0,
	     internal_file->io_handle->chunks_data_offset,
	     internal_file->io_handle->chunks_data_size,
	     0,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
		 "%s: unable to append segment to chunks vector.",
		 function );

		goto on_error;
	}
	if( libfcache_cache_initialize(
	     &( internal_file->chunks_cache ),
	     LIBEVTX_MAXIMUM_CACHE_ENTRIES_CHUNKS,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
		 "%s: unable to create chunks cache.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "Reading chunks:\n" );
	}
#endif
	if( libevtx_chunks_table_initialize(
	     &chunks_table,
	     internal_file->io_handle,
	     internal_file->chunks_vector,
	     internal_file->chunks_cache,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
		 "%s: unable to create chunks table.",
		 function );

		goto on_error;
	}
/* TODO clone function ? */
	if( libfdata_list_initialize(
	     &( internal_file->records_list ),
	     (intptr_t *) chunks_table,
	     (int (*)(intptr_t **, libcerror_error_t **)) &libevtx_chunks_table_free,
	     NULL,
	     (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfcache_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_chunks_table_read_record,
	     NULL,
	     LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
		 "%s: unable to create records list.",
		 function );

		goto on_error;
	}
	/* The chunks_table is managed by the list */

	if( libfdata_list_initialize(
	     &( internal_file->recovered_records_list ),
	     (intptr_t *) chunks_table,
	     NULL,
	     NULL,
	     (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfcache_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_chunks_table_read_record,
	     NULL,
	     LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
		 "%s: unable to create recovered records list.",
		 function );

		chunks_table = NULL;

		goto on_error;
	}
	chunks_table = NULL;

	if( libfcache_cache_initialize(
	     &( internal_file->records_cache ),
	     LIBEVTX_MAXIMUM_CACHE_ENTRIES_RECORDS,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
		 "%s: unable to create records cache.",
		 function );

		goto on_error;
	}
	file_offset = internal_file->io_handle->chunks_data_offset;

	while( ( file_offset + internal_file->io_handle->chunk_size ) <= (off64_t) file_size )
	{
		if( libevtx_chunk_initialize(
		     &chunk,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create chunk: %" PRIu16 ".",
			 function,
			 chunk_index );

			goto on_error;
		}
		result = libevtx_chunk_read(
		          chunk,
		          internal_file->io_handle,
		          file_io_handle,
		          file_offset,
		          error );

		if( result == -1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_IO,
			 LIBCERROR_IO_ERROR_READ_FAILED,
			 "%s: unable to read chunk: %" PRIu16 ".",
			 function,
			 chunk_index );

			goto on_error;
		}
		else if( result == 0 )
		{
			if( chunk_index < internal_file->io_handle->number_of_chunks )
			{
#if defined( HAVE_VERBOSE_OUTPUT )
				if( libcnotify_verbose != 0 )
				{
					libcnotify_printf(
					 "%s: corruption detected in chunk: %" PRIu16 ".\n",
					 function,
					 chunk_index );
				}
#endif
				internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED;
			}
		}
		else
		{
			if( ( chunk->flags & LIBEVTX_CHUNK_FLAG_IS_CORRUPTED ) != 0 )
			{
#if defined( HAVE_VERBOSE_OUTPUT )
				if( libcnotify_verbose != 0 )
				{
					libcnotify_printf(
					 "%s: corruption detected in chunk: %" PRIu16 ".\n",
					 function,
					 chunk_index );
				}
#endif
				if( chunk_index < internal_file->io_handle->number_of_chunks )
				{
					internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED;
				}
			}
			if( ( chunk_index < internal_file->io_handle->number_of_chunks )
			 || ( ( chunk->flags & LIBEVTX_CHUNK_FLAG_IS_CORRUPTED ) == 0 ) )
			{
				number_of_chunks++;
			}
			if( libevtx_chunk_get_number_of_records(
			     chunk,
			     &number_of_records,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
				 "%s: unable to retrieve chunk: %" PRIu16 " number of records.",
				 function,
				 chunk_index );

				goto on_error;
			}
			for( record_index = 0;
			     record_index < number_of_records;
			     record_index++ )
			{
				if( libevtx_chunk_get_record(
				     chunk,
				     record_index,
				     &record_values,
				     error ) != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
					 "%s: unable to retrieve chunk: %" PRIu16 " record: %" PRIu16 ".",
					 function,
					 chunk_index,
					 record_index );

					goto on_error;
				}
				if( record_values == NULL )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
					 "%s: missing chunk: %" PRIu16 " record: %" PRIu16 ".",
					 function,
					 chunk_index,
					 record_index );

					goto on_error;
				}
				if( record_values->identifier < internal_file->io_handle->first_record_identifier )
				{
					internal_file->io_handle->first_record_identifier = record_values->identifier;
				}
				if( record_values->identifier > internal_file->io_handle->last_record_identifier )
				{
					internal_file->io_handle->last_record_identifier = record_values->identifier;
				}
#if defined( HAVE_VERBOSE_OUTPUT )
				if( ( chunk_index == 0 )
				 && ( record_index == 0 ) )
				{
					previous_record_identifier = record_values->identifier;
				}
				else
				{
					previous_record_identifier++;

					if( record_values->identifier != previous_record_identifier )
					{
						if( libcnotify_verbose != 0 )
						{
							libcnotify_printf(
							 "%s: detected gap in record identifier ( %" PRIu64 " != %" PRIu64 " ).\n",
							 function,
							 previous_record_identifier,
							 record_values->identifier );
						}
						previous_record_identifier = record_values->identifier;
					}
				}
#endif
				/* The chunk index is stored in the element data size
				 */
				if( ( chunk_index < internal_file->io_handle->number_of_chunks )
				 || ( ( internal_file->io_handle->file_flags & LIBEVTX_FILE_FLAG_IS_DIRTY ) != 0 ) )
				{
					if( libfdata_list_append_element(
					     internal_file->records_list,
					     &element_index,
					     0,
					     file_offset + record_values->chunk_data_offset,
					     (size64_t) chunk_index,
					     0,
					     error ) != 1 )
					{
						libcerror_error_set(
						 error,
						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
						 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
						 "%s: unable to append element to records list.",
						 function );

						goto on_error;
					}
				}
				else
				{
					/* If the file is not dirty, records found in chunks outside the indicated
					 * range are considered recovered
					 */
					if( libfdata_list_append_element(
					     internal_file->recovered_records_list,
					     &element_index,
					     0,
					     file_offset + record_values->chunk_data_offset,
					     (size64_t) chunk_index,
					     0,
					     error ) != 1 )
					{
						libcerror_error_set(
						 error,
						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
						 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
						 "%s: unable to append element to recovered records list.",
						 function );

						goto on_error;
					}
				}
/* TODO cache record values ? */
			}
			if( libevtx_chunk_get_number_of_recovered_records(
			     chunk,
			     &number_of_records,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
				 "%s: unable to retrieve chunk: %" PRIu16 " number of recovered records.",
				 function,
				 chunk_index );

				goto on_error;
			}
			for( record_index = 0;
			     record_index < number_of_records;
			     record_index++ )
			{
				if( libevtx_chunk_get_recovered_record(
				     chunk,
				     record_index,
				     &record_values,
				     error ) != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
					 "%s: unable to retrieve chunk: %" PRIu16 " recovered record: %" PRIu16 ".",
					 function,
					 chunk_index,
					 record_index );

					goto on_error;
				}
				if( record_values == NULL )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
					 "%s: missing chunk: %" PRIu16 " recovered record: %" PRIu16 ".",
					 function,
					 chunk_index,
					 record_index );

					goto on_error;
				}
/* TODO check for and remove duplicate identifiers ? */
				/* The chunk index is stored in the element data size
				 */
				if( libfdata_list_append_element(
				     internal_file->recovered_records_list,
				     &element_index,
				     0,
				     file_offset + record_values->chunk_data_offset,
				     (size64_t) chunk_index,
				     0,
				     error ) != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
					 "%s: unable to append element to recovered records list.",
					 function );

					goto on_error;
				}
			}
		}
		file_offset += chunk->data_size;

		if( libevtx_chunk_free(
		     &chunk,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
			 "%s: unable to free chunk: %" PRIu16 ".",
			 function,
			 chunk_index );

			goto on_error;
		}
		chunk_index++;
	}
	internal_file->io_handle->chunks_data_size = file_offset
	                                           - internal_file->io_handle->chunks_data_offset;

	if( number_of_chunks != internal_file->io_handle->number_of_chunks )
	{
#if defined( HAVE_VERBOSE_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: mismatch in number of chunks ( %" PRIu16 " != %" PRIu16 " ).\n",
			 function,
			 internal_file->io_handle->number_of_chunks,
			 chunk_index );
		}
#endif
		internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		if( file_offset < (off64_t) file_size )
		{
			trailing_data_size = (size_t) ( file_size - file_offset );

			trailing_data = (uint8_t *) memory_allocate(
			                             sizeof( uint8_t ) * trailing_data_size );

			if( trailing_data == NULL )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_MEMORY,
				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
				 "%s: unable to create trailing data.",
				 function );

				goto on_error;
			}
			read_count = libbfio_handle_read_buffer(
				      file_io_handle,
				      trailing_data,
				      trailing_data_size,
				      error );

			if( read_count != (ssize_t) trailing_data_size )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_IO,
				 LIBCERROR_IO_ERROR_READ_FAILED,
				 "%s: unable to read trailing data.",
				 function );

				memory_free(
				 trailing_data );

				goto on_error;
			}
			file_offset += read_count;

			libcnotify_printf(
			 "%s: trailing data:\n",
			 function );
			libcnotify_print_data(
			 trailing_data,
			 trailing_data_size,
			 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );

			memory_free(
			 trailing_data );

			trailing_data = NULL;
		}
	}
#endif
	return( 1 );

on_error:
#if defined( HAVE_DEBUG_OUTPUT )
	if( trailing_data != NULL )
	{
		memory_free(
		 trailing_data );
	}
#endif
	if( chunk != NULL )
	{
		libevtx_chunk_free(
		 &chunk,
		 NULL );
	}
	if( internal_file->records_cache != NULL )
	{
		libfcache_cache_free(
		 &( internal_file->records_cache ),
		 NULL );
	}
	if( internal_file->records_list != NULL )
	{
		libfdata_list_free(
		 &( internal_file->records_list ),
		 NULL );
	}
	if( chunks_table != NULL )
	{
		libevtx_chunks_table_free(
		 &chunks_table,
		 NULL );
	}
	if( internal_file->chunks_cache != NULL )
	{
		libfcache_cache_free(
		 &( internal_file->chunks_cache ),
		 NULL );
	}
	if( internal_file->chunks_vector != NULL )
	{
		libfdata_vector_free(
		 &( internal_file->chunks_vector ),
		 NULL );
	}
	return( -1 );
}
Beispiel #26
0
/* Reads a data block header
 * Returns 1 if successful, 0 if no data block signature was found or -1 on error
 */
int libcreg_data_block_read_header(
     libcreg_data_block_t *data_block,
     libbfio_handle_t *file_io_handle,
     libcerror_error_t **error )
{
	creg_data_block_header_t data_block_header;

	static char *function = "libcreg_data_block_read_header";
	ssize_t read_count    = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	uint16_t value_16bit  = 0;
#endif

	if( data_block == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid data block.",
		 function );

		return( -1 );
	}
	if( libbfio_handle_get_offset(
	     file_io_handle,
	     &( data_block->offset ),
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve file offset.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: reading data block header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
		 function,
		 data_block->offset,
		 data_block->offset );
	}
#endif
	read_count = libbfio_handle_read_buffer(
	              file_io_handle,
	              (uint8_t *) &data_block_header,
	              sizeof( creg_data_block_header_t ),
	              error );

	if( read_count != (ssize_t) sizeof( creg_data_block_header_t ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read data block header data.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: data block header:\n",
		 function );
		libcnotify_print_data(
		 (uint8_t *) &data_block_header,
		 sizeof( creg_data_block_header_t ),
		 0 );
	}
#endif
	if( memory_compare(
	     data_block_header.signature,
	     creg_data_block_signature,
	     4 ) != 0 )
	{
		return( 0 );
	}
	byte_stream_copy_to_uint32_little_endian(
	 data_block_header.size,
	 data_block->size );

	byte_stream_copy_to_uint32_little_endian(
	 data_block_header.unused_size,
	 data_block->unused_size );

	byte_stream_copy_to_uint32_little_endian(
	 data_block_header.used_size,
	 data_block->used_size );

#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: signature\t\t\t\t: %c%c%c%c\n",
		 function,
		 data_block_header.signature[ 0 ],
		 data_block_header.signature[ 1 ],
		 data_block_header.signature[ 2 ],
		 data_block_header.signature[ 3 ] );

		libcnotify_printf(
		 "%s: size\t\t\t\t\t: %" PRIu32 "\n",
		 function,
		 data_block->size );

		libcnotify_printf(
		 "%s: unused size\t\t\t\t: %" PRIu32 "\n",
		 function,
		 data_block->unused_size );

		byte_stream_copy_to_uint16_little_endian(
		 data_block_header.unknown1,
		 value_16bit );
		libcnotify_printf(
		 "%s: unknown1\t\t\t\t: 0x%04" PRIx16 "\n",
		 function,
		 value_16bit );

		byte_stream_copy_to_uint16_little_endian(
		 data_block_header.index,
		 value_16bit );
		libcnotify_printf(
		 "%s: index\t\t\t\t\t: %" PRIu16 "\n",
		 function,
		 value_16bit );

		libcnotify_printf(
		 "%s: used size\t\t\t\t: %" PRIi32 "\n",
		 function,
		 (int32_t) data_block->used_size );

		byte_stream_copy_to_uint16_little_endian(
		 data_block_header.unknown2,
		 value_16bit );
		libcnotify_printf(
		 "%s: unknown2\t\t\t\t: %" PRIu16 "\n",
		 function,
		 value_16bit );

		byte_stream_copy_to_uint16_little_endian(
		 data_block_header.unknown3,
		 value_16bit );
		libcnotify_printf(
		 "%s: unknown3\t\t\t\t: %" PRIu16 "\n",
		 function,
		 value_16bit );

		libcnotify_printf(
		 "%s: unknown3:\n",
		 function );
		libcnotify_print_data(
		 data_block_header.unknown4,
		 8,
		 0 );

		libcnotify_printf(
		 "\n" );
	}
#endif
/* TODO check if unused_size + used_size == size */
	return( 1 );
}
/* Unwrap data using AES Key Wrap (RFC3394)
 * Returns 1 if successful or -1 on error
 */
int libfvde_encryption_aes_key_unwrap(
     const uint8_t *key,
     size_t key_bit_size,
     const uint8_t *wrapped_data,
     size_t wrapped_data_size,
     uint8_t *unwrapped_data,
     size_t unwrapped_data_size,
     libcerror_error_t **error )
{
	uint8_t block_data[ 16 ];
	uint8_t vector_data[ 8 ];

	libcaes_context_t *aes_context = NULL;
	uint8_t *initialization_vector = NULL;
	static char *function          = "libfvde_encryption_aes_key_unwrap";
	size_t block_offset            = 0;
	size_t number_of_blocks        = 0;
	size_t block_index             = 0;
	int8_t round_index             = 0;

	if( key == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid AES key.",
		 function);

		return( -1 );
	}
	if( ( key_bit_size != 128 )
	 && ( key_bit_size != 192 )
	 && ( key_bit_size != 256 ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: invalid AES key length value out of bounds.",
		 function);

		return( -1 );
	}
	if( wrapped_data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid wrapped data.",
		 function);

		return( -1 );
	}
	if( wrapped_data_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid wrapped data size value exceeds maximum.",
		 function );

		return( -1 );
	}
	if( wrapped_data_size <= 8 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
		 "%s: invalid wrapped data size value too small.",
		 function);

		return( -1 );
	}
	if( ( wrapped_data_size % 8 ) != 0 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: invalid wrapped data size value not a multitude of 8.",
		 function);

		return( -1 );
	}
	if( unwrapped_data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid unwrapped data.",
		 function);

		return( -1 );
	}
	if( unwrapped_data_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid unwrapped data size value exceeds maximum.",
		 function );

		return( -1 );
	}
	if( unwrapped_data_size < wrapped_data_size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
		 "%s: invalid unwrapped data size value too small.",
		 function);

		return( -1 );
	}
	if( libcaes_context_initialize(
	     &aes_context,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
		 "%s: unable to initialize AES context.",
		 function );

		goto on_error;
	}
	if( libcaes_crypt_set_key(
	     aes_context,
	     LIBCAES_CRYPT_MODE_DECRYPT,
	     key,
	     key_bit_size,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
		 "%s: unable to set key in AES context.",
		 function );

		goto on_error;
	}
	if( memory_copy(
	     unwrapped_data,
	     wrapped_data,
	     wrapped_data_size ) == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
		 "%s: unable to copy wrapped data.",
		 function );

		goto on_error;
	}
	number_of_blocks = wrapped_data_size / 8;

#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: number of blocks: %" PRIzd "\n",
		 function,
		 number_of_blocks );

		libcnotify_printf(
		 "%s: wrapped data:\n",
		 function );
		libcnotify_print_data(
		 wrapped_data,
		 wrapped_data_size,
		 0 );
	}
#endif
/* TODO make this code more readable */
	initialization_vector = unwrapped_data;

	for( round_index = 5;
	     round_index >= 0;
	     round_index-- )
	{
		for( block_index = number_of_blocks - 1;
		     block_index > 0;
		     block_index-- )
		{
			block_offset = block_index * 8;

			byte_stream_copy_from_uint64_big_endian(
			 vector_data,
			 (uint64_t) ( round_index * ( number_of_blocks - 1 ) + block_index ) );

			vector_data[ 0 ] ^= initialization_vector[ 0 ];
			vector_data[ 1 ] ^= initialization_vector[ 1 ];
			vector_data[ 2 ] ^= initialization_vector[ 2 ];
			vector_data[ 3 ] ^= initialization_vector[ 3 ];
			vector_data[ 4 ] ^= initialization_vector[ 4 ];
			vector_data[ 5 ] ^= initialization_vector[ 5 ];
			vector_data[ 6 ] ^= initialization_vector[ 6 ];
			vector_data[ 7 ] ^= initialization_vector[ 7 ];

			if( memory_copy(
			     &( block_data[ 0 ] ),
			     vector_data,
			     8 ) == NULL )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_MEMORY,
				 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
				 "%s: unable to copy vector data to block data.",
				 function );

				goto on_error;
			}
			if( memory_copy(
			     &( block_data[ 8 ] ),
			     &( unwrapped_data[ block_offset ] ),
			     8 ) == NULL )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_MEMORY,
				 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
				 "%s: unable to copy unwrapped data to block data.",
				 function );

				goto on_error;
			}
			if( libcaes_crypt_ecb(
			     aes_context,
			     LIBCAES_CRYPT_MODE_DECRYPT,
			     block_data,
			     16,
			     block_data,
			     16,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
				 LIBCERROR_ENCRYPTION_ERROR_DECRYPT_FAILED,
				 "%s: unable to decrypt block data.",
				 function );

				goto on_error;
			}
			if( memory_copy(
			     initialization_vector,
			     &( block_data[ 0 ] ),
			     8 ) == NULL )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_MEMORY,
				 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
				 "%s: unable to decrypted block data to initialization vector.",
				 function );

				goto on_error;
			}
			if( memory_copy(
			     &( unwrapped_data[ block_offset ] ),
			     &( block_data[ 8 ] ),
			     8 ) == NULL )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_MEMORY,
				 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
				 "%s: unable to copy decrypted block data to unwrapped data.",
				 function );

				goto on_error;
			}
		}
	}
	if( libcaes_context_free(
	     &aes_context,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
		 "%s: unable to free AES context.",
		 function );

		goto on_error;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: unwrapped data:\n",
		 function );
		libcnotify_print_data(
		 unwrapped_data,
		 wrapped_data_size,
		 0 );
	}
#endif
	return( 1 );

on_error:
	if( aes_context != NULL )
	{
		libcaes_context_free(
		 &aes_context,
		 NULL);
	}
	return( -1 );
}
Beispiel #28
0
/* Reads a data block and determines its entries
 * Returns 1 if successful or -1 on error
 */
int libcreg_data_block_read_entries(
     libcreg_data_block_t *data_block,
     libbfio_handle_t *file_io_handle,
     int (*read_entry_size_function)(
            const uint8_t *data,
            size_t data_size,
            size_t *entry_size,
            libcerror_error_t **error ),
     int ascii_codepage,
     uint8_t have_debug_output LIBCREG_ATTRIBUTE_UNUSED,
     libcerror_error_t **error )
{
	libcreg_data_block_entry_t *data_block_entry = NULL;
	uint8_t *data_block_entry_data               = NULL;
	static char *function                        = "libcreg_data_block_read_entries";
	size_t data_block_data_size                  = 0;
	size_t data_block_entry_offset               = 0;
	ssize_t read_count                           = 0;
	int entry_index                              = 0;
	int data_block_entry_index                   = 0;

#if defined( HAVE_DEBUG_OUTPUT )
	libcreg_key_name_entry_t *key_name_entry     = NULL;
#else
	LIBCREG_UNREFERENCED_PARAMETER( have_debug_output );
#endif

	if( data_block == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid data block.",
		 function );

		return( -1 );
	}
	if( data_block->data != NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
		 "%s: invalid data block - data already set.",
		 function );

		return( -1 );
	}
#if SIZEOF_SIZE_T <= 4
	if( data_block->size > (size_t) SSIZE_MAX )
#else
	if( data_block->size > (uint32_t) SSIZE_MAX )
#endif
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid data block - size value exceeds maximum.",
		 function );

		return( -1 );
	}
	if( read_entry_size_function == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid read entry size function.",
		 function );

		return( -1 );
	}
	data_block->data_size = (size_t) data_block->size - sizeof( creg_data_block_header_t );

	data_block->data = (uint8_t *) memory_allocate(
	                                sizeof( uint8_t ) * data_block->data_size );
	
	if( data_block->data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
		 "%s: unable to create data block data.",
		 function );

		goto on_error;
	}
	read_count = libbfio_handle_read_buffer(
	              file_io_handle,
	              data_block->data,
	              data_block->data_size,
	              error );

	if( read_count != (ssize_t) data_block->data_size )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_READ_FAILED,
		 "%s: unable to read data block data.",
		 function );

		goto on_error;
	}
	data_block_entry_data = data_block->data;

	if( (int32_t) data_block->used_size < 0 )
	{
		data_block_data_size = data_block->data_size;
	}
	else
	{
		data_block_data_size = (size_t) data_block->used_size - sizeof( creg_data_block_header_t );
	}
	while( data_block_entry_offset < data_block_data_size )
	{
		if( libcreg_data_block_entry_initialize(
		     &data_block_entry,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create data block entry.",
			 function );

			goto on_error;
		}
		if( read_entry_size_function(
		     &( data_block_entry_data[ data_block_entry_offset ] ),
		     data_block->data_size - data_block_entry_offset,
		     &( data_block_entry->size ),
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve data block entry size.",
			 function );

			goto on_error;
		}
#if defined( HAVE_DEBUG_OUTPUT )
		if( libcnotify_verbose != 0 )
		{
			libcnotify_printf(
			 "%s: data block entry: %03d offset\t\t: %" PRIzd "\n",
			 function,
			 data_block_entry_index,
			 data_block_entry_offset );

			libcnotify_printf(
			 "%s: data block entry: %03d size\t\t: %" PRIzd "\n",
			 function,
			 data_block_entry_index,
			 data_block_entry->size );
		}
#endif
		data_block_entry->offset = data_block_entry_offset;

#if defined( HAVE_DEBUG_OUTPUT )
		if( ( libcnotify_verbose != 0 )
		 && ( have_debug_output != 0 ) )
		{
			if( libcreg_key_name_entry_initialize(
			     &key_name_entry,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
				 "%s: unable to create key name entry.",
				 function );

				goto on_error;
			}
			if( libcreg_key_name_entry_read_data(
			     key_name_entry,
			     &( ( data_block->data )[ data_block_entry->offset ] ),
			     data_block_entry->size,
			     ascii_codepage,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_IO,
				 LIBCERROR_IO_ERROR_READ_FAILED,
				 "%s: unable to read key name entry: %d.",
				 function,
				 data_block_entry_index );

				goto on_error;
			}
			if( libcreg_key_name_entry_free(
			     &key_name_entry,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
				 "%s: unable to free key name entry.",
				 function );

				goto on_error;
			}
		}
#endif
		data_block_entry_offset += (size_t) data_block_entry->size;

		if( libcdata_array_append_entry(
		     data_block->entries_array,
		     &entry_index,
		     (intptr_t *) data_block_entry,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
			 "%s: unable to append data block entry: %d.",
			 function,
			 data_block_entry_index );

			goto on_error;
		}
		data_block_entry = NULL;

		data_block_entry_index++;
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( ( libcnotify_verbose != 0 )
	 && ( have_debug_output != 0 ) )
	{
		if( data_block_entry_offset < data_block->data_size )
		{
			libcnotify_printf(
			 "%s: trailing data:\n",
			 function );
			libcnotify_print_data(
			 &( ( data_block->data )[ data_block_entry_offset ] ),
			 data_block->data_size - data_block_entry_offset,
			 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
		}
		else
		{
			libcnotify_printf(
			 "\n" );
		}
	}
#endif
	return( 1 );

on_error:
#if defined( HAVE_DEBUG_OUTPUT )
	if( key_name_entry != NULL )
	{
		libcreg_key_name_entry_free(
		 &key_name_entry,
		 NULL );
	}
#endif
	if( data_block_entry != NULL )
	{
		libcreg_data_block_entry_free(
		 &data_block_entry,
		 NULL );
	}
	if( data_block->entries_array != NULL )
	{
		libcdata_array_clear(
		 data_block->entries_array,
		 (int (*)(intptr_t **, libcerror_error_t **)) &libcreg_data_block_entry_free,
		 NULL );
	}
	if( data_block->data != NULL )
	{
		memory_free(
		 data_block->data );

		data_block->data = NULL;
	}
	data_block->data_size = 0;

	return( -1 );
}
Beispiel #29
0
/* Reads the extent data
 * Returns 1 if successful or -1 on error
 */
int libfsext_extent_read_data(
     libfsext_extent_t *extent,
     const uint8_t *data,
     size_t data_size,
     libcerror_error_t **error )
{
	static char *function                = "libfsext_extent_read_data";
	uint32_t physical_block_number_upper = 0;
	uint16_t physical_block_number_lower = 0;

	if( extent == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid extent.",
		 function );

		return( -1 );
	}
	if( data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid data.",
		 function );

		return( -1 );
	}
	if( data_size < sizeof( fsext_extent_ext4_t ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
		 "%s: unsupported data size.",
		 function );

		return( -1 );
	}
	if( data_size > (size_t) SSIZE_MAX )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid data size value exceeds maximum.",
		 function );

		return( -1 );
	}
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: extent data:\n",
		 function );
		libcnotify_print_data(
		 data,
		 data_size,
		 0 );
	}
#endif
	byte_stream_copy_to_uint32_little_endian(
	 ( (fsext_extent_ext4_t *) data )->logical_block_number,
	 extent->logical_block_number );

	byte_stream_copy_to_uint16_little_endian(
	 ( (fsext_extent_ext4_t *) data )->number_of_blocks,
	 extent->number_of_blocks );

	byte_stream_copy_to_uint16_little_endian(
	 ( (fsext_extent_ext4_t *) data )->physical_block_number_upper,
	 physical_block_number_upper );

	byte_stream_copy_to_uint32_little_endian(
	 ( (fsext_extent_ext4_t *) data )->physical_block_number_lower,
	 physical_block_number_lower );

#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		libcnotify_printf(
		 "%s: logical block number\t\t\t\t: %" PRIu32 "\n",
		 function,
		 extent->logical_block_number );

		libcnotify_printf(
		 "%s: number of blocks\t\t\t\t: %" PRIu16 "\n",
		 function,
		 extent->number_of_blocks );

		libcnotify_printf(
		 "%s: physical block number (upper)\t\t: %" PRIu16 "\n",
		 function,
		 physical_block_number_upper );

		libcnotify_printf(
		 "%s: physical block number (lower)\t\t: %" PRIu32 "\n",
		 function,
		 physical_block_number_lower );

		libcnotify_printf(
		 "\n" );
	}
#endif /* defined( HAVE_DEBUG_OUTPUT ) */

	extent->physical_block_number = ( (uint64_t) physical_block_number_upper << 32 ) | physical_block_number_lower;

	return( 1 );
}
/* Reads the known folder location
 * Returns the number of bytes read if successful or -1 on error
 */
int liblnk_known_folder_location_read(
     liblnk_known_folder_location_t *known_folder_location,
     liblnk_data_block_t *data_block,
     libcerror_error_t **error )
{
	lnk_data_block_known_folder_location_t *known_folder_location_data = NULL;
	static char *function                                              = "liblnk_data_block_strings_read";

#if defined( HAVE_DEBUG_OUTPUT )
	libcstring_system_character_t guid_string[ 48 ];

	libfguid_identifier_t *guid                                        = NULL;
	int result                                                         = 0;
#endif

	if( known_folder_location == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid known folder location.",
		 function );

		return( -1 );
	}
	if( data_block == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid data block.",
		 function );

		return( -1 );
	}
	if( data_block->data == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
		 "%s: invalid data block - missing data.",
		 function );

		return( -1 );
	}
	if( data_block->data_size < sizeof( lnk_data_block_known_folder_location_t ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
		 "%s: invalid data block - data size too small.",
		 function );

		return( -1 );
	}
	known_folder_location_data = (lnk_data_block_known_folder_location_t *) data_block->data;

	if( memory_copy(
	     known_folder_location->folder_identifier,
	     known_folder_location_data->folder_identifier,
	     16 ) == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
		 "%s: unable to copy folder identifier.",
		 function );

		goto on_error;
	}
	byte_stream_copy_to_uint32_little_endian(
	 known_folder_location_data->first_child_segment_offset,
	 known_folder_location->first_child_segment_offset );

#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		if( libfguid_identifier_initialize(
		     &guid,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
			 "%s: unable to create GUID.",
			 function );

			goto on_error;
		}
		if( libfguid_identifier_copy_from_byte_stream(
		     guid,
		     known_folder_location->folder_identifier,
		     16,
		     LIBFGUID_ENDIAN_LITTLE,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
			 "%s: unable to copy byte stream to GUID.",
			 function );

			goto on_error;
		}
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
		result = libfguid_identifier_copy_to_utf16_string(
			  guid,
			  (uint16_t *) guid_string,
			  48,
			  LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
			  error );
#else
		result = libfguid_identifier_copy_to_utf8_string(
			  guid,
			  (uint8_t *) guid_string,
			  48,
			  LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
			  error );
#endif
		if( result != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
			 "%s: unable to copy GUID to string.",
			 function );

			goto on_error;
		}
		libcnotify_printf(
		 "%s: known folder identifier\t\t: %" PRIs_LIBCSTRING_SYSTEM "\n",
		 function,
		 guid_string );

		libcnotify_printf(
		 "%s: known folder name\t\t\t: %s\n",
		 function,
		 libfwsi_known_folder_identifier_get_name(
		  known_folder_location->folder_identifier ) );

		libcnotify_printf(
		 "%s: first child segment offset\t\t: %" PRIu32 "\n",
		 function,
		 known_folder_location->first_child_segment_offset );

		libcnotify_printf(
		 "\n" );

		if( libfguid_identifier_free(
		     &guid,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
			 "%s: unable to free GUID.",
			 function );

			goto on_error;
		}
	}
#endif
#if defined( HAVE_DEBUG_OUTPUT )
	if( libcnotify_verbose != 0 )
	{
		if( data_block->data_size > sizeof( lnk_data_block_known_folder_location_t ) )
		{
			libcnotify_printf(
			 "%s: trailing data:\n",
			 function );
			libcnotify_print_data(
			 &( data_block->data[ sizeof( lnk_data_block_known_folder_location_t ) ] ),
			 data_block->data_size - sizeof( lnk_data_block_known_folder_location_t ),
			 0 );
		}
	}
#endif
	return( 1 );

on_error:
#if defined( HAVE_DEBUG_OUTPUT )
	if( guid != NULL )
	{
		libfguid_identifier_free(
		 &guid,
		 NULL );
	}
#endif
	return( -1 );
}