4 * Read and write the per-WIM-image table of security descriptors.
8 * Copyright (C) 2012, 2013 Eric Biggers
10 * This file is part of wimlib, a library for working with WIM files.
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)
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
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/.
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"
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. */
42 /* bitwise OR of the inherit ACE flags #defined above */
45 /* Size of the access control entry. */
47 } _packed_attribute ACE_HEADER;
49 /* Grants rights to a user or group */
50 typedef struct _ACCESS_ALLOWED_ACE {
54 } _packed_attribute ACCESS_ALLOWED_ACE;
56 /* Denies rights to a user or group */
57 typedef struct _ACCESS_DENIED_ACE {
61 } _packed_attribute ACCESS_DENIED_ACE;
63 typedef struct _SYSTEM_AUDIT_ACE {
67 } _packed_attribute SYSTEM_AUDIT_ACE;
70 /* Header of an access control list. */
72 /* ACL_REVISION or ACL_REVISION_DS */
78 /* Total size of the ACL, including all access control entries */
81 /* Number of access control entry structures that follow the ACL
87 } _packed_attribute ACL;
89 /* A structure used to identify users or groups. */
94 u8 sub_authority_count;
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];
100 le32 sub_authority[];
101 } _packed_attribute SID;
103 typedef struct _SECURITY_DESCRIPTOR_RELATIVE {
109 /* Example: 0x4149 */
110 le16 security_descriptor_control;
112 /* Offset of a SID structure in the security descriptor. */
116 /* Offset of a SID structure in the security descriptor. */
120 /* Offset of an ACL structure in the security descriptor. */
125 /* Offset of an ACL structure in the security descriptor. */
126 /* Discretionary ACL. */
129 } _packed_attribute SECURITY_DESCRIPTOR_RELATIVE;
131 struct wim_security_data_disk {
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.
149 empty_sacl_fixup(SECURITY_DESCRIPTOR_RELATIVE *descr, size_t *size_p)
151 /* No-op if no NTFS-3g support, or if NTFS-3g is version 2013 or later
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);
164 struct wim_security_data *
165 new_wim_security_data(void)
167 return CALLOC(1, sizeof(struct wim_security_data));
171 * Reads the security data from the metadata resource of a WIM image.
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
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.
181 * Note: There is no `offset' argument because the security data is located at
182 * the beginning of the metadata resource.
184 * Possible errors include:
186 * WIMLIB_ERR_INVALID_SECURITY_DATA
189 read_wim_security_data(const u8 metadata_resource[], size_t metadata_resource_len,
190 struct wim_security_data **sd_ret)
192 struct wim_security_data *sd;
196 u64 size_no_descriptors;
197 const struct wim_security_data_disk *sd_disk;
200 wimlib_assert(metadata_resource_len >= 8);
202 sd = new_wim_security_data();
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);
210 DEBUG("Reading security data: num_entries=%u, total_length=%u",
211 sd->num_entries, sd->total_length);
213 /* Length field of 0 is a special case that really means length
215 if (sd->total_length == 0)
216 sd->total_length = 8;
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)
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.
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)
237 sizes_size = (u64)sd->num_entries * sizeof(u64);
238 size_no_descriptors = 8 + sizes_size;
239 if (size_no_descriptors > sd->total_length)
242 total_len = size_no_descriptors;
244 /* Return immediately if no security descriptors. */
245 if (sd->num_entries == 0)
246 goto out_align_total_length;
248 /* Allocate a new buffer for the sizes array */
249 sd->sizes = MALLOC(sizes_size);
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)
260 p = (const u8*)sd_disk + size_no_descriptors;
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)
268 for (u32 i = 0; i < sd->num_entries; i++) {
269 if (sd->sizes[i] == 0)
271 total_len += sd->sizes[i];
272 if (total_len > (u64)sd->total_length)
274 sd->descriptors[i] = MALLOC(sd->sizes[i]);
275 if (!sd->descriptors[i])
277 memcpy(sd->descriptors[i], p, sd->sizes[i]);
279 empty_sacl_fixup((SECURITY_DESCRIPTOR_RELATIVE*)sd->descriptors[i],
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);
295 ERROR("WIM security data is invalid!");
296 ret = WIMLIB_ERR_INVALID_SECURITY_DATA;
299 ERROR("Out of memory while reading WIM security data!");
300 ret = WIMLIB_ERR_NOMEM;
302 free_wim_security_data(sd);
308 * Writes the security data for a WIM image to an in-memory buffer.
311 write_wim_security_data(const struct wim_security_data * restrict sd,
314 DEBUG("Writing security data (total_length = %"PRIu32", num_entries "
315 "= %"PRIu32")", sd->total_length, sd->num_entries);
318 struct wim_security_data_disk *sd_disk = (struct wim_security_data_disk*)p;
320 sd_disk->total_length = cpu_to_le32(sd->total_length);
321 sd_disk->num_entries = cpu_to_le32(sd->num_entries);
323 for (u32 i = 0; i < sd->num_entries; i++)
324 sd_disk->sizes[i] = cpu_to_le64(sd->sizes[i]);
326 p = (u8*)&sd_disk->sizes[sd_disk->num_entries];
328 for (u32 i = 0; i < sd->num_entries; i++)
329 p = mempcpy(p, sd->descriptors[i], sd->sizes[i]);
331 while (p - orig_p < sd->total_length)
334 wimlib_assert(p - orig_p == sd->total_length);
335 wimlib_assert(((uintptr_t)p & 7) == 0);
337 DEBUG("Successfully wrote security data.");
342 print_acl(const ACL *acl, const tchar *type, size_t max_size)
346 if (max_size < sizeof(ACL))
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);
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);
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)
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);
375 print_sid(const SID *sid, const tchar *type, size_t max_size)
377 if (max_size < sizeof(SID))
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);
387 if (max_size < sizeof(SID) + (size_t)sid->sub_authority_count * sizeof(u32))
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]));
397 print_security_descriptor(const SECURITY_DESCRIPTOR_RELATIVE *descr,
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);
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);
414 if (owner_offset != 0 && owner_offset <= size)
415 print_sid((const SID*)((const u8*)descr + owner_offset),
416 T("Owner"), size - owner_offset);
418 if (group_offset != 0 && group_offset <= size)
419 print_sid((const SID*)((const u8*)descr + group_offset),
420 T("Group"), size - group_offset);
422 if (dacl_offset != 0 && dacl_offset <= size)
423 print_acl((const ACL*)((const u8*)descr + dacl_offset),
424 T("Discretionary"), size - dacl_offset);
426 if (sacl_offset != 0 && sacl_offset <= size)
427 print_acl((const ACL*)((const u8*)descr + sacl_offset),
428 T("System"), size - sacl_offset);
432 * Prints the security data for a WIM file.
435 print_wim_security_data(const struct wim_security_data *sd)
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);
441 for (u32 i = 0; i < sd->num_entries; i++) {
442 tprintf(T("[SECURITY_DESCRIPTOR_RELATIVE %"PRIu32", length = %"PRIu64"]\n"),
444 print_security_descriptor((const SECURITY_DESCRIPTOR_RELATIVE*)sd->descriptors[i],
452 free_wim_security_data(struct wim_security_data *sd)
455 u8 **descriptors = sd->descriptors;
456 u32 num_entries = sd->num_entries;
458 while (num_entries--)
459 FREE(*descriptors++);
461 FREE(sd->descriptors);
468 u8 hash[SHA1_HASH_SIZE];
469 struct rb_node rb_node;
473 free_sd_tree(struct rb_node *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));
482 /* Frees a security descriptor index set. */
484 destroy_sd_set(struct wim_sd_set *sd_set, bool 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;
494 free_sd_tree(sd_set->rb_root.rb_node);
497 /* Inserts a a new node into the security descriptor index tree. */
499 insert_sd_node(struct wim_sd_set *set, struct sd_node *new)
501 struct rb_root *root = &set->rb_root;
502 struct rb_node **p = &(root->rb_node);
503 struct rb_node *rb_parent = NULL;
506 struct sd_node *this = container_of(*p, struct sd_node, rb_node);
507 int cmp = hashes_cmp(new->hash, this->hash);
511 p = &((*p)->rb_left);
513 p = &((*p)->rb_right);
515 return false; /* Duplicate security descriptor */
517 rb_link_node(&new->rb_node, rb_parent, p);
518 rb_insert_color(&new->rb_node, root);
522 /* Returns the index of the security descriptor having a SHA1 message digest of
523 * @hash. If not found, return -1. */
525 lookup_sd(struct wim_sd_set *set, const u8 hash[SHA1_HASH_SIZE])
527 struct rb_node *node = set->rb_root.rb_node;
530 struct sd_node *sd_node = container_of(node, struct sd_node, rb_node);
531 int cmp = hashes_cmp(hash, sd_node->hash);
533 node = node->rb_left;
535 node = node->rb_right;
537 return sd_node->security_id;
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,
550 sd_set_add_sd(struct wim_sd_set *sd_set, const char *descriptor, size_t size)
552 u8 hash[SHA1_HASH_SIZE];
558 struct wim_security_data *sd;
561 sha1_buffer(descriptor, size, hash);
563 security_id = lookup_sd(sd_set, hash);
564 if (security_id >= 0) /* Identical descriptor already exists */
567 /* Need to add a new security descriptor */
570 new = MALLOC(sizeof(*new));
573 descr_copy = MALLOC(size);
579 memcpy(descr_copy, descriptor, size);
580 new->security_id = sd->num_entries;
581 copy_hash(new->hash, hash);
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]));
590 sd->descriptors = descriptors;
591 sizes = REALLOC(sd->sizes,
592 (sd->num_entries + 1) * sizeof(sd->sizes[0]));
596 sd->descriptors[sd->num_entries] = descr_copy;
597 sd->sizes[sd->num_entries] = size;
599 DEBUG("There are now %u security descriptors", sd->num_entries);
600 bret = insert_sd_node(sd_set, new);
602 security_id = new->security_id;
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
616 init_sd_set(struct wim_sd_set *sd_set, struct wim_security_data *sd)
621 sd_set->rb_root.rb_node = NULL;
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++) {
629 new = MALLOC(sizeof(struct sd_node));
631 ret = WIMLIB_ERR_NOMEM;
632 goto out_destroy_sd_set;
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 */
642 destroy_sd_set(sd_set, false);