1 /*
2  * LE header functions
3  *
4  * Copyright (C) 2011-2021, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <byte_stream.h>
24 #include <memory.h>
25 #include <types.h>
26 
27 #include "libexe_le_header.h"
28 #include "libexe_libcerror.h"
29 #include "libexe_libcnotify.h"
30 
31 #include "exe_le_header.h"
32 
33 /* Creates a LE header
34  * Make sure the value le_header is referencing, is set to NULL
35  * Returns 1 if successful or -1 on error
36  */
libexe_le_header_initialize(libexe_le_header_t ** le_header,libcerror_error_t ** error)37 int libexe_le_header_initialize(
38      libexe_le_header_t **le_header,
39      libcerror_error_t **error )
40 {
41 	static char *function = "libexe_le_header_initialize";
42 
43 	if( le_header == NULL )
44 	{
45 		libcerror_error_set(
46 		 error,
47 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
48 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
49 		 "%s: invalid LE header.",
50 		 function );
51 
52 		return( -1 );
53 	}
54 	if( *le_header != NULL )
55 	{
56 		libcerror_error_set(
57 		 error,
58 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
59 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
60 		 "%s: invalid LE header value already set.",
61 		 function );
62 
63 		return( -1 );
64 	}
65 	*le_header = memory_allocate_structure(
66 	              libexe_le_header_t );
67 
68 	if( *le_header == NULL )
69 	{
70 		libcerror_error_set(
71 		 error,
72 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
73 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
74 		 "%s: unable to create LE header.",
75 		 function );
76 
77 		goto on_error;
78 	}
79 	if( memory_set(
80 	     *le_header,
81 	     0,
82 	     sizeof( libexe_le_header_t ) ) == NULL )
83 	{
84 		libcerror_error_set(
85 		 error,
86 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
87 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
88 		 "%s: unable to clear file.",
89 		 function );
90 
91 		goto on_error;
92 	}
93 	return( 1 );
94 
95 on_error:
96 	if( *le_header != NULL )
97 	{
98 		memory_free(
99 		 *le_header );
100 
101 		*le_header = NULL;
102 	}
103 	return( -1 );
104 }
105 
106 /* Frees a LE header
107  * Returns 1 if successful or -1 on error
108  */
libexe_le_header_free(libexe_le_header_t ** le_header,libcerror_error_t ** error)109 int libexe_le_header_free(
110      libexe_le_header_t **le_header,
111      libcerror_error_t **error )
112 {
113 	static char *function = "libexe_le_header_free";
114 
115 	if( le_header == NULL )
116 	{
117 		libcerror_error_set(
118 		 error,
119 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
120 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
121 		 "%s: invalid LE header.",
122 		 function );
123 
124 		return( -1 );
125 	}
126 	if( *le_header != NULL )
127 	{
128 		memory_free(
129 		 *le_header );
130 
131 		*le_header = NULL;
132 	}
133 	return( 1 );
134 }
135 
136 /* Reads the LE header
137  * Returns 1 if successful or -1 on error
138  */
libexe_le_header_read_data(libexe_le_header_t * le_header,const uint8_t * data,size_t data_size,libcerror_error_t ** error)139 int libexe_le_header_read_data(
140      libexe_le_header_t *le_header,
141      const uint8_t *data,
142      size_t data_size,
143      libcerror_error_t **error )
144 {
145 	static char *function = "libexe_le_header_read_data";
146 
147 	if( le_header == NULL )
148 	{
149 		libcerror_error_set(
150 		 error,
151 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
152 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
153 		 "%s: invalid LE header.",
154 		 function );
155 
156 		return( -1 );
157 	}
158 	if( data == NULL )
159 	{
160 		libcerror_error_set(
161 		 error,
162 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
163 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
164 		 "%s: invalid data.",
165 		 function );
166 
167 		return( -1 );
168 	}
169 	if( data_size < sizeof( exe_le_header_t ) )
170 	{
171 		libcerror_error_set(
172 		 error,
173 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
174 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
175 		 "%s: invalid data size value too small.",
176 		 function );
177 
178 		return( -1 );
179 	}
180 	if( data_size > (size_t) SSIZE_MAX )
181 	{
182 		libcerror_error_set(
183 		 error,
184 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
185 		 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
186 		 "%s: invalid data size value exceeds maximum.",
187 		 function );
188 
189 		return( -1 );
190 	}
191 #if defined( HAVE_DEBUG_OUTPUT )
192 	if( libcnotify_verbose != 0 )
193 	{
194 		libcnotify_printf(
195 		 "%s: LE header:\n",
196 		 function );
197 		libcnotify_print_data(
198 		 data,
199 		 sizeof( exe_le_header_t ),
200 		 0 );
201 	}
202 #endif
203 	if( memory_compare(
204 	     ( (exe_le_header_t *) data )->signature,
205 	     EXE_LE_SIGNATURE,
206 	     2 ) != 0 )
207 	{
208 		libcerror_error_set(
209 		 error,
210 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
211 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
212 		 "%s: invalid signature.",
213 		 function );
214 
215 		return( -1 );
216 	}
217 #if defined( HAVE_DEBUG_OUTPUT )
218 	if( libcnotify_verbose != 0 )
219 	{
220 		libcnotify_printf(
221 		 "%s: signature\t\t\t\t: %c%c\n",
222 		 function,
223 		 ( (exe_le_header_t *) data )->signature[ 0 ],
224 		 ( (exe_le_header_t *) data )->signature[ 1 ] );
225 /* TODO */
226 
227 		libcnotify_printf(
228 		 "\n" );
229 	}
230 #endif
231 	return( 1 );
232 }
233 
234 /* Reads the LE header from a Basic File IO (bfio) handle
235  * Returns 1 if successful or -1 on error
236  */
libexe_le_header_read_file_io_handle(libexe_le_header_t * le_header,libbfio_handle_t * file_io_handle,off64_t file_offset,libcerror_error_t ** error)237 int libexe_le_header_read_file_io_handle(
238      libexe_le_header_t *le_header,
239      libbfio_handle_t *file_io_handle,
240      off64_t file_offset,
241      libcerror_error_t **error )
242 {
243 	uint8_t data[ sizeof( exe_le_header_t ) ];
244 
245 	static char *function = "libexe_le_header_read_file_io_handle";
246 	ssize_t read_count    = 0;
247 
248 #if defined( HAVE_DEBUG_OUTPUT )
249 	if( libcnotify_verbose != 0 )
250 	{
251 		libcnotify_printf(
252 		 "%s: reading LE header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
253 		 function,
254 		 file_offset,
255 		 file_offset );
256 	}
257 #endif
258 	read_count = libbfio_handle_read_buffer_at_offset(
259 	              file_io_handle,
260 	              data,
261 	              sizeof( exe_le_header_t ),
262 	              file_offset,
263 	              error );
264 
265 	if( read_count != (ssize_t) sizeof( exe_le_header_t ) )
266 	{
267 		libcerror_error_set(
268 		 error,
269 		 LIBCERROR_ERROR_DOMAIN_IO,
270 		 LIBCERROR_IO_ERROR_READ_FAILED,
271 		 "%s: unable to read LE header data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
272 		 function,
273 		 file_offset,
274 		 file_offset );
275 
276 		return( -1 );
277 	}
278 	if( libexe_le_header_read_data(
279 	     le_header,
280 	     data,
281 	     sizeof( exe_le_header_t ),
282 	     error ) != 1 )
283 	{
284 		libcerror_error_set(
285 		 error,
286 		 LIBCERROR_ERROR_DOMAIN_IO,
287 		 LIBCERROR_IO_ERROR_READ_FAILED,
288 		 "%s: unable to read LE header at offset: %" PRIi64 " (0x%08" PRIx64 ").",
289 		 function,
290 		 file_offset,
291 		 file_offset );
292 
293 		return( -1 );
294 	}
295 	return( 1 );
296 }
297 
298