2 * Copyright (c) 2000, Red Hat, Inc.
3 * Copyright (c) 2003, Robert Collins <rbtcollins@hotmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * A copy of the GNU General Public License can be found at
13 * Written by DJ Delorie <dj@cygnus.com>
14 * Robert Collins <rbtcollins@hotmail.com>
19 /* OK, here's how this works. Each of the steps needed for install -
20 dialogs, downloads, installs - are in their own files and have some
21 "do_*" function (prototype in dialog.h) and a resource id (IDD_* or
22 IDD_S_* in resource.h) for that step. Each step is responsible for
23 selecting the next step! See the NEXT macro in dialog.h. Note
24 that the IDD_S_* ids are fake; those are for steps that don't
25 really have a controlling dialog (some have progress dialogs, but
26 those don't count, although they could). Replace the IDD_S_* with
27 IDD_* if you create a real dialog for those steps. */
30 static const char *cvsid
=
46 #include "setup_version.h"
49 #include "propsheet.h"
53 #include "AntiVirus.h"
64 #include "getopt++/GetOption.h"
65 #include "getopt++/BoolOption.h"
67 #include "UserSettings.h"
68 #include "Exception.h"
75 static BoolOption
UnattendedOption (false, 'q', "quiet-mode", "Unattended setup mode");
76 static BoolOption
HelpOption (false, 'h', "help", "print help");
78 /* Maximum size of a SID on NT/W2K. */
79 #define MAX_SID_LEN 40
81 /* Computes the size of an ACL in relation to the number of ACEs it
83 #define TOKEN_ACL_SIZE(cnt) (sizeof(ACL) + \
84 (cnt) * (sizeof(ACCESS_ALLOWED_ACE) + MAX_SID_LEN))
90 /* Prevent synthetics. If assignment is needed, this should be refcounting */
91 SIDWrapper(SIDWrapper
const &);
92 SIDWrapper
&operator=(SIDWrapper
const&);
94 /* We could look at doing weird typcast overloads here,
95 but manual access is easier for now
98 PSID
const &theSID() const;
103 SIDWrapper::SIDWrapper() : value(NULL
) {}
104 SIDWrapper::~SIDWrapper()
117 SIDWrapper::theSID() const
122 class HANDLEWrapper
{
125 /* Prevent synthetics. If assignment is needed, we should duphandles, or refcount */
126 HANDLEWrapper(HANDLEWrapper
const &);
127 HANDLEWrapper
&operator=(HANDLEWrapper
const &);
130 HANDLE
const &theHANDLE() const;
135 HANDLEWrapper::HANDLEWrapper() : value (NULL
) {}
136 HANDLEWrapper::~HANDLEWrapper()
143 HANDLEWrapper::theHANDLE()
149 HANDLEWrapper::theHANDLE() const
156 class TokenGroupCollection
{
158 TokenGroupCollection(DWORD
, Setup::HANDLEWrapper
&);
159 ~TokenGroupCollection();
160 /* prevent synthetics */
161 TokenGroupCollection
&operator=(TokenGroupCollection
const &);
162 TokenGroupCollection (TokenGroupCollection
const &);
163 bool find (Setup::SIDWrapper
const &) const;
164 bool populated() const { return populated_
;}
167 mutable bool populated_
;
170 Setup::HANDLEWrapper
&token
;
173 TokenGroupCollection::TokenGroupCollection(DWORD aSize
, Setup::HANDLEWrapper
&aHandle
) : populated_(false), buffer(new char[aSize
]), bufferSize(aSize
), token(aHandle
)
177 TokenGroupCollection::~TokenGroupCollection()
184 TokenGroupCollection::populate()
186 if (!GetTokenInformation (token
.theHANDLE(), TokenGroups
, buffer
, bufferSize
, &bufferSize
))
188 log (LOG_TIMESTAMP
) << "GetTokenInformation() failed: " <<
189 GetLastError () << endLog
;
196 TokenGroupCollection::find (Setup::SIDWrapper
const &aSID
) const
200 TOKEN_GROUPS
*groups
= (TOKEN_GROUPS
*) buffer
;
201 for (DWORD pg
= 0; pg
< groups
->GroupCount
; ++pg
)
202 if (EqualSid(groups
->Groups
[pg
].Sid
, aSID
.theSID()))
210 static void NoteFailedAPI(String
const &);
213 /* prevent synthetics */
214 NTSecurity
&operator=(NTSecurity
const&);
215 NTSecurity(NTSecurity
const &);
217 void setDefaultSecurity();
219 void failed(bool const &);
220 bool const &failed() const;
221 void initialiseEveryOneSID();
222 void setDefaultDACL ();
223 Setup::SIDWrapper everyOneSID
, administratorsSID
, usid
;
224 Setup::HANDLEWrapper token
;
228 char buf
[MAX_SID_LEN
];
237 worker
.setDefaultSecurity();
241 NTSecurity::NoteFailedAPI(String
const &api
)
243 log (LOG_TIMESTAMP
) << api
<< "() failed: " << GetLastError () << endLog
;
246 NTSecurity::NTSecurity() : everyOneSID (), administratorsSID(), usid(), token(), failed_(false)
249 NTSecurity::~NTSecurity()
254 NTSecurity::failed(bool const &aBool
)
260 NTSecurity::failed() const
266 NTSecurity::initialiseEveryOneSID()
268 SID_IDENTIFIER_AUTHORITY sid_auth
= { SECURITY_WORLD_SID_AUTHORITY
};
269 if (!AllocateAndInitializeSid (&sid_auth
, 1, 0, 0, 0, 0, 0, 0, 0, 0, &everyOneSID
.theSID()))
271 NoteFailedAPI ("AllocateAndInitializeSid");
277 NTSecurity::setDefaultDACL ()
279 /* To assure that the created files have a useful ACL, the
280 default DACL in the process token is set to full access to
281 everyone. This applies to files and subdirectories created
282 in directories which don't propagate permissions to child
284 To assure that the files group is meaningful, a token primary
285 group of None is changed to Users or Administrators. */
287 initialiseEveryOneSID();
291 /* Create a buffer which has enough room to contain the TOKEN_DEFAULT_DACL
292 structure plus an ACL with one ACE. */
293 size_t bufferSize
= sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
)
294 + GetLengthSid(everyOneSID
.theSID()) - sizeof(DWORD
);
296 std::auto_ptr
<char> buf (new char[bufferSize
]);
298 /* First initialize the TOKEN_DEFAULT_DACL structure. */
299 PACL dacl
= (PACL
)buf
.get();
301 /* Initialize the ACL for containing one ACE. */
302 if (!InitializeAcl (dacl
, bufferSize
, ACL_REVISION
))
304 NoteFailedAPI ("InitializeAcl");
309 /* Create the ACE which grants full access to "Everyone" and store it
311 if (!AddAccessAllowedAce
312 (dacl
, ACL_REVISION
, GENERIC_ALL
, everyOneSID
.theSID()))
314 NoteFailedAPI ("AddAccessAllowedAce");
319 /* Get the processes access token. */
320 if (!OpenProcessToken (GetCurrentProcess (),
321 TOKEN_READ
| TOKEN_ADJUST_DEFAULT
, &token
.theHANDLE()))
323 NoteFailedAPI ("OpenProcessToken");
328 /* Set the default DACL to the above computed ACL. */
329 if (!SetTokenInformation (token
.theHANDLE(), TokenDefaultDacl
, &dacl
, bufferSize
))
331 NoteFailedAPI ("SetTokenInformation");
337 NTSecurity::setDefaultSecurity ()
345 if (!GetTokenInformation (token
.theHANDLE(), TokenUser
, &osid
,
348 NoteFailedAPI("GetTokenInformation");
351 /* Make it the owner */
352 if (!SetTokenInformation (token
.theHANDLE(), TokenOwner
, &osid
,
355 NoteFailedAPI("SetTokenInformation");
359 SID_IDENTIFIER_AUTHORITY sid_auth
;
360 sid_auth
= (SID_IDENTIFIER_AUTHORITY
) { SECURITY_NT_AUTHORITY
};
361 /* Get the SID for "Administrators" S-1-5-32-544 */
362 if (!AllocateAndInitializeSid (&sid_auth
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
363 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0, &administratorsSID
.theSID()))
365 NoteFailedAPI("AllocateAndInitializeSid");
368 /* Get the SID for "Users" S-1-5-32-545 */
369 if (!AllocateAndInitializeSid (&sid_auth
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
370 DOMAIN_ALIAS_RID_USERS
, 0, 0, 0, 0, 0, 0, &usid
.theSID()))
372 NoteFailedAPI("AllocateAndInitializeSid");
375 /* Get the token groups */
376 if (!GetTokenInformation (token
.theHANDLE(), TokenGroups
, NULL
, 0, &size
)
377 && GetLastError () != ERROR_INSUFFICIENT_BUFFER
)
379 NoteFailedAPI("GetTokenInformation");
382 TokenGroupCollection
ntGroups(size
, token
);
384 if (!ntGroups
.populated())
386 /* Set the default group to one of the above computed SID. */
388 if (ntGroups
.find (usid
))
390 nsid
= usid
.theSID();
391 log(LOG_TIMESTAMP
) << "Changing gid to Users" << endLog
;
393 else if (ntGroups
.find (administratorsSID
))
395 nsid
= administratorsSID
.theSID();
396 log(LOG_TIMESTAMP
) << "Changing gid to Administrators" << endLog
;
398 if (nsid
&& !SetTokenInformation (token
.theHANDLE(), TokenPrimaryGroup
, &nsid
, sizeof nsid
))
399 NoteFailedAPI ("SetTokenInformation");
402 // Other threads talk to this page, so we need to have it externable.
403 ThreeBarProgressPage Progress
;
405 // This is a little ugly, but the decision about where to log occurs
406 // after the source is set AND the root mount obtained
407 // so we make the actual logger available to the appropriate routine(s).
412 WinMain (HINSTANCE h
,
413 HINSTANCE hPrevInstance
, LPSTR command_line
, int cmd_show
)
419 main (int argc
, char **argv
)
421 hinstance
= GetModuleHandle (NULL
);
425 char *cwd
=new char[MAX_PATH
];
426 GetCurrentDirectory (MAX_PATH
, cwd
);
427 local_dir
= String (cwd
);
430 // TODO: make an equivalent for __argv under cygwin.
434 for (argc
= 0, _argv
= __argv
; *_argv
; _argv
++)++argc
;
440 if (!GetOption::GetInstance().Process (argc
,_argv
, NULL
))
443 LogSingleton::SetInstance (*(theLog
= LogFile::createLogFile()));
444 theLog
->setFile (LOG_BABBLE
, local_dir
+ "/setup.log.full", false);
445 theLog
->setFile (0, local_dir
+ "/setup.log", true);
447 log (LOG_PLAIN
) << "Starting cygwin install, version " << setup_version
<< endLog
;
449 // Ensure files created by postinstall and preremove scripts
450 // get sane permissions.
451 if (putenv ("CYGWIN=nontsec") != 0)
452 log (LOG_PLAIN
) << "Failed to set CYGWIN=nontsec (errno " << errno
453 << ": " << strerror(errno
) << ")" << endLog
;
455 UserSettings::Instance().loadAllSettings();
458 AntiVirusPage AntiVirus
;
461 LocalDirPage LocalDir
;
466 DesktopSetupPage Desktop
;
467 PropSheet MainWindow
;
469 log (LOG_TIMESTAMP
) << "Current Directory: " << local_dir
<< endLog
;
473 GetOption::GetInstance().ParameterUsage(log(LOG_PLAIN
)<<"\nCommand Line Options:\n");
477 unattended_mode
= UnattendedOption
;
479 /* Set the default DACL and Group only on NT/W2K. 9x/ME has
480 no idea of access control lists and security at all. */
484 // Initialize common controls
485 InitCommonControls ();
487 // Init window class lib
488 Window::SetAppInstance (hinstance
);
503 // Add pages to sheet
504 MainWindow
.AddPage (&Splash
);
505 MainWindow
.AddPage (&AntiVirus
);
506 MainWindow
.AddPage (&Source
);
507 MainWindow
.AddPage (&Root
);
508 MainWindow
.AddPage (&LocalDir
);
509 MainWindow
.AddPage (&Net
);
510 MainWindow
.AddPage (&Site
);
511 MainWindow
.AddPage (&Chooser
);
512 MainWindow
.AddPage (&Prereq
);
513 MainWindow
.AddPage (&Progress
);
514 MainWindow
.AddPage (&Desktop
);
516 // Create the PropSheet main window
517 MainWindow
.Create ();
519 // Clean exit.. save user options.
520 UserSettings::Instance().saveAllSettings();
524 TOPLEVEL_CATCH("main");