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.
7 * Copyright (C) 2012 Eric Biggers
9 * wimlib - Library for working with WIM files
11 * This library is free software; you can redistribute it and/or modify it under
12 * the terms of the GNU Lesser General Public License as published by the Free
13 * Software Foundation; either version 2.1 of the License, or (at your option) any
16 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
17 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
18 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License along
21 * with this library; if not, write to the Free Software Foundation, Inc., 59
22 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wimlib_internal.h"
30 * Reads the security data from the metadata resource.
32 * @metadata_resource: An array that contains the uncompressed metadata
33 * resource for the WIM file.
34 * @metadata_resource_len: The length of @metadata_resource.
35 * @sd: A pointer to a WIMSecurityData structure that is filled in with
37 * @return: True on success, false on failure.
39 * Note: There is no `offset' argument because the security data is located at
40 * the beginning of the metadata resource.
42 bool read_security_data(const u8 metadata_resource[],
43 u64 metadata_resource_len, WIMSecurityData *sd)
46 sd->descriptors = NULL;
49 if (metadata_resource_len < 8) {
50 ERROR("Not enough space in %"PRIu64"-byte file resource for "
51 "security data!\n", metadata_resource_len);
54 const u8 *p = metadata_resource;
55 p = get_u32(p, &sd->total_length);
56 p = get_u32(p, &sd->num_entries);
58 /* Verify the listed total length of the security data is big enough to
59 * include the sizes array, verify that the file data is big enough to
60 * include it as well, then allocate the array of sizes. */
61 u64 sizes_size = sd->num_entries * sizeof(u64);
63 DEBUG("Reading security data with %u entries\n", sd->num_entries);
65 if (sd->num_entries == 0) {
67 sd->descriptors = NULL;
71 u64 size_no_descriptors = 8 + sizes_size;
72 if (size_no_descriptors > sd->total_length) {
73 ERROR("Security data total length of %"PRIu64" is too short "
74 "because there must be at least %"PRIu64" bytes of security "
75 "data!\n", sd->total_length,
79 if (size_no_descriptors > metadata_resource_len) {
80 ERROR("File resource of %"PRIu64" bytes is not big enough "
81 "to hold security data of at least %"PRIu64" "
82 "bytes!\n", metadata_resource_len, size_no_descriptors);
85 sd->sizes = xmalloc(sizes_size);
87 /* Copy the sizes array in from the file data. */
88 p = get_bytes(p, sizes_size, sd->sizes);
89 array_to_le64(sd->sizes, sd->num_entries);
91 /* Allocate the array of pointers to descriptors, and read them in. */
92 sd->descriptors = xmalloc(sd->num_entries * sizeof(u8*));
93 u64 total_len = size_no_descriptors;
95 for (uint i = 0; i < sd->num_entries; i++) {
97 total_len += sd->sizes[i];
98 if (total_len > sd->total_length) {
99 ERROR("Security data total length of %"PRIu64" is too "
100 "short because there are at least %"PRIu64" "
101 "bytes of security data!\n",
102 sd->total_length, total_len);
106 if (total_len > metadata_resource_len) {
108 ERROR("File resource of %"PRIu64" bytes is not big enough "
109 "to hold security data of at least %"PRIu64" "
110 "bytes!\n", metadata_resource_len, total_len);
113 sd->descriptors[i] = xmalloc(sd->sizes[i]);
114 p = get_bytes(p, sd->sizes[i], sd->descriptors[i]);
117 /* The total_length field seems to take into account padding for
118 * quadword alignment of the dentry following it, so we can ignore the
119 * case where the actual length read so far is less than the specified
120 * total length of the security data. */
122 if (total_len < sd->total_length) {
123 /*ERROR("Warning: security data was actually %"PRIu64" bytes, but "*/
124 /*"it says its length is %"PRIu64" bytes!\n",*/
125 /*total_len, sd->total_length);*/
133 * Writes the security data to the output file.
135 * @sd: The security data structure.
136 * @out: The FILE* for the output file.
137 * @return: True on success, false on failure.
139 u8 *write_security_data(const WIMSecurityData *sd, u8 *p)
141 DEBUG("Writing security data (total_length = %u, num_entries = %u)\n",
142 sd->total_length, sd->num_entries);
144 p = put_u32(p, sd->total_length);
145 p = put_u32(p, sd->num_entries);
147 for (uint i = 0; i < sd->num_entries; i++)
148 p = put_u64(p, sd->sizes[i]);
150 for (uint i = 0; i < sd->num_entries; i++)
151 p = put_bytes(p, sd->sizes[i], sd->descriptors[i]);
153 wimlib_assert(p - orig_p <= sd->total_length);
155 DEBUG("Successfully wrote security data.\n");
156 return orig_p + sd->total_length;
159 /* XXX We don't actually do anything with the ACL's yet besides being able to
160 * print a few things. It seems it would be a lot of work to have comprehensive
161 * support for all the weird flags and stuff, and Windows PE seems to be okay
162 * running from a WIM file that doesn't have any security data at all... */
164 static void print_acl(const u8 *p)
167 TO_LE16(acl->acl_size);
168 TO_LE16(acl->acl_count);
170 printf(" Revision = %u\n", acl->revision);
171 printf(" ACL Size = %u\n", acl->acl_size);
172 printf(" ACE Count = %u\n", acl->ace_count);
175 for (uint i = 0; i < acl->ace_count; i++) {
176 ACEHeader *hdr = (ACEHeader*)p;
178 printf(" ACE type = %d\n", hdr->type);
179 printf(" ACE flags = 0x%x\n", hdr->flags);
180 printf(" ACE size = %u\n", hdr->size);
181 AccessAllowedACE *aaa = (AccessAllowedACE*)hdr;
182 printf(" ACE mask = %x\n", to_le32(aaa->mask));
183 printf(" SID start = %u\n", to_le32(aaa->sid_start));
188 static void print_sid(const u8 *p)
192 printf(" Revision = %u\n", sid->revision);
193 printf(" Subauthority count = %u\n", sid->sub_authority_count);
194 printf(" Identifier authority = ");
195 print_byte_field(sid->identifier_authority, sizeof(sid->identifier_authority));
197 for (uint i = 0; i < sid->sub_authority_count; i++)
198 printf(" Subauthority %u = %u\n", i, to_le32(sid->sub_authority[i]));
201 static void print_security_descriptor(const u8 *p, u64 size)
203 SecurityDescriptor *sd = (SecurityDescriptor*)p;
204 TO_LE16(sd->security_descriptor_control);
205 TO_LE32(sd->owner_offset);
206 TO_LE32(sd->group_offset);
207 TO_LE32(sd->sacl_offset);
208 TO_LE32(sd->dacl_offset);
209 printf("Revision = %u\n", sd->revision);
210 printf("Security Descriptor Control = %u\n", sd->security_descriptor_control);
211 printf("Owner offset = %u\n", sd->owner_offset);
212 printf("Group offset = %u\n", sd->group_offset);
213 printf("System ACL offset = %u\n", sd->sacl_offset);
214 printf("Discretionary ACL offset = %u\n", sd->dacl_offset);
216 if (sd->owner_offset != 0)
217 print_sid(p + sd->owner_offset);
218 if (sd->group_offset != 0)
219 print_sid(p + sd->group_offset);
220 if (sd->sacl_offset != 0)
221 print_acl(p + sd->sacl_offset);
222 if (sd->dacl_offset != 0)
223 print_acl(p + sd->dacl_offset);
227 * Prints the security data for a WIM file.
229 * @sd: A pointer to the WIMSecurityData structure.
231 void print_security_data(const WIMSecurityData *sd)
233 puts("[SECURITY DATA]");
234 printf("Length = %u bytes\n", sd->total_length);
235 printf("Number of Entries = %u\n", sd->num_entries);
237 u64 num_entries = (u64)sd->num_entries;
238 for (u64 i = 0; i < num_entries; i++) {
239 printf("[SecurityDescriptor %"PRIu64", length = %"PRIu64"]\n", i,
241 print_security_descriptor(sd->descriptors[i], sd->sizes[i]);
247 void init_security_data(WIMSecurityData *sd)
249 sd->total_length = 8;
252 sd->descriptors = NULL;
253 /* XXX figure out what the security descriptors actually do */
256 void destroy_security_data(WIMSecurityData *sd)
258 u8 **descriptors = sd->descriptors;
259 u32 num_entries = sd->num_entries;
260 while (num_entries--)
261 FREE(*descriptors++);
265 FREE(sd->descriptors);
266 sd->descriptors = NULL;