Coverage Report

Created: 2026-08-31 07:43

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