4 * Read the security data from the WIM. Doing anything with the security data
5 * is not yet implemented other than printing some information about it.
9 * Copyright (C) 2012 Eric Biggers
11 * This file is part of wimlib, a library for working with WIM files.
13 * wimlib is free software; you can redistribute it and/or modify it under the
14 * terms of the GNU Lesser General Public License as published by the Free
15 * Software Foundation; either version 2.1 of the License, or (at your option)
18 * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
19 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
20 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with wimlib; if not, see http://www.gnu.org/licenses/.
27 #include "wimlib_internal.h"
31 #ifdef ENABLE_SECURITY_DATA
34 * Reads the security data from the metadata resource.
36 * @metadata_resource: An array that contains the uncompressed metadata
37 * resource for the WIM file.
38 * @metadata_resource_len: The length of @metadata_resource.
39 * @sd_p: A pointer to a pointer wim_security_data structure that will be filled
40 * in with a pointer to a new wim_security_data structure on success.
42 * Note: There is no `offset' argument because the security data is located at
43 * the beginning of the metadata resource.
45 int read_security_data(const u8 metadata_resource[],
46 u64 metadata_resource_len, struct wim_security_data **sd_p)
48 struct wim_security_data *sd;
52 if (metadata_resource_len < 8) {
53 ERROR("Not enough space in %"PRIu64"-byte file resource for "
54 "security data!\n", metadata_resource_len);
55 return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
57 sd = MALLOC(sizeof(struct wim_security_data));
59 return WIMLIB_ERR_NOMEM;
60 p = get_u32(metadata_resource, &sd->total_length);
61 p = get_u32(p, &sd->num_entries);
63 /* Verify the listed total length of the security data is big enough to
64 * include the sizes array, verify that the file data is big enough to
65 * include it as well, then allocate the array of sizes. */
66 sizes_size = sd->num_entries * sizeof(u64);
68 DEBUG("Reading security data with %u entries\n", sd->num_entries);
70 if (sd->num_entries == 0) {
75 u64 size_no_descriptors = 8 + sizes_size;
76 if (size_no_descriptors > sd->total_length) {
77 ERROR("Security data total length of %"PRIu64" is too short because\n"
78 "there must be at least %"PRIu64" bytes of security "
79 "data!\n", sd->total_length,
82 return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
84 if (size_no_descriptors > metadata_resource_len) {
85 ERROR("File resource of %"PRIu64" bytes is not big enough\n"
86 "to hold security data of at least %"PRIu64" "
87 "bytes!\n", metadata_resource_len, size_no_descriptors);
89 return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
91 sd->sizes = MALLOC(sizes_size);
94 return WIMLIB_ERR_NOMEM;
97 /* Copy the sizes array in from the file data. */
98 p = get_bytes(p, sizes_size, sd->sizes);
99 array_to_le64(sd->sizes, sd->num_entries);
101 /* Allocate the array of pointers to descriptors, and read them in. */
102 sd->descriptors = CALLOC(sd->num_entries, sizeof(u8*));
103 if (!sd->descriptors) {
106 return WIMLIB_ERR_NOMEM;
108 u64 total_len = size_no_descriptors;
110 for (uint i = 0; i < sd->num_entries; i++) {
111 total_len += sd->sizes[i];
112 if (total_len > sd->total_length) {
113 ERROR("Security data total length of %"PRIu64" is too "
114 "short because there are at least %"PRIu64" "
115 "bytes of security data!\n",
116 sd->total_length, total_len);
117 free_security_data(sd);
118 return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
120 if (total_len > metadata_resource_len) {
121 ERROR("File resource of %"PRIu64" bytes is not big enough "
122 "to hold security data of at least %"PRIu64" "
123 "bytes!\n", metadata_resource_len, total_len);
124 free_security_data(sd);
125 return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
127 sd->descriptors[i] = MALLOC(sd->sizes[i]);
128 if (!sd->descriptors[i]) {
129 free_security_data(sd);
130 return WIMLIB_ERR_NOMEM;
132 p = get_bytes(p, sd->sizes[i], sd->descriptors[i]);
140 * Writes security data to an in-memory buffer.
142 u8 *write_security_data(const struct wim_security_data *sd, u8 *p)
145 DEBUG("Writing security data (total_length = %u, "
146 "num_entries = %u)\n", sd->total_length,
149 p = put_u32(p, sd->total_length);
150 p = put_u32(p, sd->num_entries);
152 for (uint i = 0; i < sd->num_entries; i++)
153 p = put_u64(p, sd->sizes[i]);
155 for (uint i = 0; i < sd->num_entries; i++)
156 p = put_bytes(p, sd->sizes[i], sd->descriptors[i]);
158 wimlib_assert(p - orig_p <= sd->total_length);
160 DEBUG("Successfully wrote security data.\n");
161 return orig_p + sd->total_length;
163 DEBUG("Writing security data (total_length = 8, "
164 "num_entries = 0)\n");
166 return put_u32(p, 0);
171 /* XXX We don't actually do anything with the ACL's yet besides being able to
172 * print a few things. It seems it would be a lot of work to have comprehensive
173 * support for all the weird flags and stuff, and Windows PE seems to be okay
174 * running from a WIM file that doesn't have any security data at all... */
176 static void print_acl(const u8 *p)
179 TO_LE16(acl->acl_size);
180 TO_LE16(acl->acl_count);
182 printf(" Revision = %u\n", acl->revision);
183 printf(" ACL Size = %u\n", acl->acl_size);
184 printf(" ACE Count = %u\n", acl->ace_count);
187 for (uint i = 0; i < acl->ace_count; i++) {
188 ACEHeader *hdr = (ACEHeader*)p;
190 printf(" ACE type = %d\n", hdr->type);
191 printf(" ACE flags = 0x%x\n", hdr->flags);
192 printf(" ACE size = %u\n", hdr->size);
193 AccessAllowedACE *aaa = (AccessAllowedACE*)hdr;
194 printf(" ACE mask = %x\n", to_le32(aaa->mask));
195 printf(" SID start = %u\n", to_le32(aaa->sid_start));
200 static void print_sid(const u8 *p)
204 printf(" Revision = %u\n", sid->revision);
205 printf(" Subauthority count = %u\n", sid->sub_authority_count);
206 printf(" Identifier authority = ");
207 print_byte_field(sid->identifier_authority, sizeof(sid->identifier_authority));
209 for (uint i = 0; i < sid->sub_authority_count; i++)
210 printf(" Subauthority %u = %u\n", i, to_le32(sid->sub_authority[i]));
213 static void print_security_descriptor(const u8 *p, u64 size)
215 SecurityDescriptor *sd = (SecurityDescriptor*)p;
216 TO_LE16(sd->security_descriptor_control);
217 TO_LE32(sd->owner_offset);
218 TO_LE32(sd->group_offset);
219 TO_LE32(sd->sacl_offset);
220 TO_LE32(sd->dacl_offset);
221 printf("Revision = %u\n", sd->revision);
222 printf("Security Descriptor Control = %u\n", sd->security_descriptor_control);
223 printf("Owner offset = %u\n", sd->owner_offset);
224 printf("Group offset = %u\n", sd->group_offset);
225 printf("System ACL offset = %u\n", sd->sacl_offset);
226 printf("Discretionary ACL offset = %u\n", sd->dacl_offset);
228 if (sd->owner_offset != 0)
229 print_sid(p + sd->owner_offset);
230 if (sd->group_offset != 0)
231 print_sid(p + sd->group_offset);
232 if (sd->sacl_offset != 0)
233 print_acl(p + sd->sacl_offset);
234 if (sd->dacl_offset != 0)
235 print_acl(p + sd->dacl_offset);
239 * Prints the security data for a WIM file.
241 void print_security_data(const struct wim_security_data *sd)
243 puts("[SECURITY DATA]");
245 printf("Length = %u bytes\n", sd->total_length);
246 printf("Number of Entries = %u\n", sd->num_entries);
248 u64 num_entries = (u64)sd->num_entries;
249 for (u64 i = 0; i < num_entries; i++) {
250 printf("[SecurityDescriptor %"PRIu64", "
251 "length = %"PRIu64"]\n",
253 print_security_descriptor(sd->descriptors[i],
258 puts("Length = 8 bytes\n"
259 "Number of Entries = 0");
264 void free_security_data(struct wim_security_data *sd)
268 wimlib_assert(sd->refcnt >= 1);
269 if (sd->refcnt == 1) {
270 u8 **descriptors = sd->descriptors;
271 u32 num_entries = sd->num_entries;
274 while (num_entries--)
275 FREE(*descriptors++);
277 FREE(sd->descriptors);