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