I am trying to log on another interactive user (along with its
shell/desktop) and ran into some difficulties.
Basically I would assume I'd first need to create a new window station
using CreateWindowStation() along with a new desktop with
CreateDesktop(), then logon the user with LogonUser() following loading
the user's shell (which would usually be the Explorer) with
CreateProcessAsUser(). Is this outline more or less correct or did I
miss something?
Given this procedure would be right I encountered several issues I am
wondering about
1) CreateProcessAsUser() doesnt seem to be supported for normal accounts
as it always returns ERROR_PRIVILEGE_NOT_HELD (I read on some Windows
versions LogonUser() fails as well). The workaround
CreateProcessWithLogonW() mentioned by MSDN is reported not to work for
the SYSTEM account on the other hand (not that I would see why the
function needed to be introduced). More information about this issue is
mentioned at http://f6cb1.sliceurl.com. Is there any "easy" way to
create a process as another user from any account without any tricks?
2) CreateDesktop() doesnt seem to require a handle to the window station
but rather seems to work with the current one. So I would assume one
would have to synchronise/serialise the calls in order to prevent race
conditions, right?
I hope someone would have more insight in this issue and could provide
me with more information. Thank you!
> 1) CreateProcessAsUser() doesnt seem to be supported for normal accounts
> as it always returns ERROR_PRIVILEGE_NOT_HELD (I read on some Windows
> versions LogonUser() fails as well). The workaround
> CreateProcessWithLogonW() mentioned by MSDN is reported not to work for
> the SYSTEM account on the other hand (not that I would see why the
> function needed to be introduced). More information about this issue is
> mentioned at http://f6cb1.sliceurl.com. Is there any "easy" way to
> create a process as another user from any account without any tricks?
No tricks. CreateProcessAsUser() and impersonating SYSTEM is limited to
services, so you have to temporarily register as a service.
Thanks Sebastian, although I'd have to admit I dont see why such a
limitation would be introduced (and then even less why
CreateProcessWithLogonW() is provided which does exactly this but not
from a service).
However - as it is stated on the mentioned site as well - calling the
function as SYSTEM user results in ERROR_INVALID_OWNER. So I am
wondering whether there is a recommended/suggested way to create a
process for another user.
Thanks again.
Alex wrote:
>
> Hi,
>
> I am trying to log on another interactive user (along with its
> shell/desktop) and ran into some difficulties.
>
> Basically I would assume I'd first need to create a new window station
> using CreateWindowStation() along with a new desktop with
> CreateDesktop(), then logon the user with LogonUser() following loading
> the user's shell (which would usually be the Explorer) with
> CreateProcessAsUser(). Is this outline more or less correct or did I
> miss something?
IIRC it is stated somewhere in Keith Brown's security book, that you
cannot create an interactive WindowStation. An interactive WindowStation
named winsta0 is always created in each TS session by the system. The
CreateWindowStation API is meant for you to use if you want to create a
windowstation in which you can run service-like applications. For
instance I wrote and maintain a service (at work) that runs as SYSTEM
and creates a window station that gets some special name (our company
name is contained) and also gets a specific security descriptor so that
the service can create child processes that run under specific user
accounts and are sandboxed from the rest of the system via the
WindowStation created by the service. I don't think that there are many
other use cases for CreateWindowStation for developers outside Redmond
besides from that.
--
Stefan Kuhr
> Sebastian G. wrote:
>> No tricks. CreateProcessAsUser() and impersonating SYSTEM is limited to
>> services, so you have to temporarily register as a service.
>
> Thanks Sebastian, although I'd have to admit I dont see why such a
> limitation would be introduced
You're supposed to call into the Secondary Logon service to have it create
your process on our behalf. If you want impersonation, then create a special
account and assing the SeImpersonatePrivilege to it.
> However - as it is stated on the mentioned site as well - calling the
> function as SYSTEM user results in ERROR_INVALID_OWNER.
Hm... is the user a member of the INTERACTIVE group?
Hi Stefan :)
>
> IIRC it is stated somewhere in Keith Brown's security book, that you
> cannot create an interactive WindowStation.
But isnt this what you actually did with "SUperior SU"?
I guess I should get a copy of this book - even though I just want to
logon additional users, but it seems it might be more complicated than
on Unix platforms.
> An interactive WindowStation
> named winsta0 is always created in each TS session by the system. The
> CreateWindowStation API is meant for you to use if you want to create a
> windowstation in which you can run service-like applications.
What should this be for? Why should a service need a desktop?
> For
> instance I wrote and maintain a service (at work) that runs as SYSTEM
> and creates a window station that gets some special name (our company
> name is contained) and also gets a specific security descriptor so that
> the service can create child processes that run under specific user
> accounts and are sandboxed from the rest of the system via the
> WindowStation created by the service.
Sandboxed as in what? So that it cant communicate with other
applications via Windows messages?
Thanks
> Stefan Kuhr wrote:
>> Hello Alex,
>
> Hi Stefan :)
>
>> IIRC it is stated somewhere in Keith Brown's security book, that you
>> cannot create an interactive WindowStation.
>
> But isnt this what you actually did with "SUperior SU"?
Superior SU creates a new interactive desktop within the existing WindowStation.
> What should this be for? Why should a service need a desktop?
I guess what he meant are job objects.
> Sandboxed as in what? So that it cant communicate with other
> applications via Windows messages?
If they're on different desktops, they can transfer but they can't acquire
the handle in first place, so the receiver can actively deny receiving
untrusted messages. Sending messages to applications on different
WindowStation is totally prohibited.
Alex wrote:
> Stefan Kuhr wrote:
>> Hello Alex,
>
> Hi Stefan :)
>
>>
>> IIRC it is stated somewhere in Keith Brown's security book, that you
>> cannot create an interactive WindowStation.
>
> But isnt this what you actually did with "SUperior SU"?
>
Nope. It is like Sebastian wrote, it creates new desktops in addition to
the desktop named "default". But all within the winsta0 WindowStation of
the respective TS session.
> I guess I should get a copy of this book - even though I just want to
> logon additional users, but it seems it might be more complicated than
> on Unix platforms.
>
>> An interactive WindowStation named winsta0 is always created in each
>> TS session by the system. The CreateWindowStation API is meant for you
>> to use if you want to create a windowstation in which you can run
>> service-like applications.
>
> What should this be for? Why should a service need a desktop?
We have a particular need that we need to run pieces of code in
service-like behaviour (i.e. without user intervention and with a highly
privileged account, that is a distinct user account, typically an AD
user account). But the account with which it runs might change quickly
driven by configuration changes, and if we modeled this using the
traditional approach of configuring the service to run under a distinct
user account, we would have to reconfigure the service as soon as this
account changes and have it automatically restarted. It would also
require that we cannot have two or more instances of this process with
service-like behaviour, each running under different user accounts. So
what we essentially do is create a service style logon session with
LogonUser from a service in SYSTEM and spawn individual child processes
with CreateProcessAsUser. The credentials for LogonUser are obtained via
some sort of out-of-band communication. But we cannot use the
winsta\desktop combination of the service itself for the child
processes, because that would require permanent changes to their DACL,
ouch! So we first create a windowstation and set their security
descriptor so that the child processes have proper access rights (no,
not a NULL DACL!) and specify the winsta's name as the parameter to
CPAU. This way the child processes of our service run in distinct user
accounts and all share the same winsta\desktop without changing anything
on any winsta\desktop and thus depleting the precious desktop heap for
their DACLs.
>
> Sandboxed as in what? So that it cant communicate with other
> applications via Windows messages?
That is one reason. The other is so we need not change DACLs of any
winstas and desktops. It is our own and will be shared for the whole
computer session by the child processes of our service.
--
Stefan
Sebastian G. wrote:
> Alex wrote:
>
>
>> What should this be for? Why should a service need a desktop?
>
>
> I guess what he meant are job objects.
>
No, I was talking desktops. Every service is running on some desktop.
Just look a the handles of some services in process explorer and check
out the fancy names that some windowstations have. After all, every
service has been created as a child process of services.exe via one of
the CreateProcess... APIs, which allows to specify a winsta\desktop in
which the process runs. And even if you specify NULL there you start the
child process with a winsta\desktop, you only specify default
windowstation allocation policy this way, so the system might create a
new windowstation\desktop for your child process.
--
Stefan
> Hello Sebastian,
>
> Sebastian G. wrote:
>> Alex wrote:
>>
>>
>>> What should this be for? Why should a service need a desktop?
>>
>> I guess what he meant are job objects.
>>
>
> No, I was talking desktops. Every service is running on some desktop.
Job objects, as they're implemented, also get their own desktop. But they
don't need the isolation for protecting themselves from others, but
protecting others from themselves.
> Just look a the handles of some services in process explorer and check
> out the fancy names that some windowstations have. After all, every
> service has been created as a child process of services.exe via one of
> the CreateProcess... APIs, which allows to specify a winsta\desktop in
> which the process runs. And even if you specify NULL there you start the
> child process with a winsta\desktop, you only specify default
> windowstation allocation policy this way, so the system might create a
> new windowstation\desktop for your child process.
This still doesn't explain any *need* for separate WindowStation for services.
Sebastian G. wrote:
> Stefan Kuhr wrote:
>
>> Hello Sebastian,
>>
>> Sebastian G. wrote:
>>> Alex wrote:
>>>
>>>
>>>> What should this be for? Why should a service need a desktop?
>>>
>>> I guess what he meant are job objects.
>>>
>>
>> No, I was talking desktops. Every service is running on some desktop.
>
>
> Job objects, as they're implemented, also get their own desktop. But
> they don't need the isolation for protecting themselves from others, but
> protecting others from themselves.
Thanks, I didn't know that. Seems like I have to give job objects a try.
The original design of the whole shebang was made when NT4 was still a
target platform, where job objects are no option. Seems like I have to
revise the design, now that we fortunately do not support NT4 anymore.
Thanks, for the hint about job objects, although I do not yet have any
idea how to mix and match CPAU with job objects.
>
>> Just look a the handles of some services in process explorer and check
>> out the fancy names that some windowstations have. After all, every
>> service has been created as a child process of services.exe via one of
>> the CreateProcess... APIs, which allows to specify a winsta\desktop in
>> which the process runs. And even if you specify NULL there you start
>> the child process with a winsta\desktop, you only specify default
>> windowstation allocation policy this way, so the system might create a
>> new windowstation\desktop for your child process.
>
>
> This still doesn't explain any *need* for separate WindowStation for
> services.
Well, I guess that the concept of separate WindowStations for Services
running in different logon sessions as services.exe provides them act as
sort of a boundary between services, that prevent different services
from inadvertently interacting with each other in an unfortunate manner.
Think about it the other way round: Let's assume that all services,
those running as highly privileged principals like SYSTEM and those that
run on purpose with a least privilege account would share the same
windowstation. As soon as any of such a service calls into user32, it
needs proper access rights to the windowstation and desktop that it
uses. Now how should the DACL of these user objects look like if
potentially every user needs the same access rights? In addition, think
about a service that goes awry and allocates 10000 window handles, be it
on purpose because of a bad design or because of a bug. The next time
another service would spawn a thread that uses COM with the apartment
model, this service would be unable to initialize COM, resulting in a DOS.
The reasoning for having different windowstations\desktops for services
versus interactive users' windowstations\desktops should be clear, if we
consider a number of attacks that are otherwise possible.
--
Stefan
Call into as in what? How would I access it via the API?
However to be honest I still find it weird that CreateProcessAsUser()
does not work when CreateProcessWithLogonW() succeeds under the exactly
same conditions.
>
> Hm... is the user a member of the INTERACTIVE group?
Well, I was talking about the actual SYSTEM user.
So basically the application just opens new desktops where it launches
new shells under the respective user context, right?
So I assume applications using global Windows objects can run into
problem if being run simultaneously under different "sessions". This
leads me to another question related to one of your previous posting
> IIRC it is stated somewhere in Keith Brown's security book, that you
> cannot create an interactive WindowStation.
What exactly is considered an "interactive window station"? The window
station created by the system upon a user logs on or the currently used one?
> The interactive window station, Winsta0, is the only window station
> that can display a user interface or receive user input. It is
> assigned to the logon session of the interactive user, and contains
> the keyboard, mouse, and display device. All other window stations
> are noninteractive, which means they cannot display a user interface
> or receive user input.
Given this description at MSDN I would assume the former and any other
window station can only be used at best to isolate processes - as you
did it in your project - but not to actually display anything or receive
user input (neither interactively nor programmatically). Is my
understanding of this correct or did I miss anything?
Thanks again.
>> The interactive window station, Winsta0, is the only window station
>> that can display a user interface or receive user input. It is
>> assigned to the logon session of the interactive user, and contains
>> the keyboard, mouse, and display device. All other window stations
>> are noninteractive, which means they cannot display a user interface
>> or receive user input.
>
> Given this description at MSDN I would assume the former and any other
> window station can only be used at best to isolate processes - as you
> did it in your project -
He already mentioned it: He does the isolation by using different Desktops
within the very same WindowStation.
> but not to actually display anything or receive
> user input (neither interactively nor programmatically). Is my
> understanding of this correct or did I miss anything?
On Terminal Server each TS user gets his own Window Station with its own set
of devices, though it's not interactive displayed on the TS server itself.
Alex wrote:
> Stefan Kuhr wrote:
>>
>> Nope. It is like Sebastian wrote, it creates new desktops in addition
>> to the desktop named "default". But all within the winsta0
>> WindowStation of the respective TS session.
>
> So basically the application just opens new desktops where it launches
> new shells under the respective user context, right?
Exactly.
>
> So I assume applications using global Windows objects can run into
> problem if being run simultaneously under different "sessions". This
> leads me to another question related to one of your previous posting
>
>> IIRC it is stated somewhere in Keith Brown's security book, that you
>> cannot create an interactive WindowStation.
>
> What exactly is considered an "interactive window station"? The window
> station created by the system upon a user logs on or the currently used
> one?
It is a WindowStation that is associated with a process that is ...
well.... ummhh, interactive. It can be operated by a human being using
keyboard and mouse and has a display surface attached. If someone else
has a better definition I'd be glad to hear it, so far this is probably
a trivial one and the only one I can come up with.
Technically speaking, you can differentiate interactive versus
non-interactiv ewindowstations by calling GetUserObjectInformation with
the UOI_FLAGS parameter. This will return a USEROBJECTFLAGS struct and
you can examine the dwFlags struct member. If it has the WSF_VISIBLE
flag set, it is interactive.
>
> Given this description at MSDN I would assume the former and any other
> window station can only be used at best to isolate processes - as you
> did it in your project - but not to actually display anything or receive
> user input (neither interactively nor programmatically). Is my
> understanding of this correct or did I miss anything?
>
It is AFAIK correct. But be aware that even for processes running in the
same noninteractive WindowStation it is possible to Send and Post
Windows Messages. So even between processes running in the same
noninteractive WindowStation it is possible that they simulate Key
presses and mouse clicks against each other.
--
Stefan
> It is a WindowStation that is associated with a process that is ...
> well.... ummhh, interactive. It can be operated by a human being using
> keyboard and mouse and has a display surface attached. If someone else
> has a better definition I'd be glad to hear it, so far this is probably
> a trivial one and the only one I can come up with.
Actually it's just a type of object, which acts as a container for desktops
and can be associated with devices. In Windows' limited architecture, only
one WindowStation can map to the physical graphic card, mouse and keyboard.
You can still map WindowStation to interactive users through Terminal Services.
> Technically speaking, you can differentiate interactive versus
> non-interactiv ewindowstations by calling GetUserObjectInformation with
> the UOI_FLAGS parameter. This will return a USEROBJECTFLAGS struct and
> you can examine the dwFlags struct member. If it has the WSF_VISIBLE
> flag set, it is interactive.
Which raises the question: Wouldn't this also be the case for WindowStation
associated to TS users on TS?
> But be aware that even for processes running in the
> same noninteractive WindowStation it is possible to Send and Post
> Windows Messages. So even between processes running in the same
> noninteractive WindowStation it is possible that they simulate Key
> presses and mouse clicks against each other.
But as long as they don't run on the same desktop as well, there's no way to
get a handle to the application window or its desktop for sending a message.
That is, to do communication, you need consent from potential receiver, and
the handle has to be acquired through some other IPC mechanism. Isolation
based upon WindowStation is just stronger in that sense that even
accidential consent (confused debuty problem) won't lead to any undesired
IPC through Window messages.
Thanks
>
> It is a WindowStation that is associated with a process that is ...
> well.... ummhh, interactive. It can be operated by a human being using
> keyboard and mouse and has a display surface attached. If someone else
> has a better definition I'd be glad to hear it, so far this is probably
> a trivial one and the only one I can come up with.
>
> Technically speaking, you can differentiate interactive versus
> non-interactiv ewindowstations by calling GetUserObjectInformation with
> the UOI_FLAGS parameter. This will return a USEROBJECTFLAGS struct and
> you can examine the dwFlags struct member. If it has the WSF_VISIBLE
> flag set, it is interactive.
Thanks for the explanation, so one of the major differences (the only?)
seems to be that an application cannot switch to desktops of window
stations other than Winsta0, correct?
>
> It is AFAIK correct. But be aware that even for processes running in the
> same noninteractive WindowStation it is possible to Send and Post
> Windows Messages. So even between processes running in the same
> noninteractive WindowStation it is possible that they simulate Key
> presses and mouse clicks against each other.
Okay, so while desktops of non-interactive window stations cant actually
access the system's input/output devices it technically still can
process input and provide also "virtual" output (virtual as in not
displayed but still internally rendered) - or will the creation of
windows fail as well?
Related to this I am having a similar question, what happens if an
application creates more than one window station? So far I have the
impression it can always be only associated with one window station at a
time, right? So this would mean it would always have to switch to the
desired window station prior of accessing its desktops, wouldnt it?
I guess the same would apply to individual desktops.
> Stefan Kuhr wrote:
>> Exactly.
>
> Thanks
>
>> It is a WindowStation that is associated with a process that is ...
>> well.... ummhh, interactive. It can be operated by a human being using
>> keyboard and mouse and has a display surface attached. If someone else
>> has a better definition I'd be glad to hear it, so far this is probably
>> a trivial one and the only one I can come up with.
>>
>> Technically speaking, you can differentiate interactive versus
>> non-interactiv ewindowstations by calling GetUserObjectInformation with
>> the UOI_FLAGS parameter. This will return a USEROBJECTFLAGS struct and
>> you can examine the dwFlags struct member. If it has the WSF_VISIBLE
>> flag set, it is interactive.
>
> Thanks for the explanation, so one of the major differences (the only?)
> seems to be that an application cannot switch to desktops of window
> stations other than Winsta0, correct?
A privileged application can. An unprivileged application can't even switch
to other desktops.
I already explained the difference: Application can send Window messages to
all applications on the same desktop, and to consenting application on
different desktops in the same WindowStation, but not to different
WindowStation. This and that non-virtual devices can only be assigned to one
WindowStation.
> Okay, so while desktops of non-interactive window stations cant actually
> access the system's input/output devices it technically still can
> process input and provide also "virtual" output (virtual as in not
> displayed but still internally rendered) - or will the creation of
> windows fail as well?
Seems to work quite well, since this is how Terminal Server is implemented.
> Related to this I am having a similar question, what happens if an
> application creates more than one window station?
unprivileged application: access denied
privileged application: you get a new non-interactive window station, and
you have to switch between those for pulling off various actions
privileged application on Terminal server: access denied, or system crash
> So far I have the
> impression it can always be only associated with one window station at a
> time, right?
You can still access other WindowStations via a handle.
> So this would mean it would always have to switch to the
> desired window station prior of accessing its desktops, wouldnt it?
Depends on what you want to do.
> I guess the same would apply to individual desktops.
Depends on what you want to do, though sending messages to different
desktops doesn't require switching.
Alex wrote:
> Stefan Kuhr wrote:
>>
> <snip>
> Thanks for the explanation, so one of the major differences (the only?)
> seems to be that an application cannot switch to desktops of window
> stations other than Winsta0, correct?
>
In addition to what Sebastian wrote, which is all corect AFAI can see,
as a response to this posting of yours, I even did that in a commercial
product, which switched a service's windowstation from a noninteractive
one running under a distinct user account to the one of the
interactively logged in user (simply ignoring the fact that there can be
many of them) temporarily and then back to the original one, while doing
there temporarily administrative stuff that required interactivity.
While I do not recommend this to anyone I had to do this under the
constraints that I wasn't allowed to change anything with the setup of
services in the product, let alone introduce a new dedicated service in
the product, that would have allowed to do things much easier and much
more elegant. At least, the mechanism still works for pre-Vista OS
versions today and I never received any complaint or customer issue :-)
and we are talking about a product that has millions of client licenses
in numerous enterprise environments. So in general, switching
windowstations actually works, if your process is privileged enough to
do that.
>
> Okay, so while desktops of non-interactive window stations cant actually
> access the system's input/output devices it technically still can
> process input and provide also "virtual" output (virtual as in not
> displayed but still internally rendered) - or will the creation of
> windows fail as well?
How should COM in the apartment model work for services if they couldn't
even create windows in noninteractive winstas?
Cheers,
--
S
Sebastian G. wrote:
> Stefan Kuhr wrote:
>
>
>> It is a WindowStation that is associated with a process that is ...
>> well.... ummhh, interactive. It can be operated by a human being using
>> keyboard and mouse and has a display surface attached. If someone else
>> has a better definition I'd be glad to hear it, so far this is
>> probably a trivial one and the only one I can come up with.
>
>
> Actually it's just a type of object, which acts as a container for
> desktops and can be associated with devices. In Windows' limited
> architecture, only one WindowStation can map to the physical graphic
> card, mouse and keyboard. You can still map WindowStation to interactive
> users through Terminal Services.
This for sure is a much better definition than the prosaic version of
mine. Maybe we could refine it like so: "only one WindowStation can map
to the physical graphic card, mouse and keyboard at the same time".
What do you think would make "Windows' limited architecture" look less
limited?
>
>> Technically speaking, you can differentiate interactive versus
>> non-interactiv ewindowstations by calling GetUserObjectInformation
>> with the UOI_FLAGS parameter. This will return a USEROBJECTFLAGS
>> struct and you can examine the dwFlags struct member. If it has the
>> WSF_VISIBLE flag set, it is interactive.
>
>
> Which raises the question: Wouldn't this also be the case for
> WindowStation associated to TS users on TS?
>
Try it :-)
>
>
> But as long as they don't run on the same desktop as well, there's no
> way to get a handle to the application window or its desktop for sending
> a message. That is, to do communication, you need consent from potential
> receiver, and the handle has to be acquired through some other IPC
> mechanism. Isolation based upon WindowStation is just stronger in that
> sense that even accidential consent (confused debuty problem) won't lead
> to any undesired IPC through Window messages.
Yep. This more or less explains what you wrote before: "This still
doesn't explain any *need* for separate WindowStation for services."
--
Stefan
> What do you think would make "Windows' limited architecture" look less
> limited?
Allowing multiple devices to be divided among multiple interactive
workstations, especially for displays.
>>> Technically speaking, you can differentiate interactive versus
>>> non-interactiv ewindowstations by calling GetUserObjectInformation
>>> with the UOI_FLAGS parameter. This will return a USEROBJECTFLAGS
>>> struct and you can examine the dwFlags struct member. If it has the
>>> WSF_VISIBLE flag set, it is interactive.
>>
>> Which raises the question: Wouldn't this also be the case for
>> WindowStation associated to TS users on TS?
>>
>
> Try it :-)
I got Windows 2003 R2 Enterprise Edition through MSDNAA, but this doesn't
give me any TS license.
So it isn't possible to use 2 monitors in a TS session?
--PA
Sebastian G. wrote:
> Stefan Kuhr wrote:
>
>
>> What do you think would make "Windows' limited architecture" look less
>> limited?
>
>
> Allowing multiple devices to be divided among multiple interactive
> workstations, especially for displays.
>
Ah I see. Maybe the fact that Vista allows sort of a multimonitor
support for TS is a step into that direction.
>>>> Technically speaking, you can differentiate interactive versus
>>>> non-interactiv ewindowstations by calling GetUserObjectInformation
>>>> with the UOI_FLAGS parameter. This will return a USEROBJECTFLAGS
>>>> struct and you can examine the dwFlags struct member. If it has the
>>>> WSF_VISIBLE flag set, it is interactive.
>>>
>>> Which raises the question: Wouldn't this also be the case for
>>> WindowStation associated to TS users on TS?
>>>
>>
>> Try it :-)
>
>
> I got Windows 2003 R2 Enterprise Edition through MSDNAA, but this
> doesn't give me any TS license.
You can do that with W2K3 Server if you enable remote Administration.
And you also can do that with XP if you enable FUS. The WSF_VISIBLE will
be set in TS, because they are interactive.
--
Stefan
Alex wrote:
> Sebastian G. wrote:
>>
>> You're supposed to call into the Secondary Logon service to have it
>> create your process on our behalf. If you want impersonation, then
>> create a special account and assing the SeImpersonatePrivilege to it.
>
> Call into as in what? How would I access it via the API?
>
> However to be honest I still find it weird that CreateProcessAsUser()
> does not work when CreateProcessWithLogonW() succeeds under the exactly
> same conditions.
>
This is because CPAU is a privileged API and CPWL is an API that is
internally implemented in a service (the secondary logon service) which
is privileged enough to call CPAU. If your app is calling CPWL, then an
RPC is made into the secondary logon service, which in turn calls CPAU
on your app's behalf. so CPWL is a wrapper that calls CPAU in another
process.
The reasoning, however, why CPWL doesn't work anymore when called from
SYSTEM is yet another sad story...
--
Stefan
Not for separate users.
Thanks for the explanation of the technical reason Stefan, even though I
still dont understand why the limitation of CreateProcessAsUser() wasnt
simply lifted instead of introducing a new wrapper function (it should
neither have created any compatibility issues - unlike as if security
were tightened - nor any security issues - which
CreateProcessWithLogonW() could do as well), but anyway :)
>
> The reasoning, however, why CPWL doesn't work anymore when called from
> SYSTEM is yet another sad story...
Well, if at least CreateProcessAsUser() would work under SYSTEM ....
Alex wrote:
>
> Well, if at least CreateProcessAsUser() would work under SYSTEM ....
CPAU actually works under SYSTEM, it is CPWL that doesn't work anymore
under SYSTEM, at least not without changing the DACL of the
winsta\desktop of the process that runs as SYSTEM, which is umhh, ...
not really nice.
--
S
Sorry Stefan, but as I previously mentioned CreateProcessAsUser() does
not even work under SYSTEM. I am getting ERROR_INVALID_OWNER - please
see the site I named in my first posting for more details.
Does nobody have an explanation for this?
My posting spawned several interesting replies, however none with an
actual answer unfortunately. I'd be really grateful for some .... thanks
> My posting spawned several interesting replies, however none with an
> actual answer unfortunately. I'd be really grateful for some .... thanks
Well, maybe because you didn't ever tell what you actually want to do. Maybe
your entire idea is just flawed/stupid. Most likely you should use
impersonation, communication through Named Pipes, and using an unprivileged
backend for notifications and control.
What's the problem with using CreateProcessWithLogonW, unless your
running in the SYSTEM user context, in which case you use LogonUser and
CreateProcessAsUser? This might look clumsy, but encapsulating this
neatly in another function yet-to-be-written isn't actually a big deal.
Corinna
--
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat
> My posting spawned several interesting replies, however none with an
> actual answer unfortunately. I'd be really grateful for some .... thanks
So you see now that developing a "multiuser XP" or TS from zero is not
trivial.
Regards,
--PA
Thank you Corinna, but thats actually one of the problems - I cant get
LogonUser() and CreateProcessAsUser() to work under SYSTEM.
.... apart from that I really dont understand why instead of "fixing"
this issue Microsoft decided to implement another function which does
the same but calls into a separate service and then however does not
work under other circumstances, but I suppose this is another story :).
I never assumed it would be ;) (then, what exactly is trivial), but if
problems already arise at such trivial tasks like logging on another
user I'd worry about the entire design of the system - slowly I begin to
understand the criticisms about Windows.
Hmm, whats so difficult to understand about
> I am trying to log on another interactive user (along with its shell/desktop) and ran into some difficulties.
I simply want to logon a user, create another desktop (for better
separation possibly with its own window station) for him and start his
shell ..... no control messages, no named pipes
No separate display device, keyboard and mouse to each desktop ?
--PA
No.
Multiuser applications in XP are trivial. You can use a privileged backend
and unprivileged frontends. You can create Message Boxes on the current
user's desktop, and you can can also identify the current desktop.
> I simply want to logon a user, create another desktop (for better
> separation possibly with its own window station) for him and start his
> shell ..... no control messages, no named pipes
OK, and what do you intend to achieve with that? Doesn't sound a normal
usage scenario to me.
This is running apps under several accounts, or injection of apps into
interactive desktop.
By "multiuser" I meant creation of several interactive desktops without the
TS.
Regards,
--PA
In your OP you wrote that you're bemoaning that CreateProcessAsUser
doesn't work for normal accounts. You didn't say that you don't
get CreateProcessAsUser working for SYSTEM.
LogonUser and CreateProcessAsUser work fine under the SYSTEM account
from my experience. Cygwin is using these functions for years without
problems, see
http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/?cvsroot=src
function spawn_guts in spawn.cc and function cygwin_logon_user in
sec_auth.cc.
Maybe it would make sense to reduce your code using LogonUser and
CreateProcessAsUser to the bare minimum and see if you can figure
out to get it working without any ballast from the rest of your
application. Sending a self-contained example code to this list
wouldn't hurt either. Somebody might find the flaw in your code.
> .... apart from that I really dont understand why instead of "fixing"
> this issue Microsoft decided to implement another function which does
> the same but calls into a separate service and then however does not
> work under other circumstances, but I suppose this is another story :).
You already got the explanation in this thread. CreateProcessAsUser is
the underlying function which has restrictions based on the privileges
of the account calling the function. CreateProcessWithLogonW on the
other hand is basically just a convenience wrapper which allows to use
CreateProcessAsUser without forcing you to write your own service. The
security considerations of the original CreateProcessAsUser
implementation haven't changed. You might not like it, and FWIW I don't
like it, too, but that doesn't make it less valid.
No, I didnt mention it in my original posting but in the immediate
follow up as well as on the website I referred to.
>
> LogonUser and CreateProcessAsUser work fine under the SYSTEM account
> from my experience. Cygwin is using these functions for years without
> problems, see
> http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/?cvsroot=src
> function spawn_guts in spawn.cc and function cygwin_logon_user in
> sec_auth.cc.
Sorry, my fault, obviously CreateProcessAsUser() actually does work
under SYSTEM. I checked its return code which is 1, my previous wrong
assumption came from the fact that GetLastError() returns
ERROR_INVALID_OWNER after the CreateProcessAsUser() call.
One weird issue I am encountering now however is that GUI applications
seem to be unusable.
For example, starting Notepad directly from a SYSTEM console works as
excepted. Starting Notepad however from a CreateProcessAsUser()
application (which itself was started from a SYSTEM console) shows a
basic window frame, but the application itself does not react. Might
this be due to a STARTUPINFO setting (everything zeroed in the example
however)?
>
> Maybe it would make sense to reduce your code using LogonUser and
> CreateProcessAsUser to the bare minimum and see if you can figure
> out to get it working without any ballast from the rest of your
> application. Sending a self-contained example code to this list
> wouldn't hurt either. Somebody might find the flaw in your code.
Here we go :)
void main()
{
HANDLE token;
BOOL b=LogonUser("administrator", ".", "PASSWORDOFADMIN",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &token);
printf("Result of LogonUser: %d\n", b);
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb=sizeof(si);
b=CreateProcessAsUser(token, "c:\\windows\\notepad.exe", NULL,
NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
printf("%d\n", GetLastError());
printf("Result of CreateProcessAsUser: %d\n", b);
}
>
> You already got the explanation in this thread. CreateProcessAsUser is
> the underlying function which has restrictions based on the privileges
> of the account calling the function. CreateProcessWithLogonW on the
> other hand is basically just a convenience wrapper which allows to use
> CreateProcessAsUser without forcing you to write your own service. The
> security considerations of the original CreateProcessAsUser
> implementation haven't changed. You might not like it, and FWIW I don't
> like it, too, but that doesn't make it less valid.
As I stated, I am aware of the historical reasons for this
implementation, nonetheless I dont see why it was implemented this way.
Microsoft has obviously decided to offer a generally available
CreateProcessAsUser() function, so why not actually loosening the
security limitations of CreateProcessAsUser() instead of introducing an
extra function which only adds additional overhead and doesnt even
always work .... but again, this is probably another story.
Did you adjust the DACLs of the winsta and the desktop so it now
contains the new prinicipal or the logon SID in a new ACE with
appropriate access rights? That's what you have to do unless you find a
way to inject the logon SID into the token, as CPWL does.
--
Stefan
No, I didnt set any additional descriptors, the code is just as shown in
the example.
From your statement I'd assume applications under different user
contexts cant simply use the interactive desktop but first have to
establish a security relationship to the window station respectively
desktop even if it was started from this window station/desktop, right?
I suppose this is what CreateProcessWithLogonW() indirectly does by
calling into the Secondary Logon service (just as Windows' Run as option
as well) ....
Alex wrote:
> Stefan Kuhr wrote:
>>
>> Did you adjust the DACLs of the winsta and the desktop so it now
>> contains the new prinicipal or the logon SID in a new ACE with
>> appropriate access rights? That's what you have to do unless you find
>> a way to inject the logon SID into the token, as CPWL does.
>>
>
> No, I didnt set any additional descriptors, the code is just as shown in
> the example.
>
> From your statement I'd assume applications under different user
> contexts cant simply use the interactive desktop but first have to
> establish a security relationship to the window station respectively
> desktop even if it was started from this window station/desktop, right?
Yes. The traditional way of doing this is adding either an ACE with the
new user's SID or her logon SID to the two securable objects. I
recommend you to write a utility that dumps the DACLs of winstas and
desktops and see the effect if you start something via runas on a
pre-SP2 XP box. This way you can also monitor changes that the various
SU implementations do to these securable objects.
Oh, by the way, check out the Keith Brown logon session broker article
in MSJ, IIRC March 2000.
> I suppose this is what CreateProcessWithLogonW() indirectly does by
> calling into the Secondary Logon service (just as Windows' Run as option
> as well) ....
Exactly. However, since the major change, that broke the usage of CPWL
from the SYSTEM account, it doesn't change anymore the DACLs of the
winsta and desktop but instead places the caller's logon SID in the new
token. I think for the latter technique, there are no public APIs available.
--
Stefan
No, I didnt set any additional descriptors, the code is just as shown in
the example.
From your statement I'd assume applications under different user
contexts cant simply use the interactive desktop but first have to
establish a security relationship to the window station respectively
desktop even if it was started from this window station/desktop, right?
No, I didnt set any additional descriptors, the code is just as shown in
Thanks very much Stefan, this answer cleared up quite a few things ....
Alexander
Thanks to Stefan the first question (CreateProcessAsUser) is now
answered, but I'd be really glad if someone had an answer also to the
second.
I might not have stated it well enough, so here more in detail. In order
to obtain the DC of a particular desktop I suppose I have to set it as
the current thread's desktop (maybe along with switching the window
station), then use GetDC(NULL) to retrieve its DC.
Would this be correct? If so, would the DC be still valid (respectively
accessible) if I change the thread's desktop or switch to another window
station?
One of the reason why I am worrying is because I read the reply of Sten
Westerback to news:3edc2982$1...@news.012.net.il
(http://16d0c.sliceurl.com). Shall this mean an application can open a
renderable object only on the interactive desktop?
Thanks again
Alex wrote:
> Alex wrote:
>>>
> <snip>
> I might not have stated it well enough, so here more in detail. In order
> to obtain the DC of a particular desktop I suppose I have to set it as
> the current thread's desktop (maybe along with switching the window
> station), then use GetDC(NULL) to retrieve its DC.
>
> Would this be correct? If so, would the DC be still valid (respectively
> accessible) if I change the thread's desktop or switch to another window
> station?
>
> One of the reason why I am worrying is because I read the reply of Sten
> Westerback to news:3edc2982$1...@news.012.net.il
> (http://16d0c.sliceurl.com). Shall this mean an application can open a
> renderable object only on the interactive desktop?
>
I seem to recall that whenever I wanted to create a bitmap of a winsta0
desktop's content, that it always was black, unless the desktop was the
same as the one you get via OpenInputDesktop, so this more or less
aligns with the observation made by the poster of the link you
mentioned. Does that help answer your question?
--
Stefan
Even though it is not exactly the answer I was hoping for ;), yes, your
answer was helpful - just as all your others here by the way, thanks :)
Hmm, so this would mean in order to take a screen capture of from a
desktop, one would always have to call SwitchDesktop() beforehand. Not
only would this open up a synchronisation hell but it would also
basically render the machine useless for actual local usage.
Thanks again.
> Hmm, so this would mean in order to take a screen capture of from a
> desktop, one would always have to call SwitchDesktop() beforehand.
Which is a wonderful way to fuck up Fast User Switching or programs like
Superior SU and SuRun.
Why? Apart from the mentioned backdraws in this particular configuration
(synchronisation, local usage) it would be the same multi-desktop
utilities are doing.
No, they're not. The use SwitchDesktop() for its exact purpose: Switching
the desktop. But you're suggesting to abuse it for testing if you're on the
active desktop and/or getting your current desktop.
I am not suggesting anything. Please read the whole thread before
jumping to any wild conclusions.
This actually seems to be the case unfortunately. If I create a new
desktop (at the moment even still in the current window station) and
launch an application there, I can only successfully get a screen
capture if I set the desktop as the thread's desktop and also actually
switch to it.
Does anybody know another solution or workaround? Thank you.
Really nobody?
Most window classes will paint into a DC of your choice if you supply the
right arguments to WM_PAINT or WM_PRINT. Windows simply isn't sending them
any WM_PAINT messages when the desktop is not active, it's a particular case
of the "window is obscured" reason that windows don't get paint requests.
Thanks Ben, so basically any desktop not being the interactive one is
not rendered by Windows and an application wanting to grab its output
would have to make it rendered manually?! I guess this is what Terminal
Services is doing as well.
Thanks!
Any window that isn't visible isn't sent repaint requests. This could be
because it's minimized, there's another window on top of it, it's outside
the bounds of any monitor, or it's not on the (or "any", if TS is running)
active desktop.
>
> Thanks!
- Sten
Sten Westerback (MVP SDK 2005-6 :) wrote:
> <snip>
> I believe your design is somehow flawed as i can't think of any reason why
> you would take snapshot of another desktop. Snapshotting, when actually
> needed, is something an interactive user should initiate and is handled well
> by the normal Alt-PrtSc and PrtSc (or it's equivalent in Remote Desttop).
> Maybe you could concentrate on spying on the clipboard instead. :)
>
No, it is not flawed just because you can't think of any reason for it ;-)
Think about multiple desktops in a WindowStation and you want to provide
sort of a thumbnail view to every desktop so the user can see what's
going on on every desktop. Maybe the user has initiated a lengthy
operation on one desktop a few minutes ago, has switched to another
desktop and now wants to see if the associated progress bar is
approaching 100% and it is worthwhile to switch back to the desktop now?
Something like that would be a practical use case of what Alex wants to
implement.
--
Stefan