]> cygwin.com Git - cygwin-apps/setup.git/blob - win32.cc
Support xz and lzma decompression via liblzma
[cygwin-apps/setup.git] / win32.cc
1 /*
2 * Copyright (c) 2007 Brian Dessent
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by Brian Dessent <brian@dessent.net>
13 *
14 */
15
16 #if 0
17 static const char *cvsid =
18 "\n%%% $Id$\n";
19 #endif
20
21 #include "win32.h"
22 #include <memory>
23 #include <malloc.h>
24 #include "LogFile.h"
25 #include "resource.h"
26 #include "state.h"
27 #include "ini.h"
28 #include <sys/stat.h>
29
30 NTSecurity nt_sec;
31
32 PSECURITY_DESCRIPTOR
33 NTSecurity::GetPosixPerms (const char *fname, PSID owner_sid, PSID group_sid,
34 mode_t mode, SECURITY_DESCRIPTOR &out_sd, acl_t &acl)
35 {
36 DWORD u_attribute, g_attribute, o_attribute;
37 DWORD offset = 0;
38
39 if (is_legacy)
40 return NULL;
41
42 /* Initialize out SD */
43 if (!InitializeSecurityDescriptor (&out_sd, SECURITY_DESCRIPTOR_REVISION))
44 log (LOG_TIMESTAMP) << "InitializeSecurityDescriptor(" << fname
45 << ") failed: " << GetLastError () << endLog;
46 if (OSMajorVersion () >= 5)
47 out_sd.Control |= SE_DACL_PROTECTED;
48
49 /* Initialize ACL and fill with almost POSIX-like permissions.
50 Note that the current user always requires write permissions, otherwise
51 creating files in directories with restricted permissions fails. */
52 if (!InitializeAcl (&acl.acl , sizeof acl, ACL_REVISION))
53 log (LOG_TIMESTAMP) << "InitializeAcl(" << fname << ") failed: "
54 << GetLastError () << endLog;
55 /* USER */
56 /* Default user to current user. */
57 if (!owner_sid)
58 owner_sid = ownerSID.user.User.Sid;
59 u_attribute = STANDARD_RIGHTS_ALL | FILE_GENERIC_READ | FILE_GENERIC_WRITE;
60 if (mode & 0100) // S_IXUSR
61 u_attribute |= FILE_GENERIC_EXECUTE;
62 if ((mode & 0300) == 0300) // S_IWUSR | S_IXUSR
63 u_attribute |= FILE_DELETE_CHILD;
64 if (!AddAccessAllowedAce (&acl.acl, ACL_REVISION, u_attribute, owner_sid))
65 log (LOG_TIMESTAMP) << "AddAccessAllowedAce(" << fname
66 << ", owner) failed: " << GetLastError () << endLog;
67 else
68 offset++;
69 /* GROUP */
70 /* Default group to current primary group. */
71 if (!group_sid)
72 group_sid = groupSID;
73 g_attribute = STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES;
74 if (mode & 0040) // S_IRGRP
75 g_attribute |= FILE_GENERIC_READ;
76 if (mode & 0020) // S_IWGRP
77 g_attribute |= FILE_GENERIC_WRITE;
78 if (mode & 0010) // S_IXGRP
79 g_attribute |= FILE_GENERIC_EXECUTE;
80 if ((mode & 01030) == 00030) // S_IWGRP | S_IXGRP, !S_ISVTX
81 g_attribute |= FILE_DELETE_CHILD;
82 if (!AddAccessAllowedAce (&acl.acl, ACL_REVISION, g_attribute, group_sid))
83 log (LOG_TIMESTAMP) << "AddAccessAllowedAce(" << fname
84 << ", group) failed: " << GetLastError () << endLog;
85 else
86 offset++;
87 /* OTHER */
88 o_attribute = STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES;
89 if (mode & 0004) // S_IROTH
90 o_attribute |= FILE_GENERIC_READ;
91 if (mode & 0002) // S_IWOTH
92 o_attribute |= FILE_GENERIC_WRITE;
93 if (mode & 0001) // S_IXOTH
94 o_attribute |= FILE_GENERIC_EXECUTE;
95 if ((mode & 01003) == 00003) // S_IWOTH | S_IXOTH, !S_ISVTX
96 o_attribute |= FILE_DELETE_CHILD;
97 if (!AddAccessAllowedAce (&acl.acl, ACL_REVISION, o_attribute,
98 everyOneSID.theSID ()))
99 log (LOG_TIMESTAMP) << "AddAccessAllowedAce(" << fname
100 << ", everyone) failed: " << GetLastError () << endLog;
101 else
102 offset++;
103 if (mode & 07000) /* At least one of S_ISUID, S_ISGID, S_ISVTX */
104 {
105 DWORD attribute = 0;
106 if (mode & 04000) // S_ISUID
107 attribute |= FILE_APPEND_DATA;
108 if (mode & 02000) // S_ISGID
109 attribute |= FILE_WRITE_DATA;
110 if (mode & 01000) // S_ISVTX
111 attribute |= FILE_READ_DATA;
112 if (!AddAccessAllowedAce (&acl.acl, ACL_REVISION, attribute,
113 nullSID.theSID ()))
114 log (LOG_TIMESTAMP) << "AddAccessAllowedAce(" << fname
115 << ", null) failed: " << GetLastError () << endLog;
116 else
117 offset++;
118 }
119 /* For directories, we also add inherit-only ACEs for CREATOR OWNER,
120 CREATOR GROUP, and EVERYONE (aka OTHER). */
121 if (mode & S_IFDIR)
122 {
123 if (!AddAccessAllowedAce (&acl.acl, ACL_REVISION, u_attribute,
124 cr_ownerSID.theSID ()))
125 log (LOG_TIMESTAMP) << "AddAccessAllowedAce(" << fname
126 << ", creator owner) failed: "
127 << GetLastError () << endLog;
128 else
129 {
130 ACCESS_ALLOWED_ACE *ace;
131 if (GetAce (&acl.acl, offset, (PVOID *) &ace))
132 ace->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
133 | INHERIT_ONLY_ACE;
134 offset++;
135 }
136 if (!AddAccessAllowedAce (&acl.acl, ACL_REVISION, g_attribute,
137 cr_groupSID.theSID ()))
138 log (LOG_TIMESTAMP) << "AddAccessAllowedAce(" << fname
139 << ", creator group) failed: "
140 << GetLastError () << endLog;
141 else
142 {
143 ACCESS_ALLOWED_ACE *ace;
144 if (GetAce (&acl.acl, offset, (PVOID *) &ace))
145 ace->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
146 | INHERIT_ONLY_ACE;
147 offset++;
148 }
149 if (!AddAccessAllowedAce (&acl.acl, ACL_REVISION, o_attribute,
150 everyOneSID.theSID ()))
151 log (LOG_TIMESTAMP) << "AddAccessAllowedAce(" << fname
152 << ", everyone inherit) failed: "
153 << GetLastError () << endLog;
154 else
155 {
156 ACCESS_ALLOWED_ACE *ace;
157 if (GetAce (&acl.acl, offset, (PVOID *) &ace))
158 ace->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
159 | INHERIT_ONLY_ACE;
160 offset++;
161 }
162 }
163
164 /* Set SD's DACL to just created ACL. */
165 if (!SetSecurityDescriptorDacl (&out_sd, TRUE, &acl.acl, FALSE))
166 log (LOG_TIMESTAMP) << "SetSecurityDescriptorDacl(" << fname
167 << ") failed: " << GetLastError () << endLog;
168 return &out_sd;
169 }
170
171 void
172 NTSecurity::NoteFailedAPI (const std::string &api)
173 {
174 log (LOG_TIMESTAMP) << api << "() failed: " << GetLastError () << endLog;
175 }
176
177 void
178 NTSecurity::initialiseWellKnownSIDs ()
179 {
180 SID_IDENTIFIER_AUTHORITY n_sid_auth = { SECURITY_NULL_SID_AUTHORITY };
181 /* Get the SID for "NULL" S-1-0-0 */
182 if (!AllocateAndInitializeSid (&n_sid_auth, 1, SECURITY_NULL_RID,
183 0, 0, 0, 0, 0, 0, 0, &nullSID.theSID ()))
184 {
185 NoteFailedAPI ("AllocateAndInitializeSid(null)");
186 return;
187 }
188 SID_IDENTIFIER_AUTHORITY e_sid_auth = { SECURITY_WORLD_SID_AUTHORITY };
189 /* Get the SID for "Everyone" S-1-1-0 */
190 if (!AllocateAndInitializeSid (&e_sid_auth, 1, SECURITY_WORLD_RID,
191 0, 0, 0, 0, 0, 0, 0, &everyOneSID.theSID ()))
192 {
193 NoteFailedAPI ("AllocateAndInitializeSid(everyone)");
194 return;
195 }
196 SID_IDENTIFIER_AUTHORITY nt_sid_auth = { SECURITY_NT_AUTHORITY };
197 /* Get the SID for "Administrators" S-1-5-32-544 */
198 if (!AllocateAndInitializeSid (&nt_sid_auth, 2, SECURITY_BUILTIN_DOMAIN_RID,
199 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
200 &administratorsSID.theSID ()))
201 {
202 NoteFailedAPI ("AllocateAndInitializeSid(admins)");
203 return;
204 }
205 /* Get the SID for "Users" S-1-5-32-545 */
206 if (!AllocateAndInitializeSid (&nt_sid_auth, 2, SECURITY_BUILTIN_DOMAIN_RID,
207 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0,
208 &usersSID.theSID ()))
209 {
210 NoteFailedAPI ("AllocateAndInitializeSid(users)");
211 return;
212 }
213 SID_IDENTIFIER_AUTHORITY c_sid_auth = { SECURITY_CREATOR_SID_AUTHORITY };
214 /* Get the SID for "CREATOR OWNER" S-1-3-0 */
215 if (!AllocateAndInitializeSid (&c_sid_auth, 1, SECURITY_CREATOR_OWNER_RID,
216 0, 0, 0, 0, 0, 0, 0, &cr_ownerSID.theSID ()))
217 {
218 NoteFailedAPI ("AllocateAndInitializeSid(users)");
219 return;
220 }
221 /* Get the SID for "CREATOR GROUP" S-1-3-1 */
222 if (!AllocateAndInitializeSid (&c_sid_auth, 1, SECURITY_CREATOR_GROUP_RID,
223 0, 0, 0, 0, 0, 0, 0, &cr_groupSID.theSID ()))
224 {
225 NoteFailedAPI ("AllocateAndInitializeSid(users)");
226 return;
227 }
228 wellKnownSIDsinitialized (true);
229 }
230
231 void
232 NTSecurity::setDefaultDACL ()
233 {
234 /* To assure that the created files have a useful ACL, the
235 default DACL in the process token is set to full access to
236 everyone. This applies to files and subdirectories created
237 in directories which don't propagate permissions to child
238 objects.
239 To assure that the files group is meaningful, a token primary
240 group of None is changed to Users or Administrators.
241 This is the fallback if real POSIX permissions don't
242 work for some reason. */
243
244 /* Create a buffer which has enough room to contain the TOKEN_DEFAULT_DACL
245 structure plus an ACL with one ACE. */
246 size_t bufferSize = sizeof (ACL) + sizeof (ACCESS_ALLOWED_ACE)
247 + GetLengthSid (everyOneSID.theSID ()) - sizeof (DWORD);
248
249 std::auto_ptr<char> buf (new char[bufferSize]);
250
251 /* First initialize the TOKEN_DEFAULT_DACL structure. */
252 PACL dacl = (PACL) buf.get ();
253
254 /* Initialize the ACL for containing one ACE. */
255 if (!InitializeAcl (dacl, bufferSize, ACL_REVISION))
256 {
257 NoteFailedAPI ("InitializeAcl");
258 return;
259 }
260
261 /* Create the ACE which grants full access to "Everyone" and store it
262 in dacl. */
263 if (!AddAccessAllowedAce
264 (dacl, ACL_REVISION, GENERIC_ALL, everyOneSID.theSID ()))
265 {
266 NoteFailedAPI ("AddAccessAllowedAce");
267 return;
268 }
269
270 /* Set the default DACL to the above computed ACL. */
271 if (!SetTokenInformation (token.theHANDLE(), TokenDefaultDacl, &dacl,
272 bufferSize))
273 NoteFailedAPI ("SetTokenInformation");
274 }
275
276 void
277 NTSecurity::setBackupPrivileges ()
278 {
279 LUID backup, restore;
280 if (!LookupPrivilegeValue (NULL, SE_BACKUP_NAME, &backup))
281 NoteFailedAPI ("LookupPrivilegeValue");
282 else if (!LookupPrivilegeValue (NULL, SE_RESTORE_NAME, &restore))
283 NoteFailedAPI ("LookupPrivilegeValue");
284 else
285 {
286 PTOKEN_PRIVILEGES new_privs;
287
288 new_privs = (PTOKEN_PRIVILEGES) alloca (sizeof (TOKEN_PRIVILEGES)
289 + sizeof (LUID_AND_ATTRIBUTES));
290 new_privs->PrivilegeCount = 2;
291 new_privs->Privileges[0].Luid = backup;
292 new_privs->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
293 new_privs->Privileges[1].Luid = restore;
294 new_privs->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
295 if (!AdjustTokenPrivileges (token.theHANDLE (), FALSE, new_privs,
296 0, NULL, NULL))
297 NoteFailedAPI ("AdjustTokenPrivileges");
298 else if (GetLastError () == ERROR_NOT_ALL_ASSIGNED)
299 log (LOG_TIMESTAMP) << "User has NO backup/restore rights" << endLog;
300 else
301 log (LOG_TIMESTAMP) << "User has backup/restore rights" << endLog;
302 }
303 }
304
305 void
306 NTSecurity::resetPrimaryGroup ()
307 {
308 if (primaryGroupSID.pgrp.PrimaryGroup)
309 {
310 log (LOG_TIMESTAMP) << "Changing gid back to original" << endLog;
311 if (!SetTokenInformation (token.theHANDLE (), TokenPrimaryGroup,
312 &primaryGroupSID, sizeof primaryGroupSID))
313 NoteFailedAPI ("SetTokenInformation");
314 }
315 }
316
317 void
318 NTSecurity::setAdminGroup ()
319 {
320 TOKEN_PRIMARY_GROUP tpg;
321
322 tpg.PrimaryGroup = administratorsSID.theSID ();
323 log (LOG_TIMESTAMP) << "Changing gid to Administrators" << endLog;
324 if (!SetTokenInformation (token.theHANDLE (), TokenPrimaryGroup,
325 &tpg, sizeof tpg))
326 NoteFailedAPI ("SetTokenInformation");
327 else
328 groupSID = administratorsSID.theSID ();
329 }
330
331 void
332 NTSecurity::setDefaultSecurity ()
333 {
334 /* First initialize the well known SIDs used later on. */
335 initialiseWellKnownSIDs ();
336
337 /* Get the processes access token. */
338 if (!OpenProcessToken (GetCurrentProcess (),
339 TOKEN_READ | TOKEN_ADJUST_DEFAULT
340 | TOKEN_ADJUST_PRIVILEGES, &token.theHANDLE ()))
341 {
342 NoteFailedAPI ("OpenProcessToken");
343 return;
344 }
345
346 /* Set backup and restore privileges if available. */
347 setBackupPrivileges ();
348
349 /* If initializing the well-known SIDs didn't work, we're finished here. */
350 if (!wellKnownSIDsinitialized ())
351 return;
352
353 /* Set the default DACL to all permissions for everyone as a fallback. */
354 setDefaultDACL ();
355
356 /* Get the user */
357 if (!GetTokenInformation (token.theHANDLE (), TokenUser, &ownerSID,
358 sizeof ownerSID, &size))
359 {
360 NoteFailedAPI ("GetTokenInformation(user)");
361 return;
362 }
363 /* Make it the owner */
364 TOKEN_OWNER owner = { ownerSID.user.User.Sid };
365 if (!SetTokenInformation (token.theHANDLE (), TokenOwner, &owner,
366 sizeof owner))
367 {
368 NoteFailedAPI ("SetTokenInformation(owner)");
369 return;
370 }
371 /* Get original primary group. The token's primary group will be reset
372 to the original group right before we call the postinstall scripts.
373 This is necessary, otherwise, if the installing user is a domain user,
374 the group information created by the postinstall calls to `mkpasswd -c,
375 mkgroup -c' will be plain wrong. */
376 if (!GetTokenInformation (token.theHANDLE (), TokenPrimaryGroup,
377 &primaryGroupSID, sizeof primaryGroupSID, &size))
378 {
379 NoteFailedAPI("GetTokenInformation(pgrp)");
380 primaryGroupSID.pgrp.PrimaryGroup = (PSID) NULL;
381 }
382 groupSID = primaryGroupSID.pgrp.PrimaryGroup;
383 /* Try to set the primary group to the Administrators group, but only if
384 "Install for all users" has been chosen. If it doesn't work, we're
385 no admin and that's all there's to say about it. */
386 if (root_scope == IDC_ROOT_SYSTEM)
387 setAdminGroup ();
388 }
389
390 VersionInfo::VersionInfo ()
391 {
392 v.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
393 if (GetVersionEx (&v) == 0)
394 {
395 log (LOG_PLAIN) << "GetVersionEx () failed: " << GetLastError ()
396 << endLog;
397
398 /* If GetVersionEx fails we really should bail with an error of some kind,
399 but for now just assume we're on NT and continue. */
400 v.dwPlatformId = VER_PLATFORM_WIN32_NT;
401 }
402 }
403
404 /* This is the Construct on First Use idiom to avoid static initialization
405 order problems. */
406 VersionInfo& GetVer ()
407 {
408 static VersionInfo *vi = new VersionInfo ();
409 return *vi;
410 }
This page took 0.050302 seconds and 5 git commands to generate.