1 /*
2  * Security descriptor index 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 <types.h>
26 
27 #include "libfsntfs_data_stream.h"
28 #include "libfsntfs_definitions.h"
29 #include "libfsntfs_index.h"
30 #include "libfsntfs_index_node.h"
31 #include "libfsntfs_index_value.h"
32 #include "libfsntfs_libbfio.h"
33 #include "libfsntfs_libcdata.h"
34 #include "libfsntfs_libcerror.h"
35 #include "libfsntfs_libcnotify.h"
36 #include "libfsntfs_mft_attribute.h"
37 #include "libfsntfs_mft_entry.h"
38 #include "libfsntfs_security_descriptor_index.h"
39 #include "libfsntfs_security_descriptor_index_value.h"
40 #include "libfsntfs_security_descriptor_values.h"
41 #include "libfsntfs_sds_index_value.h"
42 #include "libfsntfs_types.h"
43 
44 #include "fsntfs_secure.h"
45 
46 /* Creates a security descriptor index
47  * Make sure the value security_descriptor_index is referencing, is set to NULL
48  * Returns 1 if successful or -1 on error
49  */
libfsntfs_security_descriptor_index_initialize(libfsntfs_security_descriptor_index_t ** security_descriptor_index,libfsntfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfsntfs_mft_attribute_t * data_attribute,libcerror_error_t ** error)50 int libfsntfs_security_descriptor_index_initialize(
51      libfsntfs_security_descriptor_index_t **security_descriptor_index,
52      libfsntfs_io_handle_t *io_handle,
53      libbfio_handle_t *file_io_handle,
54      libfsntfs_mft_attribute_t *data_attribute,
55      libcerror_error_t **error )
56 {
57 	static char *function = "libfsntfs_security_descriptor_index_initialize";
58 
59 	if( security_descriptor_index == NULL )
60 	{
61 		libcerror_error_set(
62 		 error,
63 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
64 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
65 		 "%s: invalid security descriptor index.",
66 		 function );
67 
68 		return( -1 );
69 	}
70 	if( *security_descriptor_index != NULL )
71 	{
72 		libcerror_error_set(
73 		 error,
74 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
75 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
76 		 "%s: invalid security descriptor index value already set.",
77 		 function );
78 
79 		return( -1 );
80 	}
81 	if( data_attribute == NULL )
82 	{
83 		libcerror_error_set(
84 		 error,
85 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
86 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
87 		 "%s: invalid $SDS data attribute.",
88 		 function );
89 
90 		return( -1 );
91 	}
92 	*security_descriptor_index = memory_allocate_structure(
93 	                              libfsntfs_security_descriptor_index_t );
94 
95 	if( *security_descriptor_index == NULL )
96 	{
97 		libcerror_error_set(
98 		 error,
99 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
100 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
101 		 "%s: unable to create security descriptor index.",
102 		 function );
103 
104 		goto on_error;
105 	}
106 	if( memory_set(
107 	     *security_descriptor_index,
108 	     0,
109 	     sizeof( libfsntfs_security_descriptor_index_t ) ) == NULL )
110 	{
111 		libcerror_error_set(
112 		 error,
113 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
114 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
115 		 "%s: unable to clear security descriptor index.",
116 		 function );
117 
118 		memory_free(
119 		 *security_descriptor_index );
120 
121 		*security_descriptor_index = NULL;
122 
123 		return( -1 );
124 	}
125 /* TODO move out of index ? */
126 	if( libfsntfs_data_stream_initialize(
127 	     &( ( *security_descriptor_index )->data_stream ),
128 	     file_io_handle,
129 	     io_handle,
130 	     data_attribute,
131 	     error ) != 1 )
132 	{
133 		libcerror_error_set(
134 		 error,
135 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
136 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
137 		 "%s: unable to create $SDS data stream.",
138 		 function );
139 
140 		goto on_error;
141 	}
142 	return( 1 );
143 
144 on_error:
145 	if( *security_descriptor_index != NULL )
146 	{
147 		memory_free(
148 		 *security_descriptor_index );
149 
150 		*security_descriptor_index = NULL;
151 	}
152 	return( -1 );
153 }
154 
155 /* Frees a security descriptor index
156  * Returns 1 if successful or -1 on error
157  */
libfsntfs_security_descriptor_index_free(libfsntfs_security_descriptor_index_t ** security_descriptor_index,libcerror_error_t ** error)158 int libfsntfs_security_descriptor_index_free(
159      libfsntfs_security_descriptor_index_t **security_descriptor_index,
160      libcerror_error_t **error )
161 {
162 	static char *function = "libfsntfs_security_descriptor_index_free";
163 	int result            = 1;
164 
165 	if( security_descriptor_index == NULL )
166 	{
167 		libcerror_error_set(
168 		 error,
169 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
170 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
171 		 "%s: invalid security descriptor index.",
172 		 function );
173 
174 		return( -1 );
175 	}
176 	if( *security_descriptor_index != NULL )
177 	{
178 		if( ( *security_descriptor_index )->sii_index != NULL )
179 		{
180 			if( libfsntfs_index_free(
181 			     &( ( *security_descriptor_index )->sii_index ),
182 			     error ) != 1 )
183 			{
184 				libcerror_error_set(
185 				 error,
186 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
187 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
188 				 "%s: unable to free $SII index.",
189 				 function );
190 
191 				result = -1;
192 			}
193 		}
194 		if( libfsntfs_data_stream_free(
195 		     &( ( *security_descriptor_index )->data_stream ),
196 		     error ) != 1 )
197 		{
198 			libcerror_error_set(
199 			 error,
200 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
201 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
202 			 "%s: unable to free $SDS data stream.",
203 			 function );
204 
205 			result = -1;
206 		}
207 		memory_free(
208 		 *security_descriptor_index );
209 
210 		*security_descriptor_index = NULL;
211 	}
212 	return( result );
213 }
214 
215 /* Reads the security descriptor identifier ($SII) index
216  * Returns 1 if successful or -1 on error
217  */
libfsntfs_security_descriptor_index_read_sii_index(libfsntfs_security_descriptor_index_t * security_descriptor_index,libfsntfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfsntfs_mft_entry_t * mft_entry,libcerror_error_t ** error)218 int libfsntfs_security_descriptor_index_read_sii_index(
219      libfsntfs_security_descriptor_index_t *security_descriptor_index,
220      libfsntfs_io_handle_t *io_handle,
221      libbfio_handle_t *file_io_handle,
222      libfsntfs_mft_entry_t *mft_entry,
223      libcerror_error_t **error )
224 {
225 	static char *function   = "libfsntfs_security_descriptor_index_read_sii_index";
226 	uint32_t attribute_type = 0;
227 	uint32_t collation_type = 0;
228 	int result              = 0;
229 
230 	if( security_descriptor_index == NULL )
231 	{
232 		libcerror_error_set(
233 		 error,
234 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
235 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
236 		 "%s: invalid security descriptor index.",
237 		 function );
238 
239 		return( -1 );
240 	}
241 	if( security_descriptor_index->sii_index != NULL )
242 	{
243 		libcerror_error_set(
244 		 error,
245 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
246 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
247 		 "%s: invalid security descriptor index - $SII index value already set.",
248 		 function );
249 
250 		return( -1 );
251 	}
252 	if( libfsntfs_index_initialize(
253 	     &( security_descriptor_index->sii_index ),
254 	     io_handle,
255 	     (uint8_t *) "$SII",
256 	     5,
257 	     error ) != 1 )
258 	{
259 		libcerror_error_set(
260 		 error,
261 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
262 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
263 		 "%s: unable to create $SII index.",
264 		 function );
265 
266 		goto on_error;
267 	}
268 	result = libfsntfs_index_read(
269 	          security_descriptor_index->sii_index,
270 	          file_io_handle,
271 	          mft_entry,
272 	          0,
273 	          error );
274 
275 	if( result == -1 )
276 	{
277 		libcerror_error_set(
278 		 error,
279 		 LIBCERROR_ERROR_DOMAIN_IO,
280 		 LIBCERROR_IO_ERROR_READ_FAILED,
281 		 "%s: unable to read $SII index.",
282 		 function );
283 
284 		goto on_error;
285 	}
286 	else if( result != 0 )
287 	{
288 		if( libfsntfs_index_get_attribute_type(
289 		     security_descriptor_index->sii_index,
290 		     &attribute_type,
291 		     error ) != 1 )
292 		{
293 			libcerror_error_set(
294 			 error,
295 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
296 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
297 			 "%s: unable to retrieve attribute type from index.",
298 			 function );
299 
300 			goto on_error;
301 		}
302 		if( attribute_type != 0 )
303 		{
304 			libcerror_error_set(
305 			 error,
306 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
307 			 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
308 			 "%s: unsupported index attribute type.",
309 			 function );
310 
311 			goto on_error;
312 		}
313 		if( libfsntfs_index_get_collation_type(
314 		     security_descriptor_index->sii_index,
315 		     &collation_type,
316 		     error ) != 1 )
317 		{
318 			libcerror_error_set(
319 			 error,
320 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
321 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
322 			 "%s: unable to retrieve collation type from index.",
323 			 function );
324 
325 			goto on_error;
326 		}
327 		if( collation_type != 16 )
328 		{
329 			libcerror_error_set(
330 			 error,
331 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
332 			 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
333 			 "%s: unsupported index collation type.",
334 			 function );
335 
336 			goto on_error;
337 		}
338 	}
339 	return( 1 );
340 
341 on_error:
342 	if( security_descriptor_index->sii_index != NULL )
343 	{
344 		libfsntfs_index_free(
345 		 &( security_descriptor_index->sii_index ),
346 		 NULL );
347 	}
348 	return( -1 );
349 }
350 
351 /* Retrieves the security descriptor from an index node for a specific identifier
352  * This function creates new security descriptor values
353  * Returns 1 if successful, 0 if no such security descriptor or -1 on error
354  */
libfsntfs_security_descriptor_index_get_entry_from_index_node_by_identifier(libfsntfs_security_descriptor_index_t * security_descriptor_index,libbfio_handle_t * file_io_handle,libfsntfs_index_node_t * index_node,uint32_t security_descriptor_identifier,libfsntfs_security_descriptor_values_t ** security_descriptor_values,int recursion_depth,libcerror_error_t ** error)355 int libfsntfs_security_descriptor_index_get_entry_from_index_node_by_identifier(
356      libfsntfs_security_descriptor_index_t *security_descriptor_index,
357      libbfio_handle_t *file_io_handle,
358      libfsntfs_index_node_t *index_node,
359      uint32_t security_descriptor_identifier,
360      libfsntfs_security_descriptor_values_t **security_descriptor_values,
361      int recursion_depth,
362      libcerror_error_t **error )
363 {
364 	uint8_t secure_index_value_data[ sizeof( fsntfs_secure_index_value_t ) ];
365 
366 	libfsntfs_index_node_t *sub_node                                             = NULL;
367 	libfsntfs_index_value_t *index_value                                         = NULL;
368 	libfsntfs_sds_index_value_t *sds_index_value                                 = NULL;
369 	libfsntfs_security_descriptor_index_value_t *security_descriptor_index_value = NULL;
370 	libfsntfs_security_descriptor_values_t *safe_security_descriptor_values      = NULL;
371 	static char *function                                                        = "libfsntfs_security_descriptor_index_get_entry_from_index_node_by_identifier";
372 	size_t security_descriptor_data_size                                         = 0;
373 	ssize_t read_count                                                           = 0;
374 	off64_t index_entry_offset                                                   = 0;
375 	int compare_result                                                           = 0;
376 	int index_value_entry                                                        = 0;
377 	int is_allocated                                                             = 0;
378 	int number_of_index_values                                                   = 0;
379 	int result                                                                   = 0;
380 
381 	if( security_descriptor_index == NULL )
382 	{
383 		libcerror_error_set(
384 		 error,
385 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
386 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
387 		 "%s: invalid security descriptor index.",
388 		 function );
389 
390 		return( -1 );
391 	}
392 	if( security_descriptor_index->sii_index == NULL )
393 	{
394 		libcerror_error_set(
395 		 error,
396 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
397 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
398 		 "%s: invalid security descriptor index - missing $SII index.",
399 		 function );
400 
401 		return( -1 );
402 	}
403 	if( security_descriptor_index->sii_index->io_handle == NULL )
404 	{
405 		libcerror_error_set(
406 		 error,
407 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
408 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
409 		 "%s: invalid security descriptor index - invalid $SII index - missing IO handle.",
410 		 function );
411 
412 		return( -1 );
413 	}
414 	if( security_descriptor_values == NULL )
415 	{
416 		libcerror_error_set(
417 		 error,
418 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
419 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
420 		 "%s: invalid security descriptor values.",
421 		 function );
422 
423 		return( -1 );
424 	}
425 	if( ( recursion_depth < 0 )
426 	 || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) )
427 	{
428 		libcerror_error_set(
429 		 error,
430 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
431 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
432 		 "%s: invalid recursion depth value out of bounds.",
433 		 function );
434 
435 		return( -1 );
436 	}
437 	if( libfsntfs_index_node_get_number_of_values(
438 	     index_node,
439 	     &number_of_index_values,
440 	     error ) != 1 )
441 	{
442 		libcerror_error_set(
443 		 error,
444 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
445 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
446 		 "%s: unable to retrieve number of values from index node.",
447 		 function );
448 
449 		goto on_error;
450 	}
451 	for( index_value_entry = 0;
452 	     index_value_entry < number_of_index_values;
453 	     index_value_entry++ )
454 	{
455 		if( libfsntfs_index_node_get_value_by_index(
456 		     index_node,
457 		     index_value_entry,
458 		     &index_value,
459 		     error ) != 1 )
460 		{
461 			libcerror_error_set(
462 			 error,
463 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
464 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
465 			 "%s: unable to retrieve value: %d from index node.",
466 			 function,
467 			 index_value_entry );
468 
469 			goto on_error;
470 		}
471 		if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_HAS_SUB_NODE ) != 0 )
472 		{
473 			if( index_value->sub_node_vcn > (uint64_t) INT_MAX )
474 			{
475 				libcerror_error_set(
476 				 error,
477 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
478 				 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
479 				 "%s: node index value: %d sub node VCN value out of bounds.",
480 				 function,
481 				 index_value_entry );
482 
483 				goto on_error;
484 			}
485 			is_allocated = libfsntfs_index_sub_node_is_allocated(
486 			                security_descriptor_index->sii_index,
487 			                (int) index_value->sub_node_vcn,
488 			                error );
489 
490 			if( is_allocated == -1 )
491 			{
492 				libcerror_error_set(
493 				 error,
494 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
495 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
496 				 "%s: unable to determine if sub node with VCN: %d is allocated.",
497 				 function,
498 				 (int) index_value->sub_node_vcn );
499 
500 				goto on_error;
501 			}
502 			else if( is_allocated == 0 )
503 			{
504 				continue;
505 			}
506 		}
507 		if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 )
508 		{
509 			break;
510 		}
511 		if( libfsntfs_security_descriptor_index_value_initialize(
512 		     &security_descriptor_index_value,
513 		     error ) != 1 )
514 		{
515 			libcerror_error_set(
516 			 error,
517 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
518 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
519 			 "%s: unable to create security descriptor index value.",
520 			 function );
521 
522 			goto on_error;
523 		}
524 		if( libfsntfs_security_descriptor_index_value_read_data(
525 		     security_descriptor_index_value,
526 		     index_value->value_data,
527 		     (size_t) index_value->value_data_size,
528 		     error ) != 1 )
529 		{
530 			libcerror_error_set(
531 			 error,
532 			 LIBCERROR_ERROR_DOMAIN_IO,
533 			 LIBCERROR_IO_ERROR_READ_FAILED,
534 			 "%s: unable to read security descriptor index value.",
535 			 function );
536 
537 			goto on_error;
538 		}
539 		if( security_descriptor_identifier < security_descriptor_index_value->identifier )
540 		{
541 			compare_result = LIBCDATA_COMPARE_LESS;
542 		}
543 		else if( security_descriptor_identifier > security_descriptor_index_value->identifier )
544 		{
545 			compare_result = LIBCDATA_COMPARE_GREATER;
546 		}
547 		else
548 		{
549 			compare_result = LIBCDATA_COMPARE_EQUAL;
550 		}
551 		if( compare_result != LIBCDATA_COMPARE_EQUAL )
552 		{
553 			if( libfsntfs_security_descriptor_index_value_free(
554 			     &security_descriptor_index_value,
555 			     error ) != 1 )
556 			{
557 				libcerror_error_set(
558 				 error,
559 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
560 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
561 				 "%s: unable to free security descriptor index value.",
562 				 function );
563 
564 				goto on_error;
565 			}
566 		}
567 		if( compare_result == LIBCDATA_COMPARE_LESS )
568 		{
569 			if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_HAS_SUB_NODE ) != 0 )
570 			{
571 				break;
572 			}
573 		}
574 		else if( compare_result == LIBCDATA_COMPARE_EQUAL )
575 		{
576 			break;
577 		}
578 	}
579 	if( compare_result == LIBCDATA_COMPARE_EQUAL )
580 	{
581 		if( security_descriptor_index_value->data_size < (size64_t) ( sizeof( fsntfs_secure_index_value_t ) + 20 ) )
582 		{
583 			libcerror_error_set(
584 			 error,
585 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
586 			 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
587 			 "%s: unsupported security descriptor stream ($SDS) data size: %" PRIu64 "\n",
588 			 function,
589 			 security_descriptor_index_value->data_size );
590 
591 			return( -1 );
592 		}
593 		read_count = libfsntfs_data_stream_read_buffer_at_offset(
594 		              security_descriptor_index->data_stream,
595 		              secure_index_value_data,
596 		              sizeof( fsntfs_secure_index_value_t ),
597 		              (off64_t) security_descriptor_index_value->data_offset,
598 		              error );
599 
600 		if( read_count < 0 )
601 		{
602 			libcerror_error_set(
603 			 error,
604 			 LIBCERROR_ERROR_DOMAIN_IO,
605 			 LIBCERROR_IO_ERROR_READ_FAILED,
606 			 "%s: unable to read security descriptor stream ($SDS) data at offset: 0x%08" PRIx64 ".",
607 			 function,
608 			 security_descriptor_index_value->data_offset );
609 
610 			goto on_error;
611 		}
612 		if( libfsntfs_sds_index_value_initialize(
613 		     &sds_index_value,
614 		     error ) != 1 )
615 		{
616 			libcerror_error_set(
617 			 error,
618 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
619 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
620 			 "%s: unable to create $SDS index value.",
621 			 function );
622 
623 			goto on_error;
624 		}
625 		if( libfsntfs_sds_index_value_read_data(
626 		     sds_index_value,
627 		     secure_index_value_data,
628 		     sizeof( fsntfs_secure_index_value_t ),
629 		     error ) != 1 )
630 		{
631 			libcerror_error_set(
632 			 error,
633 			 LIBCERROR_ERROR_DOMAIN_IO,
634 			 LIBCERROR_IO_ERROR_READ_FAILED,
635 			 "%s: unable to read $SDS index value data.",
636 			 function );
637 
638 			goto on_error;
639 		}
640 /* TODO check index values against secure_index_value */
641 
642 		if( libfsntfs_security_descriptor_values_initialize(
643 		     &safe_security_descriptor_values,
644 		     error ) != 1 )
645 		{
646 			libcerror_error_set(
647 			 error,
648 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
649 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
650 			 "%s: unable to create security descriptor values.",
651 			 function );
652 
653 			goto on_error;
654 		}
655 		security_descriptor_data_size = (size_t) ( security_descriptor_index_value->data_size - sizeof( fsntfs_secure_index_value_t ) );
656 
657 		if( ( security_descriptor_data_size == 0 )
658 		 || ( security_descriptor_data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
659 		{
660 			libcerror_error_set(
661 			 error,
662 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
663 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
664 			 "%s: invalid security descriptor values data value out of bounds.",
665 			 function,
666 			 index_value_entry );
667 
668 			goto on_error;
669 		}
670 		safe_security_descriptor_values->data = memory_allocate(
671 		                                         sizeof( uint8_t ) * security_descriptor_data_size );
672 
673 		if( safe_security_descriptor_values->data == NULL )
674 		{
675 			libcerror_error_set(
676 			 error,
677 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
678 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
679 			 "%s: unable to create security descriptor values data.",
680 			 function );
681 
682 			goto on_error;
683 		}
684 		safe_security_descriptor_values->data_size = security_descriptor_data_size;
685 
686 		if( memory_set(
687 		     safe_security_descriptor_values->data,
688 		     0,
689 		     sizeof( uint8_t ) * safe_security_descriptor_values->data_size ) == NULL )
690 		{
691 			libcerror_error_set(
692 			 error,
693 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
694 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
695 			 "%s: unable to clear security descriptor data.",
696 			 function );
697 
698 			goto on_error;
699 		}
700 		read_count = libfsntfs_data_stream_read_buffer(
701 		              security_descriptor_index->data_stream,
702 		              safe_security_descriptor_values->data,
703 		              safe_security_descriptor_values->data_size,
704 		              error );
705 
706 		if( read_count < 0 )
707 		{
708 			libcerror_error_set(
709 			 error,
710 			 LIBCERROR_ERROR_DOMAIN_IO,
711 			 LIBCERROR_IO_ERROR_READ_FAILED,
712 			 "%s: unable to read security descriptor data at offset: 0x%08" PRIx64 ".",
713 			 function,
714 			 security_descriptor_index_value->data_offset );
715 
716 			goto on_error;
717 		}
718 		if( libfsntfs_security_descriptor_values_read_data(
719 		     safe_security_descriptor_values,
720 		     safe_security_descriptor_values->data,
721 		     safe_security_descriptor_values->data_size,
722 		     error ) != 1 )
723 		{
724 			libcerror_error_set(
725 			 error,
726 			 LIBCERROR_ERROR_DOMAIN_IO,
727 			 LIBCERROR_IO_ERROR_READ_FAILED,
728 			 "%s: unable to read security descriptor values.",
729 			 function );
730 
731 			goto on_error;
732 		}
733 		*security_descriptor_values = safe_security_descriptor_values;
734 
735 		result = 1;
736 	}
737 	else if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_HAS_SUB_NODE ) != 0 )
738 	{
739 		index_entry_offset = (off64_t) ( index_value->sub_node_vcn * security_descriptor_index->sii_index->io_handle->cluster_block_size );
740 
741 		if( libfsntfs_index_get_sub_node(
742 		     security_descriptor_index->sii_index,
743 		     file_io_handle,
744 		     security_descriptor_index->sii_index->index_node_cache,
745 		     index_entry_offset,
746 		     (int) index_value->sub_node_vcn,
747 		     &sub_node,
748 		     error ) != 1 )
749 		{
750 			libcerror_error_set(
751 			 error,
752 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
753 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
754 			 "%s: unable to retrieve sub node with VCN: %d at offset: 0x%08" PRIx64 ".",
755 			 function,
756 			 (int) index_value->sub_node_vcn,
757 			 index_entry_offset );
758 
759 			goto on_error;
760 		}
761 		result = libfsntfs_security_descriptor_index_get_entry_from_index_node_by_identifier(
762 		          security_descriptor_index,
763 		          file_io_handle,
764 		          security_descriptor_index->sii_index->root_node,
765 		          security_descriptor_identifier,
766 		          security_descriptor_values,
767 		          recursion_depth + 1,
768 		          error );
769 
770 		if( result == -1 )
771 		{
772 			libcerror_error_set(
773 			 error,
774 			 LIBCERROR_ERROR_DOMAIN_IO,
775 			 LIBCERROR_IO_ERROR_READ_FAILED,
776 			 "%s: unable to retrieve security descriptor by identifier from index entry with VCN: %d at offset: 0x%08" PRIx64 ".",
777 			 function,
778 			 (int) index_value->sub_node_vcn,
779 			 index_entry_offset );
780 
781 			goto on_error;
782 		}
783 	}
784 	return( result );
785 
786 on_error:
787 	if( safe_security_descriptor_values != NULL )
788 	{
789 		libfsntfs_security_descriptor_values_free(
790 		 &safe_security_descriptor_values,
791 		 NULL );
792 	}
793 	if( security_descriptor_index_value != NULL )
794 	{
795 		libfsntfs_security_descriptor_index_value_free(
796 		 &security_descriptor_index_value,
797 		 NULL );
798 	}
799 	return( -1 );
800 }
801 
802 /* Retrieves the security descriptor for a specific identifier
803  * This function creates new security descriptor values
804  * Returns 1 if successful, 0 if not available or -1 on error
805  */
libfsntfs_security_descriptor_index_get_entry_by_identifier(libfsntfs_security_descriptor_index_t * security_descriptor_index,libbfio_handle_t * file_io_handle,uint32_t security_descriptor_identifier,libfsntfs_security_descriptor_values_t ** security_descriptor_values,libcerror_error_t ** error)806 int libfsntfs_security_descriptor_index_get_entry_by_identifier(
807      libfsntfs_security_descriptor_index_t *security_descriptor_index,
808      libbfio_handle_t *file_io_handle,
809      uint32_t security_descriptor_identifier,
810      libfsntfs_security_descriptor_values_t **security_descriptor_values,
811      libcerror_error_t **error )
812 {
813 	static char *function = "libfsntfs_security_descriptor_index_get_entry_by_identifier";
814 	int result            = 0;
815 
816 	if( security_descriptor_index == NULL )
817 	{
818 		libcerror_error_set(
819 		 error,
820 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
821 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
822 		 "%s: invalid security descriptor index.",
823 		 function );
824 
825 		return( -1 );
826 	}
827 	result = libfsntfs_security_descriptor_index_get_entry_from_index_node_by_identifier(
828 	          security_descriptor_index,
829 	          file_io_handle,
830 	          security_descriptor_index->sii_index->root_node,
831 	          security_descriptor_identifier,
832 	          security_descriptor_values,
833 	          0,
834 	          error );
835 
836 	if( result == -1 )
837 	{
838 		libcerror_error_set(
839 		 error,
840 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
841 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
842 		 "%s: unable to retrieve security descriptor by identifier.",
843 		 function );
844 
845 		return( -1 );
846 	}
847 	return( result );
848 }
849 
850