* autoload.cc (CloseDesktop): Define.

(CreateDesktopA): Define.
	(SetThreadDesktop): Define.
	* spawn.cc (spawn_guts): When starting a process under another user
	account, don't open up permissions on current window station and
	desktop.  Instead, if not in interactive session, create a new per-user
	window station plus default desktop and use that for the child process.
This commit is contained in:
Corinna Vinschen 2007-08-17 19:58:57 +00:00
parent 2ad518b5a0
commit e0bdf94f32
3 changed files with 64 additions and 17 deletions

View File

@ -1,3 +1,13 @@
2007-08-17 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (CloseDesktop): Define.
(CreateDesktopA): Define.
(SetThreadDesktop): Define.
* spawn.cc (spawn_guts): When starting a process under another user
account, don't open up permissions on current window station and
desktop. Instead, if not in interactive session, create a new per-user
window station plus default desktop and use that for the child process.
2007-08-16 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_disk_file::fchmod): Handle S_IFSOCK

View File

@ -322,7 +322,9 @@ LoadDLLfuncEx (LsaRegisterLogonProcess, 12, secur32, 1)
LoadDLLfunc (CharToOemA, 8, user32)
LoadDLLfunc (CloseClipboard, 0, user32)
LoadDLLfunc (CloseDesktop, 4, user32)
LoadDLLfunc (CloseWindowStation, 4, user32)
LoadDLLfunc (CreateDesktopA, 24, user32)
LoadDLLfunc (CreateWindowExA, 48, user32)
LoadDLLfunc (CreateWindowStationA, 16, user32)
LoadDLLfunc (DefWindowProcA, 16, user32)
@ -349,6 +351,7 @@ LoadDLLfunc (RegisterClassA, 4, user32)
LoadDLLfunc (RegisterClipboardFormatA, 4, user32)
LoadDLLfunc (SendMessageA, 16, user32)
LoadDLLfunc (SetClipboardData, 8, user32)
LoadDLLfunc (SetThreadDesktop, 4, user32)
LoadDLLfunc (SetProcessWindowStation, 4, user32)
LoadDLLfunc (accept, 12, ws2_32)

View File

@ -512,25 +512,49 @@ loop:
if (mode == _P_OVERLAY)
myself.set_acl();
/* allow the child to interact with our window station/desktop */
HANDLE hwst, hdsk;
SECURITY_INFORMATION dsi = DACL_SECURITY_INFORMATION;
NTSTATUS status;
char wstname[1024] = { '\0' };
HWINSTA hwst_orig = NULL, hwst = NULL;
HDESK hdsk_orig = NULL, hdsk = NULL;
PSECURITY_ATTRIBUTES sa;
DWORD n;
char wstname[1024];
char dskname[1024];
hwst = GetProcessWindowStation ();
if ((status = NtSetSecurityObject (hwst, dsi, get_null_sd ())))
system_printf ("NtSetSecurityObject, %lx", status);
GetUserObjectInformation (hwst, UOI_NAME, wstname, 1024, &n);
hdsk = GetThreadDesktop (GetCurrentThreadId ());
if ((status = NtSetSecurityObject (hdsk, dsi, get_null_sd ())))
system_printf ("NtSetSecurityObject, %lx", status);
GetUserObjectInformation (hdsk, UOI_NAME, dskname, 1024, &n);
strcat (wstname, "\\");
strcat (wstname, dskname);
si.lpDesktop = wstname;
hwst_orig = GetProcessWindowStation ();
hdsk_orig = GetThreadDesktop (GetCurrentThreadId ());
GetUserObjectInformation (hwst_orig, UOI_NAME, wstname, 1024, &n);
/* Prior to Vista it was possible to start a service with the
"Interact with desktop" flag. This started the service in the
interactive window station of the console. A big security
risk, but we don't want to disable this behaviour for older
OSes because it's still heavily used by some users. They have
been warned. */
if (!strcasematch (wstname, "WinSta0"))
{
char sid[128];
sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024),
cygheap->user.sid ());
/* We're create a window station per user, not per logon session.
First of all we might not have a valid logon session for
the user (logon by create_token), and second, it doesn't
make sense in terms of security to create a new window
station for every logon of the same user. It just fills up
the system with window stations for no good reason. */
hwst = CreateWindowStationA (cygheap->user.get_windows_id (sid), 0,
GENERIC_READ | GENERIC_WRITE, sa);
if (!hwst)
system_printf ("CreateWindowStation failed, %E");
else if (!SetProcessWindowStation (hwst))
system_printf ("SetProcessWindowStation failed, %E");
else if (!(hdsk = CreateDesktopA ("Default", NULL, NULL, 0,
GENERIC_ALL, sa)))
system_printf ("CreateDesktop failed, %E");
else
{
stpcpy (stpcpy (wstname, sid), "\\Default");
si.lpDesktop = wstname;
debug_printf ("Desktop: %s", si.lpDesktop);
}
}
rc = CreateProcessAsUser (cygheap->user.primary_token (),
runpath, /* image name - with full path */
@ -543,6 +567,16 @@ loop:
NULL,
&si,
&pi);
if (hwst)
{
SetProcessWindowStation (hwst_orig);
CloseWindowStation (hwst);
}
if (hdsk)
{
SetThreadDesktop (hdsk_orig);
CloseDesktop (hdsk);
}
}
/* Restore impersonation. In case of _P_OVERLAY this isn't