1 /*
2  * Reparse point attribute ($REPARSE_POINT) functions
3  *
4  * Copyright (C) 2010-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 <narrow_string.h>
26 #include <system_string.h>
27 #include <types.h>
28 #include <wide_string.h>
29 
30 #include "libfsntfs_debug.h"
31 #include "libfsntfs_definitions.h"
32 #include "libfsntfs_libcerror.h"
33 #include "libfsntfs_libcnotify.h"
34 #include "libfsntfs_libuna.h"
35 #include "libfsntfs_mft_attribute.h"
36 #include "libfsntfs_reparse_point_values.h"
37 
38 #include "fsntfs_reparse_point.h"
39 
40 /* Creates reparse point values
41  * Make sure the value reparse_point_values is referencing, is set to NULL
42  * Returns 1 if successful or -1 on error
43  */
libfsntfs_reparse_point_values_initialize(libfsntfs_reparse_point_values_t ** reparse_point_values,libcerror_error_t ** error)44 int libfsntfs_reparse_point_values_initialize(
45      libfsntfs_reparse_point_values_t **reparse_point_values,
46      libcerror_error_t **error )
47 {
48 	static char *function = "libfsntfs_reparse_point_values_initialize";
49 
50 	if( reparse_point_values == NULL )
51 	{
52 		libcerror_error_set(
53 		 error,
54 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56 		 "%s: invalid reparse point values.",
57 		 function );
58 
59 		return( -1 );
60 	}
61 	if( *reparse_point_values != NULL )
62 	{
63 		libcerror_error_set(
64 		 error,
65 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
66 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67 		 "%s: invalid reparse point values value already set.",
68 		 function );
69 
70 		return( -1 );
71 	}
72 	*reparse_point_values = memory_allocate_structure(
73 	                         libfsntfs_reparse_point_values_t );
74 
75 	if( *reparse_point_values == NULL )
76 	{
77 		libcerror_error_set(
78 		 error,
79 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
80 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
81 		 "%s: unable to create reparse point values.",
82 		 function );
83 
84 		goto on_error;
85 	}
86 	if( memory_set(
87 	     *reparse_point_values,
88 	     0,
89 	     sizeof( libfsntfs_reparse_point_values_t ) ) == NULL )
90 	{
91 		libcerror_error_set(
92 		 error,
93 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
94 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
95 		 "%s: unable to clear reparse point values.",
96 		 function );
97 
98 		goto on_error;
99 	}
100 	return( 1 );
101 
102 on_error:
103 	if( *reparse_point_values != NULL )
104 	{
105 		memory_free(
106 		 *reparse_point_values );
107 
108 		*reparse_point_values = NULL;
109 	}
110 	return( -1 );
111 }
112 
113 /* Frees reparse point values
114  * Returns 1 if successful or -1 on error
115  */
libfsntfs_reparse_point_values_free(libfsntfs_reparse_point_values_t ** reparse_point_values,libcerror_error_t ** error)116 int libfsntfs_reparse_point_values_free(
117      libfsntfs_reparse_point_values_t **reparse_point_values,
118      libcerror_error_t **error )
119 {
120 	static char *function = "libfsntfs_reparse_point_values_free";
121 
122 	if( reparse_point_values == NULL )
123 	{
124 		libcerror_error_set(
125 		 error,
126 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
127 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
128 		 "%s: invalid reparse point values.",
129 		 function );
130 
131 		return( -1 );
132 	}
133 	if( *reparse_point_values != NULL )
134 	{
135 		if( ( *reparse_point_values )->reparse_data != NULL )
136 		{
137 			memory_free(
138 			 ( *reparse_point_values )->reparse_data );
139 		}
140 		memory_free(
141 		 *reparse_point_values );
142 
143 		*reparse_point_values = NULL;
144 	}
145 	return( 1 );
146 }
147 
148 /* Reads the reparse point values
149  * Returns 1 if successful or -1 on error
150  */
libfsntfs_reparse_point_values_read_data(libfsntfs_reparse_point_values_t * reparse_point_values,const uint8_t * data,size_t data_size,libcerror_error_t ** error)151 int libfsntfs_reparse_point_values_read_data(
152      libfsntfs_reparse_point_values_t *reparse_point_values,
153      const uint8_t *data,
154      size_t data_size,
155      libcerror_error_t **error )
156 {
157 	static char *function            = "libfsntfs_reparse_point_values_read_data";
158 	uint32_t flags                   = 0;
159 
160 #if defined( HAVE_DEBUG_OUTPUT )
161 	system_character_t *value_string = NULL;
162 	size_t value_string_size         = 0;
163 	uint32_t value_32bit             = 0;
164 	int result                       = 0;
165 #endif
166 
167 	if( reparse_point_values == NULL )
168 	{
169 		libcerror_error_set(
170 		 error,
171 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
172 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
173 		 "%s: invalid reparse point values.",
174 		 function );
175 
176 		return( -1 );
177 	}
178 	if( data == NULL )
179 	{
180 		libcerror_error_set(
181 		 error,
182 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
183 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
184 		 "%s: invalid data.",
185 		 function );
186 
187 		return( -1 );
188 	}
189 	if( data_size > (size_t) SSIZE_MAX )
190 	{
191 		libcerror_error_set(
192 		 error,
193 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
194 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
195 		 "%s: invalid data size value out of bounds.",
196 		 function );
197 
198 		return( -1 );
199 	}
200 #if defined( HAVE_DEBUG_OUTPUT )
201 	if( libcnotify_verbose != 0 )
202 	{
203 		libcnotify_printf(
204 		 "%s: reparse point data:\n",
205 		 function );
206 		libcnotify_print_data(
207 		 data,
208 		 data_size,
209 		 0 );
210 	}
211 #endif
212 	byte_stream_copy_to_uint32_little_endian(
213 	 ( (fsntfs_reparse_point_t *) data )->tag,
214 	 reparse_point_values->tag );
215 
216 	byte_stream_copy_to_uint16_little_endian(
217 	 ( (fsntfs_reparse_point_t *) data )->reparse_data_size,
218 	 reparse_point_values->reparse_data_size );
219 
220 #if defined( HAVE_DEBUG_OUTPUT )
221 	if( libcnotify_verbose != 0 )
222 	{
223 		libcnotify_printf(
224 		 "%s: tag\t\t\t\t: 0x%08" PRIx32 "\n",
225 		 function,
226 		 reparse_point_values->tag );
227 		libfsntfs_debug_print_reparse_point_tag(
228 		 reparse_point_values->tag );
229 		libcnotify_printf(
230 		 "\n" );
231 
232 		libcnotify_printf(
233 		 "%s: reparse data size\t\t: %" PRIu16 "\n",
234 		 function,
235 		 reparse_point_values->reparse_data_size );
236 
237 		libcnotify_printf(
238 		 "\n" );
239 	}
240 #endif
241 	if( reparse_point_values->reparse_data_size > 0 )
242 	{
243 		if( ( sizeof( fsntfs_reparse_point_t ) > data_size )
244 		 || ( (size_t) reparse_point_values->reparse_data_size > ( data_size - sizeof( fsntfs_reparse_point_t ) ) )
245 		 || ( (size_t) reparse_point_values->reparse_data_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
246 		{
247 			libcerror_error_set(
248 			 error,
249 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
250 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
251 			 "%s: invalid reparse data size value out of bounds.",
252 			 function );
253 
254 			goto on_error;
255 		}
256 		reparse_point_values->reparse_data = (uint8_t *) memory_allocate(
257 		                                                  sizeof( uint8_t ) * reparse_point_values->reparse_data_size );
258 
259 		if( reparse_point_values->reparse_data == NULL )
260 		{
261 			libcerror_error_set(
262 			 error,
263 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
264 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
265 			 "%s: unable to create reparse data.",
266 			 function );
267 
268 			goto on_error;
269 		}
270 		if( memory_copy(
271 		     reparse_point_values->reparse_data,
272 		     &( data[ sizeof( fsntfs_reparse_point_t ) ] ),
273 		     (size_t) reparse_point_values->reparse_data_size ) == NULL )
274 		{
275 			libcerror_error_set(
276 			 error,
277 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
278 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
279 			 "%s: unable to copy reparse data.",
280 			 function );
281 
282 			goto on_error;
283 		}
284 	}
285 	if( reparse_point_values->tag == 0x80000017 )
286 	{
287 		byte_stream_copy_to_uint32_little_endian(
288 		 &( reparse_point_values->reparse_data[ 12 ] ),
289 		 reparse_point_values->compression_method );
290 
291 #if defined( HAVE_DEBUG_OUTPUT )
292 		if( libcnotify_verbose != 0 )
293 		{
294 			byte_stream_copy_to_uint32_little_endian(
295 			 &( reparse_point_values->reparse_data[ 0 ] ),
296 			 value_32bit );
297 			libcnotify_printf(
298 			 "%s: external version\t\t: %" PRIu32 "\n",
299 			 function,
300 			 value_32bit );
301 
302 			byte_stream_copy_to_uint32_little_endian(
303 			 &( reparse_point_values->reparse_data[ 4 ] ),
304 			 value_32bit );
305 			libcnotify_printf(
306 			 "%s: external provider\t\t: %" PRIu32 "\n",
307 			 function,
308 			 value_32bit );
309 
310 			byte_stream_copy_to_uint32_little_endian(
311 			 &( reparse_point_values->reparse_data[ 8 ] ),
312 			 value_32bit );
313 			libcnotify_printf(
314 			 "%s: internal version\t\t: %" PRIu32 "\n",
315 			 function,
316 			 value_32bit );
317 
318 			libcnotify_printf(
319 			 "%s: compression method\t\t: %" PRIu32 " (%s)\n",
320 			 function,
321 			 reparse_point_values->compression_method,
322 			 libfsntfs_debug_print_compression_method(
323 			  reparse_point_values->compression_method ) );
324 		}
325 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
326 	}
327 	else if( ( reparse_point_values->tag == 0xa0000003 )
328 	      || ( reparse_point_values->tag == 0xa000000c ) )
329 	{
330 		byte_stream_copy_to_uint16_little_endian(
331 		 ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->substitute_name_offset,
332 		 reparse_point_values->substitute_name_offset );
333 
334 		byte_stream_copy_to_uint16_little_endian(
335 		 ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->substitute_name_size,
336 		 reparse_point_values->substitute_name_size );
337 
338 		byte_stream_copy_to_uint16_little_endian(
339 		 ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->print_name_offset,
340 		 reparse_point_values->print_name_offset );
341 
342 		byte_stream_copy_to_uint16_little_endian(
343 		 ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->print_name_size,
344 		 reparse_point_values->print_name_size );
345 
346 #if defined( HAVE_DEBUG_OUTPUT )
347 		if( libcnotify_verbose != 0 )
348 		{
349 			libcnotify_printf(
350 			 "%s: substitute name offset\t: 0x%04" PRIx16 "\n",
351 			 function,
352 			 reparse_point_values->substitute_name_offset );
353 
354 			libcnotify_printf(
355 			 "%s: substitute name size\t\t: %" PRIu16 "\n",
356 			 function,
357 			 reparse_point_values->substitute_name_size );
358 
359 			libcnotify_printf(
360 			 "%s: print name offset\t\t: 0x%04" PRIx16 "\n",
361 			 function,
362 			 reparse_point_values->print_name_offset );
363 
364 			libcnotify_printf(
365 			 "%s: print name size\t\t: %" PRIu16 "\n",
366 			 function,
367 			 reparse_point_values->print_name_size );
368 		}
369 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
370 	}
371 	if( reparse_point_values->tag == 0xa0000003 )
372 	{
373 		reparse_point_values->substitute_name_offset += sizeof( fsntfs_mount_point_reparse_data_t );
374 		reparse_point_values->print_name_offset      += sizeof( fsntfs_mount_point_reparse_data_t );
375 	}
376 	else if( reparse_point_values->tag == 0xa000000c )
377 	{
378 		byte_stream_copy_to_uint32_little_endian(
379 		 ( (fsntfs_symbolic_link_reparse_data_t *) reparse_point_values->reparse_data )->flags,
380 		 flags );
381 
382 #if defined( HAVE_DEBUG_OUTPUT )
383 		if( libcnotify_verbose != 0 )
384 		{
385 			libcnotify_printf(
386 			 "%s: flags\t\t\t\t: 0x%08" PRIx32 "\n",
387 			 function,
388 			 flags );
389 		}
390 #endif
391 		reparse_point_values->substitute_name_offset += sizeof( fsntfs_symbolic_link_reparse_data_t );
392 		reparse_point_values->print_name_offset      += sizeof( fsntfs_symbolic_link_reparse_data_t );
393 	}
394 #if defined( HAVE_DEBUG_OUTPUT )
395 	if( libcnotify_verbose != 0 )
396 	{
397 		if( ( reparse_point_values->tag != 0x80000017 )
398 		 && ( reparse_point_values->tag != 0xa0000003 )
399 		 && ( reparse_point_values->tag != 0xa000000c ) )
400 		{
401 			libcnotify_printf(
402 			 "%s: unusupported reparse point tag: 0x%08" PRIx32 "\n",
403 			 function,
404 			 reparse_point_values->tag );
405 		}
406 	}
407 #endif
408 	if( reparse_point_values->substitute_name_size > 0 )
409 	{
410 		if( reparse_point_values->substitute_name_offset >= reparse_point_values->reparse_data_size )
411 		{
412 			libcerror_error_set(
413 			 error,
414 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
415 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
416 			 "%s: invalid substitute name offset value out of bounds.",
417 			 function );
418 
419 			goto on_error;
420 		}
421 		if( reparse_point_values->substitute_name_size > ( reparse_point_values->reparse_data_size - reparse_point_values->substitute_name_offset ) )
422 		{
423 			libcerror_error_set(
424 			 error,
425 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
426 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
427 			 "%s: invalid substitute name size value out of bounds.",
428 			 function );
429 
430 			goto on_error;
431 		}
432 #if defined( HAVE_DEBUG_OUTPUT )
433 		if( libcnotify_verbose != 0 )
434 		{
435 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
436 			result = libuna_utf16_string_size_from_utf16_stream(
437 			          &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
438 			          (size_t) reparse_point_values->substitute_name_size,
439 			          LIBUNA_ENDIAN_LITTLE,
440 			          &value_string_size,
441 			          error );
442 #else
443 			result = libuna_utf8_string_size_from_utf16_stream(
444 			          &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
445 			          (size_t) reparse_point_values->substitute_name_size,
446 			          LIBUNA_ENDIAN_LITTLE,
447 			          &value_string_size,
448 			          error );
449 #endif
450 			if( result != 1 )
451 			{
452 				libcerror_error_set(
453 				 error,
454 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
455 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
456 				 "%s: unable to determine size of substitute name string.",
457 				 function );
458 
459 				goto on_error;
460 			}
461 			value_string = system_string_allocate(
462 			                value_string_size );
463 
464 			if( value_string == NULL )
465 			{
466 				libcerror_error_set(
467 				 error,
468 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
469 				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
470 				 "%s: unable to create substitute name string.",
471 				 function );
472 
473 				goto on_error;
474 			}
475 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
476 			result = libuna_utf16_string_copy_from_utf16_stream(
477 			          (libuna_utf16_character_t *) value_string,
478 			          value_string_size,
479 			          &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
480 			          (size_t) reparse_point_values->substitute_name_size,
481 			          LIBUNA_ENDIAN_LITTLE,
482 			          error );
483 #else
484 			result = libuna_utf8_string_copy_from_utf16_stream(
485 			          (libuna_utf8_character_t *) value_string,
486 			          value_string_size,
487 			          &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
488 			          (size_t) reparse_point_values->substitute_name_size,
489 			          LIBUNA_ENDIAN_LITTLE,
490 			          error );
491 #endif
492 			if( result != 1 )
493 			{
494 				libcerror_error_set(
495 				 error,
496 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
497 				 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
498 				 "%s: unable to set substitute name string.",
499 				 function );
500 
501 				goto on_error;
502 			}
503 			libcnotify_printf(
504 			 "%s: substitute name\t\t: %" PRIs_SYSTEM "\n",
505 			 function,
506 			 value_string );
507 
508 			memory_free(
509 			 value_string );
510 
511 			value_string = NULL;
512 		}
513 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
514 	}
515 	if( reparse_point_values->print_name_size > 0 )
516 	{
517 		if( reparse_point_values->print_name_offset >= reparse_point_values->reparse_data_size )
518 		{
519 			libcerror_error_set(
520 			 error,
521 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
522 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
523 			 "%s: invalid print name offset value out of bounds.",
524 			 function );
525 
526 			goto on_error;
527 		}
528 		if( reparse_point_values->print_name_size > ( reparse_point_values->reparse_data_size - reparse_point_values->print_name_offset ) )
529 		{
530 			libcerror_error_set(
531 			 error,
532 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
533 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
534 			 "%s: invalid print name size value out of bounds.",
535 			 function );
536 
537 			goto on_error;
538 		}
539 #if defined( HAVE_DEBUG_OUTPUT )
540 		if( libcnotify_verbose != 0 )
541 		{
542 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
543 			result = libuna_utf16_string_size_from_utf16_stream(
544 			          &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
545 			          (size_t) reparse_point_values->print_name_size,
546 			          LIBUNA_ENDIAN_LITTLE,
547 			          &value_string_size,
548 			          error );
549 #else
550 			result = libuna_utf8_string_size_from_utf16_stream(
551 			          &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
552 			          (size_t) reparse_point_values->print_name_size,
553 			          LIBUNA_ENDIAN_LITTLE,
554 			          &value_string_size,
555 			          error );
556 #endif
557 			if( result != 1 )
558 			{
559 				libcerror_error_set(
560 				 error,
561 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
562 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
563 				 "%s: unable to determine size of print name string.",
564 				 function );
565 
566 				goto on_error;
567 			}
568 			value_string = system_string_allocate(
569 			                value_string_size );
570 
571 			if( value_string == NULL )
572 			{
573 				libcerror_error_set(
574 				 error,
575 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
576 				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
577 				 "%s: unable to create print name string.",
578 				 function );
579 
580 				goto on_error;
581 			}
582 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
583 			result = libuna_utf16_string_copy_from_utf16_stream(
584 			          (libuna_utf16_character_t *) value_string,
585 			          value_string_size,
586 			          &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
587 			          (size_t) reparse_point_values->print_name_size,
588 			          LIBUNA_ENDIAN_LITTLE,
589 			          error );
590 #else
591 			result = libuna_utf8_string_copy_from_utf16_stream(
592 			          (libuna_utf8_character_t *) value_string,
593 			          value_string_size,
594 			          &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
595 			          (size_t) reparse_point_values->print_name_size,
596 			          LIBUNA_ENDIAN_LITTLE,
597 			          error );
598 #endif
599 			if( result != 1 )
600 			{
601 				libcerror_error_set(
602 				 error,
603 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
604 				 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
605 				 "%s: unable to set print name string.",
606 				 function );
607 
608 				goto on_error;
609 			}
610 			libcnotify_printf(
611 			 "%s: print name\t\t\t: %" PRIs_SYSTEM "\n",
612 			 function,
613 			 value_string );
614 
615 			memory_free(
616 			 value_string );
617 
618 			value_string = NULL;
619 		}
620 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
621 	}
622 #if defined( HAVE_DEBUG_OUTPUT )
623 	if( libcnotify_verbose != 0 )
624 	{
625 		libcnotify_printf(
626 		 "\n" );
627 	}
628 #endif
629 	return( 1 );
630 
631 on_error:
632 #if defined( HAVE_DEBUG_OUTPUT )
633 	if( value_string != NULL )
634 	{
635 		memory_free(
636 		 value_string );
637 	}
638 #endif
639 	if( reparse_point_values->reparse_data != NULL )
640 	{
641 		memory_free(
642 		 reparse_point_values->reparse_data );
643 
644 		reparse_point_values->reparse_data = NULL;
645 	}
646 	reparse_point_values->reparse_data_size = 0;
647 
648 	return( -1 );
649 }
650 
651 /* Reads the reparse point values from an MFT attribute
652  * Returns 1 if successful or -1 on error
653  */
libfsntfs_reparse_point_values_read_from_mft_attribute(libfsntfs_reparse_point_values_t * reparse_point_values,libfsntfs_mft_attribute_t * mft_attribute,libcerror_error_t ** error)654 int libfsntfs_reparse_point_values_read_from_mft_attribute(
655      libfsntfs_reparse_point_values_t *reparse_point_values,
656      libfsntfs_mft_attribute_t *mft_attribute,
657      libcerror_error_t **error )
658 {
659 	uint8_t *data           = NULL;
660 	static char *function   = "libfsntfs_reparse_point_values_read_from_mft_attribute";
661 	size_t data_size        = 0;
662 	uint32_t attribute_type = 0;
663 	int result              = 0;
664 
665 	if( reparse_point_values == NULL )
666 	{
667 		libcerror_error_set(
668 		 error,
669 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
670 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
671 		 "%s: invalid reparse point values.",
672 		 function );
673 
674 		return( -1 );
675 	}
676 	if( libfsntfs_mft_attribute_get_type(
677 	     mft_attribute,
678 	     &attribute_type,
679 	     error ) != 1 )
680 	{
681 		libcerror_error_set(
682 		 error,
683 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
684 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
685 		 "%s: unable to retrieve type from attribute.",
686 		 function );
687 
688 		return( -1 );
689 	}
690 	if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT )
691 	{
692 		libcerror_error_set(
693 		 error,
694 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
695 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
696 		 "%s: unsupported attribute type.",
697 		 function );
698 
699 		return( -1 );
700 	}
701 	result = libfsntfs_mft_attribute_data_is_resident(
702 	          mft_attribute,
703 	          error );
704 
705 	if( result == -1 )
706 	{
707 		libcerror_error_set(
708 		 error,
709 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
710 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
711 		 "%s: unable to determine if attribute data is resident.",
712 		 function );
713 
714 		return( -1 );
715 	}
716 	else if( result == 0 )
717 	{
718 		libcerror_error_set(
719 		 error,
720 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
721 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
722 		 "%s: unsupported non-resident attribute.",
723 		 function );
724 
725 		return( 1 );
726 	}
727 	if( libfsntfs_mft_attribute_get_resident_data(
728 	     mft_attribute,
729 	     &data,
730 	     &data_size,
731 	     error ) != 1 )
732 	{
733 		libcerror_error_set(
734 		 error,
735 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
736 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
737 		 "%s: unable to retrieve resident data from attribute.",
738 		 function );
739 
740 		return( -1 );
741 	}
742 	if( libfsntfs_reparse_point_values_read_data(
743 	     reparse_point_values,
744 	     data,
745 	     data_size,
746 	     error ) != 1 )
747 	{
748 		libcerror_error_set(
749 		 error,
750 		 LIBCERROR_ERROR_DOMAIN_IO,
751 		 LIBCERROR_IO_ERROR_READ_FAILED,
752 		 "%s: unable to read reparse point values.",
753 		 function );
754 
755 		return( -1 );
756 	}
757 	return( 1 );
758 }
759 
760 /* Retrieves the tag
761  * The tag is a combination of the type and flags
762  * Returns 1 if successful or -1 on error
763  */
libfsntfs_reparse_point_values_get_tag(libfsntfs_reparse_point_values_t * reparse_point_values,uint32_t * tag,libcerror_error_t ** error)764 int libfsntfs_reparse_point_values_get_tag(
765      libfsntfs_reparse_point_values_t *reparse_point_values,
766      uint32_t *tag,
767      libcerror_error_t **error )
768 {
769 	static char *function = "libfsntfs_reparse_point_values_get_tag";
770 
771 	if( reparse_point_values == NULL )
772 	{
773 		libcerror_error_set(
774 		 error,
775 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
776 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
777 		 "%s: invalid reparse point values.",
778 		 function );
779 
780 		return( -1 );
781 	}
782 	if( tag == NULL )
783 	{
784 		libcerror_error_set(
785 		 error,
786 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
787 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
788 		 "%s: invalid tag.",
789 		 function );
790 
791 		return( -1 );
792 	}
793 	*tag = reparse_point_values->tag;
794 
795 	return( 1 );
796 }
797 
798 /* Retrieves the Windows Overlay Filter (WOF) compression method
799  * Returns 1 if successful, 0 if not available or -1 on error
800  */
libfsntfs_reparse_point_values_get_compression_method(libfsntfs_reparse_point_values_t * reparse_point_values,uint32_t * compression_method,libcerror_error_t ** error)801 int libfsntfs_reparse_point_values_get_compression_method(
802      libfsntfs_reparse_point_values_t *reparse_point_values,
803      uint32_t *compression_method,
804      libcerror_error_t **error )
805 {
806 	static char *function = "libfsntfs_reparse_point_values_get_compression_method";
807 
808 	if( reparse_point_values == NULL )
809 	{
810 		libcerror_error_set(
811 		 error,
812 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
813 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
814 		 "%s: invalid reparse point values.",
815 		 function );
816 
817 		return( -1 );
818 	}
819 	if( compression_method == NULL )
820 	{
821 		libcerror_error_set(
822 		 error,
823 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
824 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
825 		 "%s: invalid compression method.",
826 		 function );
827 
828 		return( -1 );
829 	}
830 	if( reparse_point_values->tag == 0x80000017 )
831 	{
832 		*compression_method = reparse_point_values->compression_method;
833 
834 		return( 1 );
835 	}
836 	return( 0 );
837 }
838 
839 /* Retrieves the size of the UTF-8 encoded substitute name
840  * The returned size includes the end of string character
841  * Returns 1 if successful, 0 if not available or -1 on error
842  */
libfsntfs_reparse_point_values_get_utf8_substitute_name_size(libfsntfs_reparse_point_values_t * reparse_point_values,size_t * utf8_string_size,libcerror_error_t ** error)843 int libfsntfs_reparse_point_values_get_utf8_substitute_name_size(
844      libfsntfs_reparse_point_values_t *reparse_point_values,
845      size_t *utf8_string_size,
846      libcerror_error_t **error )
847 {
848 	static char *function = "libfsntfs_reparse_point_values_get_utf8_substitute_name_size";
849 
850 	if( reparse_point_values == NULL )
851 	{
852 		libcerror_error_set(
853 		 error,
854 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
855 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
856 		 "%s: invalid reparse point values.",
857 		 function );
858 
859 		return( -1 );
860 	}
861 	if( reparse_point_values->substitute_name_size == 0 )
862 	{
863 		return( 0 );
864 	}
865 	if( libuna_utf8_string_size_from_utf16_stream(
866 	     &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
867 	     (size_t) reparse_point_values->substitute_name_size,
868 	     LIBUNA_ENDIAN_LITTLE,
869 	     utf8_string_size,
870 	     error ) != 1 )
871 	{
872 		libcerror_error_set(
873 		 error,
874 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
875 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
876 		 "%s: unable to retrieve UTF-8 string size.",
877 		 function );
878 
879 		return( -1 );
880 	}
881 	return( 1 );
882 }
883 
884 /* Retrieves the UTF-8 encoded substitute name
885  * The size should include the end of string character
886  * Returns 1 if successful, 0 if not available or -1 on error
887  */
libfsntfs_reparse_point_values_get_utf8_substitute_name(libfsntfs_reparse_point_values_t * reparse_point_values,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)888 int libfsntfs_reparse_point_values_get_utf8_substitute_name(
889      libfsntfs_reparse_point_values_t *reparse_point_values,
890      uint8_t *utf8_string,
891      size_t utf8_string_size,
892      libcerror_error_t **error )
893 {
894 	static char *function = "libfsntfs_reparse_point_values_get_utf8_substitute_name";
895 
896 	if( reparse_point_values == NULL )
897 	{
898 		libcerror_error_set(
899 		 error,
900 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
901 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
902 		 "%s: invalid reparse point values.",
903 		 function );
904 
905 		return( -1 );
906 	}
907 	if( reparse_point_values->substitute_name_size == 0 )
908 	{
909 		return( 0 );
910 	}
911 	if( libuna_utf8_string_copy_from_utf16_stream(
912 	     utf8_string,
913 	     utf8_string_size,
914 	     &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
915 	     (size_t) reparse_point_values->substitute_name_size,
916 	     LIBUNA_ENDIAN_LITTLE,
917 	     error ) != 1 )
918 	{
919 		libcerror_error_set(
920 		 error,
921 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
922 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
923 		 "%s: unable to retrieve UTF-8 string.",
924 		 function );
925 
926 		return( -1 );
927 	}
928 	return( 1 );
929 }
930 
931 /* Retrieves the size of the UTF-16 encoded substitute name
932  * The returned size includes the end of string character
933  * Returns 1 if successful, 0 if not available or -1 on error
934  */
libfsntfs_reparse_point_values_get_utf16_substitute_name_size(libfsntfs_reparse_point_values_t * reparse_point_values,size_t * utf16_string_size,libcerror_error_t ** error)935 int libfsntfs_reparse_point_values_get_utf16_substitute_name_size(
936      libfsntfs_reparse_point_values_t *reparse_point_values,
937      size_t *utf16_string_size,
938      libcerror_error_t **error )
939 {
940 	static char *function = "libfsntfs_reparse_point_values_get_utf16_substitute_name_size";
941 
942 	if( reparse_point_values == NULL )
943 	{
944 		libcerror_error_set(
945 		 error,
946 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
947 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
948 		 "%s: invalid reparse point values.",
949 		 function );
950 
951 		return( -1 );
952 	}
953 	if( reparse_point_values->substitute_name_size == 0 )
954 	{
955 		return( 0 );
956 	}
957 	if( libuna_utf16_string_size_from_utf16_stream(
958 	     &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
959 	     (size_t) reparse_point_values->substitute_name_size,
960 	     LIBUNA_ENDIAN_LITTLE,
961 	     utf16_string_size,
962 	     error ) != 1 )
963 	{
964 		libcerror_error_set(
965 		 error,
966 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
967 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
968 		 "%s: unable to retrieve UTF-16 string size.",
969 		 function );
970 
971 		return( -1 );
972 	}
973 	return( 1 );
974 }
975 
976 /* Retrieves the UTF-16 encoded substitute name
977  * The size should include the end of string character
978  * Returns 1 if successful, 0 if not available or -1 on error
979  */
libfsntfs_reparse_point_values_get_utf16_substitute_name(libfsntfs_reparse_point_values_t * reparse_point_values,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)980 int libfsntfs_reparse_point_values_get_utf16_substitute_name(
981      libfsntfs_reparse_point_values_t *reparse_point_values,
982      uint16_t *utf16_string,
983      size_t utf16_string_size,
984      libcerror_error_t **error )
985 {
986 	static char *function = "libfsntfs_reparse_point_values_get_utf16_substitute_name";
987 
988 	if( reparse_point_values == NULL )
989 	{
990 		libcerror_error_set(
991 		 error,
992 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
993 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
994 		 "%s: invalid reparse point values.",
995 		 function );
996 
997 		return( -1 );
998 	}
999 	if( reparse_point_values->substitute_name_size == 0 )
1000 	{
1001 		return( 0 );
1002 	}
1003 	if( libuna_utf16_string_copy_from_utf16_stream(
1004 	     utf16_string,
1005 	     utf16_string_size,
1006 	     &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
1007 	     (size_t) reparse_point_values->substitute_name_size,
1008 	     LIBUNA_ENDIAN_LITTLE,
1009 	     error ) != 1 )
1010 	{
1011 		libcerror_error_set(
1012 		 error,
1013 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1014 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1015 		 "%s: unable to retrieve UTF-16 string.",
1016 		 function );
1017 
1018 		return( -1 );
1019 	}
1020 	return( 1 );
1021 }
1022 
1023 /* Retrieves the size of the UTF-8 encoded print name
1024  * The returned size includes the end of string character
1025  * Returns 1 if successful, 0 if not available or -1 on error
1026  */
libfsntfs_reparse_point_values_get_utf8_print_name_size(libfsntfs_reparse_point_values_t * reparse_point_values,size_t * utf8_string_size,libcerror_error_t ** error)1027 int libfsntfs_reparse_point_values_get_utf8_print_name_size(
1028      libfsntfs_reparse_point_values_t *reparse_point_values,
1029      size_t *utf8_string_size,
1030      libcerror_error_t **error )
1031 {
1032 	static char *function = "libfsntfs_reparse_point_values_get_utf8_print_name_size";
1033 
1034 	if( reparse_point_values == NULL )
1035 	{
1036 		libcerror_error_set(
1037 		 error,
1038 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1039 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1040 		 "%s: invalid reparse point values.",
1041 		 function );
1042 
1043 		return( -1 );
1044 	}
1045 	if( reparse_point_values->print_name_size == 0 )
1046 	{
1047 		return( 0 );
1048 	}
1049 	if( libuna_utf8_string_size_from_utf16_stream(
1050 	     &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
1051 	     (size_t) reparse_point_values->print_name_size,
1052 	     LIBUNA_ENDIAN_LITTLE,
1053 	     utf8_string_size,
1054 	     error ) != 1 )
1055 	{
1056 		libcerror_error_set(
1057 		 error,
1058 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1059 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1060 		 "%s: unable to retrieve UTF-8 string size.",
1061 		 function );
1062 
1063 		return( -1 );
1064 	}
1065 	return( 1 );
1066 }
1067 
1068 /* Retrieves the UTF-8 encoded print name
1069  * The size should include the end of string character
1070  * Returns 1 if successful, 0 if not available or -1 on error
1071  */
libfsntfs_reparse_point_values_get_utf8_print_name(libfsntfs_reparse_point_values_t * reparse_point_values,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)1072 int libfsntfs_reparse_point_values_get_utf8_print_name(
1073      libfsntfs_reparse_point_values_t *reparse_point_values,
1074      uint8_t *utf8_string,
1075      size_t utf8_string_size,
1076      libcerror_error_t **error )
1077 {
1078 	static char *function = "libfsntfs_reparse_point_values_get_utf8_print_name";
1079 
1080 	if( reparse_point_values == NULL )
1081 	{
1082 		libcerror_error_set(
1083 		 error,
1084 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1085 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1086 		 "%s: invalid reparse point values.",
1087 		 function );
1088 
1089 		return( -1 );
1090 	}
1091 	if( reparse_point_values->print_name_size == 0 )
1092 	{
1093 		return( 0 );
1094 	}
1095 	if( libuna_utf8_string_copy_from_utf16_stream(
1096 	     utf8_string,
1097 	     utf8_string_size,
1098 	     &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
1099 	     (size_t) reparse_point_values->print_name_size,
1100 	     LIBUNA_ENDIAN_LITTLE,
1101 	     error ) != 1 )
1102 	{
1103 		libcerror_error_set(
1104 		 error,
1105 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1106 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1107 		 "%s: unable to retrieve UTF-8 string.",
1108 		 function );
1109 
1110 		return( -1 );
1111 	}
1112 	return( 1 );
1113 }
1114 
1115 /* Retrieves the size of the UTF-16 encoded print name
1116  * The returned size includes the end of string character
1117  * Returns 1 if successful, 0 if not available or -1 on error
1118  */
libfsntfs_reparse_point_values_get_utf16_print_name_size(libfsntfs_reparse_point_values_t * reparse_point_values,size_t * utf16_string_size,libcerror_error_t ** error)1119 int libfsntfs_reparse_point_values_get_utf16_print_name_size(
1120      libfsntfs_reparse_point_values_t *reparse_point_values,
1121      size_t *utf16_string_size,
1122      libcerror_error_t **error )
1123 {
1124 	static char *function = "libfsntfs_reparse_point_values_get_utf16_print_name_size";
1125 
1126 	if( reparse_point_values == NULL )
1127 	{
1128 		libcerror_error_set(
1129 		 error,
1130 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1131 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1132 		 "%s: invalid reparse point values.",
1133 		 function );
1134 
1135 		return( -1 );
1136 	}
1137 	if( reparse_point_values->print_name_size == 0 )
1138 	{
1139 		return( 0 );
1140 	}
1141 	if( libuna_utf16_string_size_from_utf16_stream(
1142 	     &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
1143 	     (size_t) reparse_point_values->print_name_size,
1144 	     LIBUNA_ENDIAN_LITTLE,
1145 	     utf16_string_size,
1146 	     error ) != 1 )
1147 	{
1148 		libcerror_error_set(
1149 		 error,
1150 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1151 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1152 		 "%s: unable to retrieve UTF-16 string size.",
1153 		 function );
1154 
1155 		return( -1 );
1156 	}
1157 	return( 1 );
1158 }
1159 
1160 /* Retrieves the UTF-16 encoded print name
1161  * The size should include the end of string character
1162  * Returns 1 if successful, 0 if not available or -1 on error
1163  */
libfsntfs_reparse_point_values_get_utf16_print_name(libfsntfs_reparse_point_values_t * reparse_point_values,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)1164 int libfsntfs_reparse_point_values_get_utf16_print_name(
1165      libfsntfs_reparse_point_values_t *reparse_point_values,
1166      uint16_t *utf16_string,
1167      size_t utf16_string_size,
1168      libcerror_error_t **error )
1169 {
1170 	static char *function = "libfsntfs_reparse_point_values_get_utf16_print_name";
1171 
1172 	if( reparse_point_values == NULL )
1173 	{
1174 		libcerror_error_set(
1175 		 error,
1176 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1177 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1178 		 "%s: invalid reparse point values.",
1179 		 function );
1180 
1181 		return( -1 );
1182 	}
1183 	if( reparse_point_values->print_name_size == 0 )
1184 	{
1185 		return( 0 );
1186 	}
1187 	if( libuna_utf16_string_copy_from_utf16_stream(
1188 	     utf16_string,
1189 	     utf16_string_size,
1190 	     &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
1191 	     (size_t) reparse_point_values->print_name_size,
1192 	     LIBUNA_ENDIAN_LITTLE,
1193 	     error ) != 1 )
1194 	{
1195 		libcerror_error_set(
1196 		 error,
1197 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1198 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1199 		 "%s: unable to retrieve UTF-16 string.",
1200 		 function );
1201 
1202 		return( -1 );
1203 	}
1204 	return( 1 );
1205 }
1206 
1207