views:

74

answers:

3

I'm trying to figure out how to solve the privilege acquisition.

The application requires a desktop access, so it cannot be executed as a Windows service: it have to create a window for receiving message sent by other processes using SendMessage (it must be used for waiting message acknowledge).

The application shall be started when an user login, and it will manage the user session (manage applications, windows...). Only one user can be managed at time.

What I'm asking is which is the best solution for requesting privilege acquisition, since the application requires it (execute a process which calls SetWindowsHook).

  • How it possible to run any process at user login with (higher) privileges, possibly without prompting UAC messages? The setup operations could be peformed during the installation phase...
  • How could be possible to run an utility service starting a process when user logon? In this way the (installed) service could run the effective process with any priviledges...
  • Any other solution? *

What are the definive action to be taken for having a full compatible UAC application? (I mean in the build and deploy phases?

For example, I am including the following manifest file using mt.exe (using VS2005):

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"     xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-    com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    security>
      <applicationRequestMinimum>
        <defaultAssemblyRequest permissionSetReference="Custom" />
        <PermissionSet class="System.Security.PermissionSet" version="1"     Unrestricted="true" ID="Custom" SameSite="site" />
      </applicationRequestMinimum>
        <requestedPrivileges>
                <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
        </requestedPrivileges>
    </security>
  </trustInfo>
</asmv1:assembly>

It seems correct to you? No, because it doesn't work to me...

*

It actually make sense to create an additional user account (but this shall work also on windows domains) with administrator privileges to execute a controlled environment. It could be also acceptable to create a working session (a new desktop station) without logging any user, but actually I don't know if it is possible.

A: 

Services are exempt from UAC. Scheduled tasks (that run at user logon) are not. If you don't want the UAC prompt, and yet you want to run at logon, your best bet is to write both and have them communicate. Set up a service to do the privileged thing - write to Program Files or HKLM or whatever. Have it autostart. Now set up a scheduled task that runs at user logon. When it wants the privileged thing done, it asks the service to do it. How they communicate is up to you and depends on what your app does. If you have a database involved you could have a table where the task wrote requests. Or you could use the file system. Or you could use more direct integration.

The manifest file you've included in your question will make your exe elevate. This will cause a UAC prompt which you say you don't want.

Finally, can you revisit why you need to be elevated? Is there no way you could rewrite this task so it writes to AppData or HKCU or some other less protected area? Then you can just write the task and be done with it and not have to deal with interacting with a service.

Kate Gregory
Agreed. My UAC issues (see my comment above) were resolved by writing to isolated storage instead of HKLM.
Zippit
At the moment there is only SetWindowsHook which requires higher priviledges, but I fear that configuration (which is system wide), it cannot be stored on user hive/app data. My idea was to start (using a SYSTEM service) the application, which derives priviledges from service. Isn't the right approach?
Luca
A: 

Why not have a windows service running as a high privilege account that carries out the required high privilege actions and also have a user level app that does any UI/interactive actions and comunicates with the windows serives using WCF?

Ben Robinson
I'm not familiar with WCF, and manage every possible UI/Service interaction could be cumbersome. It would be nice to have only the service (since application is already a distributed one), but this is not possible.
Luca
If you are calling methods in a class to carry out actions from the UI, wrapping these classes in a WCF service and then creating proxy classes to call from your UI code should be a relatively simple bit of refactoring.
Ben Robinson
+3  A: 

You are asking a lot of questions inside of one question. There are many unclear subjects (unclear for me) about architecture of your solutions. It is also absolutely unclear for me why you need SetWindowsHook. So I try to answer only on the technical parts of your questions.

Starting of a program without prompting UAC is not a large problem and can be soleved with respect of manifestes.

Starting of a process on users's desktop from a service, so that the process runs not under users credentials, is tricky but possible. How I understand your service run under SYSTEM account. Then it has SE_TCB_NAME privilage. The service run in the session 0 (see http://www.microsoft.com/whdc/system/sysinternals/session0changes.mspx). If a user login, the processes which he see run on in the session 1 or higher. Under Windows XP the first logged user run use session 0 and only the next login (if fast switching is on) use session 1 etc. So on any operation system acn be required to start a process on other session. To do this you should use SetTokenInformation function with TokenSessionId parameter. I described details in http://stackoverflow.com/questions/3128017/possible-to-launch-a-process-in-a-users-session-from-a-service/3128679#3128679.

In all cases you should monitor users logins and logoffs and should get users session id to be able to start a process on the session. You can do this in different ways. One of the most simple way is to have a application which runs in autostart (registerd unter HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run for example). This application communicate with your service and you get through impersonation the users token and the session id. Another way is usage of ISensLogon2 notifications (see http://msdn.microsoft.com/en-us/library/aa376863.aspx) of the System Event Notification Service (SENS).

One more small problem. Depend on account used for the process which you start on users desktop in can requires to change Security Descriptor of the Desktop and Windows Station objects with respect of OpenWindowStation, OpenDesktop and SetUserObjectSecurity (see http://msdn.microsoft.com/en-us/library/ms681928.aspx, http://msdn.microsoft.com/en-us/library/ms687107.aspx and http://support.microsoft.com/kb/165194)

Oleg