]> wimlib.net Git - wimlib/blob - src/security.c
dentry.c: Read/write dentries from structure
[wimlib] / src / security.c
1 /*
2  * security.c
3  *
4  * Read and write the per-WIM-image table of security descriptors.
5  */
6
7 /*
8  * Copyright (C) 2012, 2013 Eric Biggers
9  *
10  * This file is part of wimlib, a library for working with WIM files.
11  *
12  * wimlib is free software; you can redistribute it and/or modify it under the
13  * terms of the GNU General Public License as published by the Free
14  * Software Foundation; either version 3 of the License, or (at your option)
15  * any later version.
16  *
17  * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
18  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
19  * A PARTICULAR PURPOSE. See the GNU General Public License for more
20  * details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with wimlib; if not, see http://www.gnu.org/licenses/.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #  include "config.h"
28 #endif
29
30 #include "wimlib/assert.h"
31 #include "wimlib/buffer_io.h"
32 #include "wimlib/error.h"
33 #include "wimlib/security.h"
34 #include "wimlib/sha1.h"
35 #include "wimlib/util.h"
36
37 /* At the start of each type of access control entry.  */
38 typedef struct _ACE_HEADER {
39         /* enum ace_type, specifies what type of ACE this is.  */
40         u8 type;
41
42         /* bitwise OR of the inherit ACE flags #defined above */
43         u8 flags;
44
45         /* Size of the access control entry. */
46         le16 size;
47 } _packed_attribute ACE_HEADER;
48
49 /* Grants rights to a user or group */
50 typedef struct _ACCESS_ALLOWED_ACE {
51         ACE_HEADER hdr;
52         le32 mask;
53         le32 sid_start;
54 } _packed_attribute ACCESS_ALLOWED_ACE;
55
56 /* Denies rights to a user or group */
57 typedef struct _ACCESS_DENIED_ACE {
58         ACE_HEADER hdr;
59         le32 mask;
60         le32 sid_start;
61 } _packed_attribute ACCESS_DENIED_ACE;
62
63 typedef struct _SYSTEM_AUDIT_ACE {
64         ACE_HEADER hdr;
65         le32 mask;
66         le32 sid_start;
67 } _packed_attribute SYSTEM_AUDIT_ACE;
68
69
70 /* Header of an access control list. */
71 typedef struct _ACL {
72         /* ACL_REVISION or ACL_REVISION_DS */
73         u8 revision;
74
75         /* padding */
76         u8 sbz1;
77
78         /* Total size of the ACL, including all access control entries */
79         le16 acl_size;
80
81         /* Number of access control entry structures that follow the ACL
82          * structure. */
83         le16 ace_count;
84
85         /* padding */
86         le16 sbz2;
87 } _packed_attribute ACL;
88
89 /* A structure used to identify users or groups. */
90 typedef struct _SID {
91
92         /* example: 0x1 */
93         u8  revision;
94         u8  sub_authority_count;
95
96         /* Identifies the authority that issued the SID.  Can be, but does not
97          * have to be, one of enum sid_authority_value */
98         u8  identifier_authority[6];
99
100         le32 sub_authority[];
101 } _packed_attribute SID;
102
103 typedef struct _SECURITY_DESCRIPTOR_RELATIVE  {
104         /* Example: 0x1 */
105         u8 revision;
106         /* Example: 0x0 */
107         u8 sbz1;
108
109         /* Example: 0x4149 */
110         le16 security_descriptor_control;
111
112         /* Offset of a SID structure in the security descriptor. */
113         /* Example: 0x14 */
114         le32 owner_offset;
115
116         /* Offset of a SID structure in the security descriptor. */
117         /* Example: 0x24 */
118         le32 group_offset;
119
120         /* Offset of an ACL structure in the security descriptor. */
121         /* System ACL. */
122         /* Example: 0x00 */
123         le32 sacl_offset;
124
125         /* Offset of an ACL structure in the security descriptor. */
126         /* Discretionary ACL. */
127         /* Example: 0x34 */
128         le32 dacl_offset;
129 } _packed_attribute SECURITY_DESCRIPTOR_RELATIVE;
130
131 struct wim_security_data_disk {
132         le32 total_length;
133         le32 num_entries;
134         le64 sizes[];
135 } _packed_attribute;
136
137 /*
138  * This is a hack to work around a problem in libntfs-3g.  libntfs-3g validates
139  * security descriptors with a function named ntfs_valid_descr().
140  * ntfs_valid_descr() considers a security descriptor that ends in a SACL
141  * (Sysetm Access Control List) with no ACE's (Access Control Entries) to be
142  * invalid.  However, a security descriptor like this exists in the Windows 7
143  * install.wim.  Here, security descriptors matching this pattern are modified
144  * to have no SACL.  This should make no difference since the SACL had no
145  * entries anyway; however this ensures that that the security descriptors pass
146  * the validation in libntfs-3g.
147  */
148 static void
149 empty_sacl_fixup(SECURITY_DESCRIPTOR_RELATIVE *descr, size_t *size_p)
150 {
151         /* No-op if no NTFS-3g support, or if NTFS-3g is version 2013 or later
152          * */
153 #if defined(WITH_NTFS_3G) && !defined(HAVE_NTFS_MNT_RDONLY)
154         if (*size_p >= sizeof(SECURITY_DESCRIPTOR_RELATIVE)) {
155                 u32 sacl_offset = le32_to_cpu(descr->sacl_offset);
156                 if (sacl_offset == *size_p - sizeof(ACL)) {
157                         descr->sacl_offset = cpu_to_le32(0);
158                         *size_p -= sizeof(ACL);
159                 }
160         }
161 #endif
162 }
163
164 struct wim_security_data *
165 new_wim_security_data(void)
166 {
167         return CALLOC(1, sizeof(struct wim_security_data));
168 }
169
170 /*
171  * Reads the security data from the metadata resource of a WIM image.
172  *
173  * @metadata_resource:  An array that contains the uncompressed metadata
174  *                              resource for the WIM image.
175  * @metadata_resource_len:      The length of @metadata_resource.  It must be at
176  *                              least 8 bytes.
177  * @sd_ret:     A pointer to a pointer to a wim_security_data structure that
178  *              will be filled in with a pointer to a new wim_security_data
179  *              structure containing the security data on success.
180  *
181  * Note: There is no `offset' argument because the security data is located at
182  * the beginning of the metadata resource.
183  *
184  * Possible errors include:
185  *      WIMLIB_ERR_NOMEM
186  *      WIMLIB_ERR_INVALID_SECURITY_DATA
187  */
188 int
189 read_wim_security_data(const u8 metadata_resource[], size_t metadata_resource_len,
190                        struct wim_security_data **sd_ret)
191 {
192         struct wim_security_data *sd;
193         int ret;
194         u64 total_len;
195         u64 sizes_size;
196         u64 size_no_descriptors;
197         const struct wim_security_data_disk *sd_disk;
198         const u8 *p;
199
200         wimlib_assert(metadata_resource_len >= 8);
201
202         sd = new_wim_security_data();
203         if (!sd)
204                 goto out_of_memory;
205
206         sd_disk = (const struct wim_security_data_disk*)metadata_resource;
207         sd->total_length = le32_to_cpu(sd_disk->total_length);
208         sd->num_entries = le32_to_cpu(sd_disk->num_entries);
209
210         DEBUG("Reading security data: num_entries=%u, total_length=%u",
211               sd->num_entries, sd->total_length);
212
213         /* Length field of 0 is a special case that really means length
214          * of 8. */
215         if (sd->total_length == 0)
216                 sd->total_length = 8;
217
218         /* The security_id field of each dentry is a signed 32-bit integer, so
219          * the possible indices into the security descriptors table are 0
220          * through 0x7fffffff.  Which means 0x80000000 security descriptors
221          * maximum.  Not like you should ever have anywhere close to that many
222          * security descriptors! */
223         if (sd->num_entries > 0x80000000)
224                 goto out_invalid_sd;
225
226         /* Verify the listed total length of the security data is big enough to
227          * include the sizes array, verify that the file data is big enough to
228          * include it as well, then allocate the array of sizes.
229          *
230          * Note: The total length of the security data must fit in a 32-bit
231          * integer, even though each security descriptor size is a 64-bit
232          * integer.  This is stupid, and we need to be careful not to actually
233          * let the security descriptor sizes be over 0xffffffff.  */
234         if (sd->total_length > metadata_resource_len)
235                 goto out_invalid_sd;
236
237         sizes_size = (u64)sd->num_entries * sizeof(u64);
238         size_no_descriptors = 8 + sizes_size;
239         if (size_no_descriptors > sd->total_length)
240                 goto out_invalid_sd;
241
242         total_len = size_no_descriptors;
243
244         /* Return immediately if no security descriptors. */
245         if (sd->num_entries == 0)
246                 goto out_align_total_length;
247
248         /* Allocate a new buffer for the sizes array */
249         sd->sizes = MALLOC(sizes_size);
250         if (!sd->sizes)
251                 goto out_of_memory;
252
253         /* Copy the sizes array into the new buffer */
254         for (u32 i = 0; i < sd->num_entries; i++) {
255                 sd->sizes[i] = le64_to_cpu(sd_disk->sizes[i]);
256                 if (sd->sizes[i] > 0xffffffff)
257                         goto out_invalid_sd;
258         }
259
260         p = (const u8*)sd_disk + size_no_descriptors;
261
262         /* Allocate the array of pointers to the security descriptors, then read
263          * them into separate buffers. */
264         sd->descriptors = CALLOC(sd->num_entries, sizeof(sd->descriptors[0]));
265         if (!sd->descriptors)
266                 goto out_of_memory;
267
268         for (u32 i = 0; i < sd->num_entries; i++) {
269                 if (sd->sizes[i] == 0)
270                         continue;
271                 total_len += sd->sizes[i];
272                 if (total_len > (u64)sd->total_length)
273                         goto out_invalid_sd;
274                 sd->descriptors[i] = MALLOC(sd->sizes[i]);
275                 if (!sd->descriptors[i])
276                         goto out_of_memory;
277                 memcpy(sd->descriptors[i], p, sd->sizes[i]);
278                 p += sd->sizes[i];
279                 empty_sacl_fixup((SECURITY_DESCRIPTOR_RELATIVE*)sd->descriptors[i],
280                                  &sd->sizes[i]);
281         }
282 out_align_total_length:
283         total_len = (total_len + 7) & ~7;
284         sd->total_length = (sd->total_length + 7) & ~7;
285         if (total_len != sd->total_length) {
286                 WARNING("Expected WIM security data total length of "
287                         "%u bytes, but calculated %u bytes",
288                         sd->total_length, (unsigned)total_len);
289         }
290 out_return_sd:
291         *sd_ret = sd;
292         ret = 0;
293         goto out;
294 out_invalid_sd:
295         ERROR("WIM security data is invalid!");
296         ret = WIMLIB_ERR_INVALID_SECURITY_DATA;
297         goto out_free_sd;
298 out_of_memory:
299         ERROR("Out of memory while reading WIM security data!");
300         ret = WIMLIB_ERR_NOMEM;
301 out_free_sd:
302         free_wim_security_data(sd);
303 out:
304         return ret;
305 }
306
307 /*
308  * Writes the security data for a WIM image to an in-memory buffer.
309  */
310 u8 *
311 write_wim_security_data(const struct wim_security_data * restrict sd,
312                         u8 * restrict p)
313 {
314         DEBUG("Writing security data (total_length = %"PRIu32", num_entries "
315               "= %"PRIu32")", sd->total_length, sd->num_entries);
316
317         u8 *orig_p = p;
318         struct wim_security_data_disk *sd_disk = (struct wim_security_data_disk*)p;
319
320         sd_disk->total_length = cpu_to_le32(sd->total_length);
321         sd_disk->num_entries = cpu_to_le32(sd->num_entries);
322
323         for (u32 i = 0; i < sd->num_entries; i++)
324                 sd_disk->sizes[i] = cpu_to_le64(sd->sizes[i]);
325
326         p = (u8*)&sd_disk->sizes[sd_disk->num_entries];
327
328         for (u32 i = 0; i < sd->num_entries; i++)
329                 p = mempcpy(p, sd->descriptors[i], sd->sizes[i]);
330
331         while (p - orig_p < sd->total_length)
332                 *p++ = 0;
333
334         wimlib_assert(p - orig_p == sd->total_length);
335         wimlib_assert(((uintptr_t)p & 7) == 0);
336
337         DEBUG("Successfully wrote security data.");
338         return p;
339 }
340
341 static void
342 print_acl(const ACL *acl, const tchar *type, size_t max_size)
343 {
344         const u8 *p;
345
346         if (max_size < sizeof(ACL))
347                 return;
348
349         u8 revision = acl->revision;
350         u16 acl_size = le16_to_cpu(acl->acl_size);
351         u16 ace_count = le16_to_cpu(acl->ace_count);
352
353         tprintf(T("    [%"TS" ACL]\n"), type);
354         tprintf(T("    Revision = %u\n"), revision);
355         tprintf(T("    ACL Size = %u\n"), acl_size);
356         tprintf(T("    ACE Count = %u\n"), ace_count);
357
358         p = (const u8*)acl + sizeof(ACL);
359         for (u16 i = 0; i < ace_count; i++) {
360                 if (max_size < p + sizeof(ACCESS_ALLOWED_ACE) - (const u8*)acl)
361                         break;
362                 const ACCESS_ALLOWED_ACE *aaa = (const ACCESS_ALLOWED_ACE*)p;
363                 tprintf(T("        [ACE]\n"));
364                 tprintf(T("        ACE type  = %d\n"), aaa->hdr.type);
365                 tprintf(T("        ACE flags = 0x%x\n"), aaa->hdr.flags);
366                 tprintf(T("        ACE size  = %u\n"), le16_to_cpu(aaa->hdr.size));
367                 tprintf(T("        ACE mask = %x\n"), le32_to_cpu(aaa->mask));
368                 tprintf(T("        SID start = %u\n"), le32_to_cpu(aaa->sid_start));
369                 p += le16_to_cpu(aaa->hdr.size);
370         }
371         tputchar(T('\n'));
372 }
373
374 static void
375 print_sid(const SID *sid, const tchar *type, size_t max_size)
376 {
377         if (max_size < sizeof(SID))
378                 return;
379
380         tprintf(T("    [%"TS" SID]\n"), type);
381         tprintf(T("    Revision = %u\n"), sid->revision);
382         tprintf(T("    Subauthority count = %u\n"), sid->sub_authority_count);
383         tprintf(T("    Identifier authority = "));
384         print_byte_field(sid->identifier_authority,
385                          sizeof(sid->identifier_authority), stdout);
386         tputchar(T('\n'));
387         if (max_size < sizeof(SID) + (size_t)sid->sub_authority_count * sizeof(u32))
388                 return;
389         for (u8 i = 0; i < sid->sub_authority_count; i++) {
390                 tprintf(T("    Subauthority %u = %u\n"),
391                         i, le32_to_cpu(sid->sub_authority[i]));
392         }
393         tputchar(T('\n'));
394 }
395
396 static void
397 print_security_descriptor(const SECURITY_DESCRIPTOR_RELATIVE *descr,
398                           size_t size)
399 {
400         u8 revision      = descr->revision;
401         u16 control      = le16_to_cpu(descr->security_descriptor_control);
402         u32 owner_offset = le32_to_cpu(descr->owner_offset);
403         u32 group_offset = le32_to_cpu(descr->group_offset);
404         u32 dacl_offset  = le32_to_cpu(descr->dacl_offset);
405         u32 sacl_offset  = le32_to_cpu(descr->sacl_offset);
406
407         tprintf(T("Revision = %u\n"), revision);
408         tprintf(T("Security Descriptor Control = %#x\n"), control);
409         tprintf(T("Owner offset = %u\n"), owner_offset);
410         tprintf(T("Group offset = %u\n"), group_offset);
411         tprintf(T("Discretionary ACL offset = %u\n"), dacl_offset);
412         tprintf(T("System ACL offset = %u\n"), sacl_offset);
413
414         if (owner_offset != 0 && owner_offset <= size)
415                 print_sid((const SID*)((const u8*)descr + owner_offset),
416                           T("Owner"), size - owner_offset);
417
418         if (group_offset != 0 && group_offset <= size)
419                 print_sid((const SID*)((const u8*)descr + group_offset),
420                           T("Group"), size - group_offset);
421
422         if (dacl_offset != 0 && dacl_offset <= size)
423                 print_acl((const ACL*)((const u8*)descr + dacl_offset),
424                           T("Discretionary"), size - dacl_offset);
425
426         if (sacl_offset != 0 && sacl_offset <= size)
427                 print_acl((const ACL*)((const u8*)descr + sacl_offset),
428                           T("System"), size - sacl_offset);
429 }
430
431 /*
432  * Prints the security data for a WIM file.
433  */
434 void
435 print_wim_security_data(const struct wim_security_data *sd)
436 {
437         tputs(T("[SECURITY DATA]"));
438         tprintf(T("Length            = %"PRIu32" bytes\n"), sd->total_length);
439         tprintf(T("Number of Entries = %"PRIu32"\n"), sd->num_entries);
440
441         for (u32 i = 0; i < sd->num_entries; i++) {
442                 tprintf(T("[SECURITY_DESCRIPTOR_RELATIVE %"PRIu32", length = %"PRIu64"]\n"),
443                         i, sd->sizes[i]);
444                 print_security_descriptor((const SECURITY_DESCRIPTOR_RELATIVE*)sd->descriptors[i],
445                                           sd->sizes[i]);
446                 tputchar(T('\n'));
447         }
448         tputchar(T('\n'));
449 }
450
451 void
452 free_wim_security_data(struct wim_security_data *sd)
453 {
454         if (sd) {
455                 u8 **descriptors = sd->descriptors;
456                 u32 num_entries  = sd->num_entries;
457                 if (descriptors)
458                         while (num_entries--)
459                                 FREE(*descriptors++);
460                 FREE(sd->sizes);
461                 FREE(sd->descriptors);
462                 FREE(sd);
463         }
464 }
465
466 struct sd_node {
467         int security_id;
468         u8 hash[SHA1_HASH_SIZE];
469         struct rb_node rb_node;
470 };
471
472 static void
473 free_sd_tree(struct rb_node *node)
474 {
475         if (node) {
476                 free_sd_tree(node->rb_left);
477                 free_sd_tree(node->rb_right);
478                 FREE(container_of(node, struct sd_node, rb_node));
479         }
480 }
481
482 /* Frees a security descriptor index set. */
483 void
484 destroy_sd_set(struct wim_sd_set *sd_set, bool rollback)
485 {
486         if (rollback) {
487                 struct wim_security_data *sd = sd_set->sd;
488                 u8 **descriptors = sd->descriptors + sd_set->orig_num_entries;
489                 u32 num_entries  = sd->num_entries - sd_set->orig_num_entries;
490                 while (num_entries--)
491                         FREE(*descriptors++);
492                 sd->num_entries = sd_set->orig_num_entries;
493         }
494         free_sd_tree(sd_set->rb_root.rb_node);
495 }
496
497 /* Inserts a a new node into the security descriptor index tree. */
498 static bool
499 insert_sd_node(struct wim_sd_set *set, struct sd_node *new)
500 {
501         struct rb_root *root = &set->rb_root;
502         struct rb_node **p = &(root->rb_node);
503         struct rb_node *rb_parent = NULL;
504
505         while (*p) {
506                 struct sd_node *this = container_of(*p, struct sd_node, rb_node);
507                 int cmp = hashes_cmp(new->hash, this->hash);
508
509                 rb_parent = *p;
510                 if (cmp < 0)
511                         p = &((*p)->rb_left);
512                 else if (cmp > 0)
513                         p = &((*p)->rb_right);
514                 else
515                         return false; /* Duplicate security descriptor */
516         }
517         rb_link_node(&new->rb_node, rb_parent, p);
518         rb_insert_color(&new->rb_node, root);
519         return true;
520 }
521
522 /* Returns the index of the security descriptor having a SHA1 message digest of
523  * @hash.  If not found, return -1. */
524 int
525 lookup_sd(struct wim_sd_set *set, const u8 hash[SHA1_HASH_SIZE])
526 {
527         struct rb_node *node = set->rb_root.rb_node;
528
529         while (node) {
530                 struct sd_node *sd_node = container_of(node, struct sd_node, rb_node);
531                 int cmp = hashes_cmp(hash, sd_node->hash);
532                 if (cmp < 0)
533                         node = node->rb_left;
534                 else if (cmp > 0)
535                         node = node->rb_right;
536                 else
537                         return sd_node->security_id;
538         }
539         return -1;
540 }
541
542 /*
543  * Adds a security descriptor to the indexed security descriptor set as well as
544  * the corresponding `struct wim_security_data', and returns the new security
545  * ID; or, if there is an existing security descriptor that is the same, return
546  * the security ID for it.  If a new security descriptor cannot be allocated,
547  * return -1.
548  */
549 int
550 sd_set_add_sd(struct wim_sd_set *sd_set, const char *descriptor, size_t size)
551 {
552         u8 hash[SHA1_HASH_SIZE];
553         int security_id;
554         struct sd_node *new;
555         u8 **descriptors;
556         u64 *sizes;
557         char *descr_copy;
558         struct wim_security_data *sd;
559         bool bret;
560
561         sha1_buffer(descriptor, size, hash);
562
563         security_id = lookup_sd(sd_set, hash);
564         if (security_id >= 0) /* Identical descriptor already exists */
565                 goto out;
566
567         /* Need to add a new security descriptor */
568         security_id = -1;
569
570         new = MALLOC(sizeof(*new));
571         if (!new)
572                 goto out;
573         descr_copy = MALLOC(size);
574         if (!descr_copy)
575                 goto out_free_node;
576
577         sd = sd_set->sd;
578
579         memcpy(descr_copy, descriptor, size);
580         new->security_id = sd->num_entries;
581         copy_hash(new->hash, hash);
582
583         /* There typically are only a few dozen security descriptors in a
584          * directory tree, so expanding the array of security descriptors by
585          * only 1 extra space each time should not be a problem. */
586         descriptors = REALLOC(sd->descriptors,
587                               (sd->num_entries + 1) * sizeof(sd->descriptors[0]));
588         if (!descriptors)
589                 goto out_free_descr;
590         sd->descriptors = descriptors;
591         sizes = REALLOC(sd->sizes,
592                         (sd->num_entries + 1) * sizeof(sd->sizes[0]));
593         if (!sizes)
594                 goto out_free_descr;
595         sd->sizes = sizes;
596         sd->descriptors[sd->num_entries] = descr_copy;
597         sd->sizes[sd->num_entries] = size;
598         sd->num_entries++;
599         DEBUG("There are now %u security descriptors", sd->num_entries);
600         bret = insert_sd_node(sd_set, new);
601         wimlib_assert(bret);
602         security_id = new->security_id;
603         goto out;
604 out_free_descr:
605         FREE(descr_copy);
606 out_free_node:
607         FREE(new);
608 out:
609         return security_id;
610 }
611
612 /* Initialize a `struct sd_set' mapping from SHA1 message digests of security
613  * descriptors to indices into the security descriptors table of the WIM image
614  * (security IDs).  */
615 int
616 init_sd_set(struct wim_sd_set *sd_set, struct wim_security_data *sd)
617 {
618         int ret;
619
620         sd_set->sd = sd;
621         sd_set->rb_root.rb_node = NULL;
622
623         /* Remember the original number of security descriptors so that newly
624          * added ones can be rolled back if needed. */
625         sd_set->orig_num_entries = sd->num_entries;
626         for (u32 i = 0; i < sd->num_entries; i++) {
627                 struct sd_node *new;
628
629                 new = MALLOC(sizeof(struct sd_node));
630                 if (!new) {
631                         ret = WIMLIB_ERR_NOMEM;
632                         goto out_destroy_sd_set;
633                 }
634                 sha1_buffer(sd->descriptors[i], sd->sizes[i], new->hash);
635                 new->security_id = i;
636                 if (!insert_sd_node(sd_set, new))
637                         FREE(new); /* Ignore duplicate security descriptor */
638         }
639         ret = 0;
640         goto out;
641 out_destroy_sd_set:
642         destroy_sd_set(sd_set, false);
643 out:
644         return ret;
645 }