UAC is for Developers

I recently wrote this short article for the latest DevelopMentor newsletter. It is not as detailed as it could be – but I only had 1000 words. Maybe it is still interesting for you.

 

Windows Vista finally starts to address one of the biggest security problems we have in software development today – the administrator problem. Most applications don’t need administrative rights, most services don’t need them either – but strangely a lot of applications simply don’t work when run as a normal user thus forcing your clients (e.g. in corporate environments) to run as administrators. Why is that?

This is kind of a chicken and egg problem. The developers writing these applications also mostly run as administrators and often just don’t properly debug and test their code under non-administrative conditions. The changes in Vista security try to break this vicious circle.

The UAC (User Account Control) feature in Vista makes administrators have kind of a split personality. Even if a user is in the administrators group, all administrative privileges are stripped out of their default security token. So whenever an application requests these powerful privileges, Vista puts up a consent dialog to inform the user about this fact. After the user confirms, Vista will put the full token containing all groups and privileges on the newly created process and thus giving it all rights a “normal” administrator would have. This only applies to administrators – not standard users.

This serves two purposes. First of all, people that insist on being administrators on their machines run with reduced privileges by default which makes it much harder for malware to cause harm to your system (but not your user data of course). For developers this makes it much easier to find out if their applications work with a normal privileged user account. If your apps work elevated but not with the default security context – you most probably do something that requires elevated privileges and you should think about if this is really needed.

The most common problems why applications break when run as normal users are very easy to fix. Check e.g. if you are trying to write to a location where you don’t have write access to. Popular locations are e.g. “Program Files”, the Windows directory or HKLM in the registry – which is just forbidden. You should always put user data into the profile – and it is incredibly easy to do that. The following line of code returns the per-application directory in the profile – similar enum values exist for “My Documents”, the desktop and so on:

string path = Environment.GetFolderPath(
  Environment.SpecialFolder.ApplicationData);

Now – another new feature of Vista makes this a little bit harder to test – it is called Virtualization. By default Vista redirects write attempts to some forbidden locations to a per user store. This includes parts of “Program Files” and parts of the registry. This feature is enabled by default to not break legacy applications running in this new and tighter security context on Vista. But what makes an application “legacy”?

Applications express their “Vista readiness” by embedding a so called manifest into the binary. The existence of this manifest makes Vista turn off the compatibility features like Virtualization and an attempt to write to the above mentioned locations will result in an access denied error. Manifests further express the security needs of an application, e.g. if they are designed to work with normal privileges as opposed to administrative applications. Embedding a manifest into applications is by the way a Vista logo requirement.

A manifest is a resource file that looks like this:

#include <winuser.h>
#define IDR_MANIFEST 1 // 2 for a DLL

IDR_MANIFEST RT_MANIFEST MOVEABLE PURE
{
  “<assembly xmlns=””urn:schemas-microsoft-com:asm.v1″” manifestVersion=””1.0″”>
    <asmv3:trustInfo xmlns:asmv3=””urn:schemas-microsoft-com:asm.v3″”>
      <asmv3:security>
        <asmv3:requestedPrivileges>
          <asmv3:requestedExecutionLevel
            level=””asInvoker””
            uiAccess=””false”” />
        </asmv3:requestedPrivileges>
      </asmv3:security>
    </asmv3:trustInfo>
  </assembly>”
}

The level attribute tells Vista about the security needs of the application. “asInvoker” starts the application with the current security token of the user – which is by default non-administrative. There is another value called “requireAdministrator” which tells Vista that this application is designed to be used by administrators only and the user will see the elevation prompt at application startup.

Before Visual Studio “Orcas” there is no automated way of embedding this resource files into your assemblies – you have to do the following steps:

Compile this file (which should have an extension of “.rc”) to a binary resource file using the resource compiler:

rc.exe manifest.rc

This will result in a “.res” file that you can embed using the project properties dialog in Visual Studio. Use the “Resource File” option in the “Application” tab for that. That’s it – you are done.

Now the application will behave “Vista compatible” – which is exactly the same behavior as running it on pre-Vista operating systems under a non-administrative account. You are now at a point where you can easily test the application under normal user conditions. And when you start Visual Studio non-elevated (which you should do contrary to what most blog entries tell you), you can also debug it using the standard-user security context.

In the case you plan to write applications that expose both user and administrator functionality you can also programmatically find out in which security context the application was started and modify the application based on that. The following line of code tells you about your state:

bool isElevated = newWindowsPrincipal(
  WindowsIdentity.GetCurrent()).IsInRole(
    WindowsBuiltInRole.Administrator);

By talking to the shell (and thus the consent dialog) you can also programmatically elevate your application programmatically. You can use the standard .NET process API for that:

public static void StartElevated(
  string filename, string workingDirectory, string arguments)
{
  ProcessStartInfo startInfo = newProcessStartInfo();
  startInfo.UseShellExecute = true;
  startInfo.Verb = “runas”;
  startInfo.WorkingDirectory = workingDirectory;
  startInfo.FileName = filename;
  startInfo.Arguments = arguments;

  Process.Start(startInfo);
}

You should always make a conscious decision about who the target audience of your application is. If it is meant to be used by administrators then you need administrative privileges. If it is meant for normal users, you should be very careful to not introduce unneeded dependencies on administrative privileges. This is nothing new in Vista – UAC just makes it easier now for developers to switch between contexts and to find out if your apps work in both “worlds”. Happy testing!

 

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s