1 /*
2  * Info handle
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 <file_stream.h>
24 #include <memory.h>
25 #include <narrow_string.h>
26 #include <system_string.h>
27 #include <types.h>
28 #include <wide_string.h>
29 
30 #include "evtinput.h"
31 #include "evttools_libcerror.h"
32 #include "evttools_libclocale.h"
33 #include "evttools_libevt.h"
34 #include "info_handle.h"
35 
36 #define INFO_HANDLE_NOTIFY_STREAM	stdout
37 
38 /* Creates an info handle
39  * Make sure the value info_handle is referencing, is set to NULL
40  * Returns 1 if successful or -1 on error
41  */
info_handle_initialize(info_handle_t ** info_handle,libcerror_error_t ** error)42 int info_handle_initialize(
43      info_handle_t **info_handle,
44      libcerror_error_t **error )
45 {
46 	static char *function = "info_handle_initialize";
47 
48 	if( info_handle == NULL )
49 	{
50 		libcerror_error_set(
51 		 error,
52 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
53 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
54 		 "%s: invalid info handle.",
55 		 function );
56 
57 		return( -1 );
58 	}
59 	if( *info_handle != NULL )
60 	{
61 		libcerror_error_set(
62 		 error,
63 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
64 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
65 		 "%s: invalid info handle value already set.",
66 		 function );
67 
68 		return( -1 );
69 	}
70 	*info_handle = memory_allocate_structure(
71 	                info_handle_t );
72 
73 	if( *info_handle == NULL )
74 	{
75 		libcerror_error_set(
76 		 error,
77 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
78 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
79 		 "%s: unable to create info handle.",
80 		 function );
81 
82 		goto on_error;
83 	}
84 	if( memory_set(
85 	     *info_handle,
86 	     0,
87 	     sizeof( info_handle_t ) ) == NULL )
88 	{
89 		libcerror_error_set(
90 		 error,
91 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
92 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
93 		 "%s: unable to clear info handle.",
94 		 function );
95 
96 		goto on_error;
97 	}
98 	if( libevt_file_initialize(
99 	     &( ( *info_handle )->input_file ),
100 	     error ) != 1 )
101 	{
102 		libcerror_error_set(
103 		 error,
104 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
105 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
106 		 "%s: unable to initialize input file.",
107 		 function );
108 
109 		goto on_error;
110 	}
111 	( *info_handle )->event_log_type = EVTTOOLS_EVENT_LOG_TYPE_UNKNOWN;
112 	( *info_handle )->ascii_codepage = LIBEVT_CODEPAGE_WINDOWS_1252;
113 	( *info_handle )->notify_stream  = INFO_HANDLE_NOTIFY_STREAM;
114 
115 	return( 1 );
116 
117 on_error:
118 	if( *info_handle != NULL )
119 	{
120 		memory_free(
121 		 *info_handle );
122 
123 		*info_handle = NULL;
124 	}
125 	return( -1 );
126 }
127 
128 /* Frees an info handle
129  * Returns 1 if successful or -1 on error
130  */
info_handle_free(info_handle_t ** info_handle,libcerror_error_t ** error)131 int info_handle_free(
132      info_handle_t **info_handle,
133      libcerror_error_t **error )
134 {
135 	static char *function = "info_handle_free";
136 	int result            = 1;
137 
138 	if( info_handle == NULL )
139 	{
140 		libcerror_error_set(
141 		 error,
142 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
143 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
144 		 "%s: invalid info handle.",
145 		 function );
146 
147 		return( -1 );
148 	}
149 	if( *info_handle != NULL )
150 	{
151 		if( libevt_file_free(
152 		     &( ( *info_handle )->input_file ),
153 		     error ) != 1 )
154 		{
155 			libcerror_error_set(
156 			 error,
157 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
158 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
159 			 "%s: unable to free input file.",
160 			 function );
161 
162 			result = -1;
163 		}
164 		memory_free(
165 		 *info_handle );
166 
167 		*info_handle = NULL;
168 	}
169 	return( result );
170 }
171 
172 /* Signals the info handle to abort
173  * Returns 1 if successful or -1 on error
174  */
info_handle_signal_abort(info_handle_t * info_handle,libcerror_error_t ** error)175 int info_handle_signal_abort(
176      info_handle_t *info_handle,
177      libcerror_error_t **error )
178 {
179 	static char *function = "info_handle_signal_abort";
180 
181 	if( info_handle == NULL )
182 	{
183 		libcerror_error_set(
184 		 error,
185 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
186 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
187 		 "%s: invalid info handle.",
188 		 function );
189 
190 		return( -1 );
191 	}
192 	info_handle->abort = 1;
193 
194 	if( info_handle->input_file != NULL )
195 	{
196 		if( libevt_file_signal_abort(
197 		     info_handle->input_file,
198 		     error ) != 1 )
199 		{
200 			libcerror_error_set(
201 			 error,
202 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
203 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
204 			 "%s: unable to signal input file to abort.",
205 			 function );
206 
207 			return( -1 );
208 		}
209 	}
210 	return( 1 );
211 }
212 
213 /* Sets the ascii codepage
214  * Returns 1 if successful or -1 on error
215  */
info_handle_set_ascii_codepage(info_handle_t * info_handle,const system_character_t * string,libcerror_error_t ** error)216 int info_handle_set_ascii_codepage(
217      info_handle_t *info_handle,
218      const system_character_t *string,
219      libcerror_error_t **error )
220 {
221 	static char *function  = "info_handle_set_ascii_codepage";
222 	size_t string_length   = 0;
223 	uint32_t feature_flags = 0;
224 	int result             = 0;
225 
226 	if( info_handle == NULL )
227 	{
228 		libcerror_error_set(
229 		 error,
230 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
231 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
232 		 "%s: invalid info handle.",
233 		 function );
234 
235 		return( -1 );
236 	}
237 	feature_flags = LIBCLOCALE_CODEPAGE_FEATURE_FLAG_HAVE_KOI8
238 	              | LIBCLOCALE_CODEPAGE_FEATURE_FLAG_HAVE_WINDOWS;
239 
240 	string_length = system_string_length(
241 	                 string );
242 
243 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
244 	result = libclocale_codepage_copy_from_string_wide(
245 	          &( info_handle->ascii_codepage ),
246 	          string,
247 	          string_length,
248 	          feature_flags,
249 	          error );
250 #else
251 	result = libclocale_codepage_copy_from_string(
252 	          &( info_handle->ascii_codepage ),
253 	          string,
254 	          string_length,
255 	          feature_flags,
256 	          error );
257 #endif
258 	if( result == -1 )
259 	{
260 		libcerror_error_set(
261 		 error,
262 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
263 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
264 		 "%s: unable to determine ASCII codepage.",
265 		 function );
266 
267 		return( -1 );
268 	}
269 	return( result );
270 }
271 
272 /* Sets the event log type from the filename
273  * Returns 1 if successful or -1 on error
274  */
info_handle_set_event_log_type_from_filename(info_handle_t * info_handle,const system_character_t * filename,libcerror_error_t ** error)275 int info_handle_set_event_log_type_from_filename(
276      info_handle_t *info_handle,
277      const system_character_t *filename,
278      libcerror_error_t **error )
279 {
280 	static char *function = "info_handle_set_event_log_type_from_filename";
281 	int result            = 0;
282 
283 	if( info_handle == NULL )
284 	{
285 		libcerror_error_set(
286 		 error,
287 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
288 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
289 		 "%s: invalid info handle.",
290 		 function );
291 
292 		return( -1 );
293 	}
294 	result = evtinput_determine_event_log_type_from_filename(
295 	          filename,
296 	          &( info_handle->event_log_type ),
297 	          error );
298 
299 	if( result == -1 )
300 	{
301 		libcerror_error_set(
302 		 error,
303 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
304 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
305 		 "%s: unable to determine event log type from filename.",
306 		 function );
307 
308 		return( -1 );
309 	}
310 	return( result );
311 }
312 
313 /* Opens the input
314  * Returns 1 if successful or -1 on error
315  */
info_handle_open_input(info_handle_t * info_handle,const system_character_t * filename,libcerror_error_t ** error)316 int info_handle_open_input(
317      info_handle_t *info_handle,
318      const system_character_t *filename,
319      libcerror_error_t **error )
320 {
321 	static char *function = "info_handle_open_input";
322 
323 	if( info_handle == NULL )
324 	{
325 		libcerror_error_set(
326 		 error,
327 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
328 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
329 		 "%s: invalid info handle.",
330 		 function );
331 
332 		return( -1 );
333 	}
334 	if( libevt_file_set_ascii_codepage(
335 	     info_handle->input_file,
336 	     info_handle->ascii_codepage,
337 	     error ) != 1 )
338 	{
339 		libcerror_error_set(
340 		 error,
341 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
342 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
343 		 "%s: unable to set ASCII codepage in input file.",
344 		 function );
345 
346 		return( -1 );
347 	}
348 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
349 	if( libevt_file_open_wide(
350 	     info_handle->input_file,
351 	     filename,
352 	     LIBEVT_OPEN_READ,
353 	     error ) != 1 )
354 #else
355 	if( libevt_file_open(
356 	     info_handle->input_file,
357 	     filename,
358 	     LIBEVT_OPEN_READ,
359 	     error ) != 1 )
360 #endif
361 	{
362 		libcerror_error_set(
363 		 error,
364 		 LIBCERROR_ERROR_DOMAIN_IO,
365 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
366 		 "%s: unable to open input file.",
367 		 function );
368 
369 		return( -1 );
370 	}
371 	return( 1 );
372 }
373 
374 /* Closes the input
375  * Returns the 0 if succesful or -1 on error
376  */
info_handle_close_input(info_handle_t * info_handle,libcerror_error_t ** error)377 int info_handle_close_input(
378      info_handle_t *info_handle,
379      libcerror_error_t **error )
380 {
381 	static char *function = "info_handle_close_input";
382 
383 	if( info_handle == NULL )
384 	{
385 		libcerror_error_set(
386 		 error,
387 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
388 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
389 		 "%s: invalid info handle.",
390 		 function );
391 
392 		return( -1 );
393 	}
394 	if( libevt_file_close(
395 	     info_handle->input_file,
396 	     error ) != 0 )
397 	{
398 		libcerror_error_set(
399 		 error,
400 		 LIBCERROR_ERROR_DOMAIN_IO,
401 		 LIBCERROR_IO_ERROR_CLOSE_FAILED,
402 		 "%s: unable to close input file.",
403 		 function );
404 
405 		return( -1 );
406 	}
407 	return( 0 );
408 }
409 
410 /* Prints the file information
411  * Returns 1 if successful or -1 on error
412  */
info_handle_file_fprint(info_handle_t * info_handle,libcerror_error_t ** error)413 int info_handle_file_fprint(
414      info_handle_t *info_handle,
415      libcerror_error_t **error )
416 {
417 	const system_character_t *event_log_type = NULL;
418 	static char *function                    = "info_handle_file_fprint";
419 	uint32_t flags                           = 0;
420 	uint32_t major_version                   = 0;
421 	uint32_t minor_version                   = 0;
422 	int is_corrupted                         = 0;
423 	int number_of_recovered_records          = 0;
424 	int number_of_records                    = 0;
425 
426 	if( info_handle == NULL )
427 	{
428 		libcerror_error_set(
429 		 error,
430 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
431 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
432 		 "%s: invalid info handle.",
433 		 function );
434 
435 		return( -1 );
436 	}
437 	if( libevt_file_get_format_version(
438 	     info_handle->input_file,
439 	     &major_version,
440 	     &minor_version,
441 	     error ) != 1 )
442 	{
443 		libcerror_error_set(
444 		 error,
445 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
446 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
447 		 "%s: unable to retrieve format version.",
448 		 function );
449 
450 		return( -1 );
451 	}
452 	if( libevt_file_get_flags(
453 	     info_handle->input_file,
454 	     &flags,
455 	     error ) != 1 )
456 	{
457 		libcerror_error_set(
458 		 error,
459 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
460 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
461 		 "%s: unable to retrieve flags.",
462 		 function );
463 
464 		return( -1 );
465 	}
466 	is_corrupted = libevt_file_is_corrupted(
467 	                info_handle->input_file,
468 	                error );
469 
470 	if( is_corrupted == -1 )
471 	{
472 		libcerror_error_set(
473 		 error,
474 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
475 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
476 		 "%s: unable to determine if file is corrupted.",
477 		 function );
478 
479 		return( -1 );
480 	}
481 	if( libevt_file_get_number_of_records(
482 	     info_handle->input_file,
483 	     &number_of_records,
484 	     error ) != 1 )
485 	{
486 		libcerror_error_set(
487 		 error,
488 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
489 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
490 		 "%s: unable to retrieve number of records.",
491 		 function );
492 
493 		return( -1 );
494 	}
495 	if( libevt_file_get_number_of_recovered_records(
496 	     info_handle->input_file,
497 	     &number_of_recovered_records,
498 	     error ) != 1 )
499 	{
500 		libcerror_error_set(
501 		 error,
502 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
503 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
504 		 "%s: unable to retrieve number of recovered records.",
505 		 function );
506 
507 		return( -1 );
508 	}
509 	fprintf(
510 	 info_handle->notify_stream,
511 	 "Windows Event Log (EVT) information:\n" );
512 
513 	fprintf(
514 	 info_handle->notify_stream,
515 	 "\tVersion\t\t\t\t: %" PRIu32 ".%" PRIu32 "\n",
516 	 major_version,
517 	 minor_version );
518 
519 	fprintf(
520 	 info_handle->notify_stream,
521 	 "\tNumber of records\t\t: %d\n",
522 	 number_of_records );
523 
524 	fprintf(
525 	 info_handle->notify_stream,
526 	 "\tNumber of recovered records\t: %d\n",
527 	 number_of_recovered_records );
528 
529 	switch( info_handle->event_log_type )
530 	{
531 		case EVTTOOLS_EVENT_LOG_TYPE_APPLICATION:
532 			event_log_type = _SYSTEM_STRING( "Application" );
533 			break;
534 
535 		case EVTTOOLS_EVENT_LOG_TYPE_INTERNET_EXPLORER:
536 			event_log_type = _SYSTEM_STRING( "Internet Explorer" );
537 			break;
538 
539 		case EVTTOOLS_EVENT_LOG_TYPE_SECURITY:
540 			event_log_type = _SYSTEM_STRING( "Security" );
541 			break;
542 
543 		case EVTTOOLS_EVENT_LOG_TYPE_SYSTEM:
544 			event_log_type = _SYSTEM_STRING( "System" );
545 			break;
546 	}
547 	if( event_log_type != NULL )
548 	{
549 		fprintf(
550 		 info_handle->notify_stream,
551 		 "\tLog type\t\t\t: %" PRIs_SYSTEM "\n",
552 		 event_log_type );
553 	}
554 	if( is_corrupted != 0 )
555 	{
556 		fprintf(
557 		 info_handle->notify_stream,
558 		 "\tIs corrupted\n" );
559 	}
560 	if( flags != 0 )
561 	{
562 		fprintf(
563 		 info_handle->notify_stream,
564 		 "\tFlags:\n" );
565 
566 		if( ( flags & LIBEVT_FILE_FLAG_IS_DIRTY ) != 0 )
567 		{
568 			fprintf(
569 			 info_handle->notify_stream,
570 			 "\t\tIs dirty\n" );
571 		}
572 		if( ( flags & LIBEVT_FILE_FLAG_HAS_WRAPPED ) != 0 )
573 		{
574 			fprintf(
575 			 info_handle->notify_stream,
576 			 "\t\tHas wrapped\n" );
577 		}
578 		if( ( flags & LIBEVT_FILE_FLAG_IS_FULL ) != 0 )
579 		{
580 			fprintf(
581 			 info_handle->notify_stream,
582 			 "\t\tIs full\n" );
583 		}
584 		if( ( flags & LIBEVT_FILE_FLAG_ARCHIVE ) != 0 )
585 		{
586 			fprintf(
587 			 info_handle->notify_stream,
588 			 "\t\tShould be archived\n" );
589 		}
590 	}
591 	fprintf(
592 	 info_handle->notify_stream,
593 	 "\n" );
594 
595 	return( 1 );
596 }
597 
598