Why do many elevation operations fail if a network share is involved?

One fairly annoying aspect of elevation on Windows Vista is that one often cannot, in general, successfully elevate to perform many tasks when they involve a network share.

For example, if one tries to copy a file from a UNC share that one has provided explicit credentials to into a directory that requires administrative access (say, %systemroot%), the operation will often ultimately fail with an error message akin to the following:

[Folder Access Denied]

You don’t have permission to copy files to this location over the network. You can copy files to the Documents folder and then move them to this location.

[Cancel]

This message is somewhat confusing at first glance, considering that to get to this point, one had to elevate to an administrator in the first place!

What actually happens under the hood here is that the code that is elevated to perform the file copy loses access to the network share at the same time as it gains access to the desired destination directory on the local computer. The reason behind this is, however, slightly complicated, and to be perfectly fair, I’m not sure that I could really phase a better (concise) error message in this case myself. Nevertheless, I shall attempt to explain the underlying cause behind the failure in this case.

At a high level, this problem occurs because explicit network share credentials are stored on a per logon session basis in Windows, and by virtue of switching to the elevation token (whether that be a different user entirely, if one is logged on as a “plain user”, or simply the elevated “shadow token” if one is logged on as a non-elevated administrator), the code performing the file copying runs under a different logon session than the one in which network share credentials were supplied.

A token is associated with a logon session by means of an associated attribute called the authentication ID, which represents the LUID of the LSA logon session to which the token is attached. An LSA logon session is, confusingly enough, completely different from a Terminal Server session (though a TS session will, typically, have one or more LSA logon sessions associated with it). LSA logon sessions are generally created when a token is generated by LSA in response to an authentication attempt, such as a LogonUser call. More than one token can share a particular logon session; in the common case, the shell and most other parts of the end user Windows desktop all run under the context of a single LSA logon session.

Elevation changes this typical behavior of everything on the user’s desktop running under the same logon session, as code that has been elevated runs under a different security context. Conceptually, this process is in many ways very similar to what happens when one starts a program under alternate credentials using Run As (which, by the way, suffers a similar limitation with respect to network share access).

The result is that while the user may have provided credentials to the shell for a network share access, these credentials are attached to a specific logon session. Since the elevated code has its own logon session (with its own network share session credential “namespace”), the only credentials that will typically be available to it are the implicit NTLM or Kerberos credentials corresponding to the elevated user account. Given that most of the time, elevation is to a local computer account (an administrator), this account will typically not have any privileges on the network, unless there exists an account under the same name with the same password as the elevated account on the remote machine in question.

The error dialog already presents one workaround to this problem, which is to copy the data in question to a local drive and then elevate (with the understanding that a local computer administrator will likely have access to any location on the computer that one might choose to copy the file(s) in question to). Another workaround is to elevate a command prompt instance, use net use to provide explicit network credentials to the remote network share, and then perform the operation from the command prompt (or start a program from the command prompt to do the operation for you).

Elevation of actual programs residing on a network share is handled in a slightly better fashion, in that the consent UI will prompt for network credentials after asking for elevation credentials or elevation consent. This support is, however, not enabled for elevated file copy, or many other shell operations that have automatic elevation.

Tags: ,

4 Responses to “Why do many elevation operations fail if a network share is involved?”

  1. Gert-Jan says:

    I understand the technical part of the issue, but I fail to see why Windows can’t just make this work correctly:
    – it can actually implement what the error message says, i.e. make the intermediate copy itself before elevating for the final copy to the destination
    – it can read from the share using the user’s credentials and write (e.g. by spawning a helper process or something) using the elevated credentials.
    So it may be a technical explanation of what is happening but it is not an excuse :-)

  2. Skywing says:

    I am not on the Microsoft payroll, nor did I have any influence on those who implemented this functionality; thus it would be inaccurate (to say the least) to consider this posting any sort of excuse for the current behavior.

    This post is intended solely as (hopefully) informative information on how things operate internally right now.

  3. Rob says:

    @Gert-Jan: My understanding of the way that UAC and (in general) the Windows security system is that each thread has a security token. Threads inherit the security token from the parent process when they are spawned unless they are given a specific token. The Windows API does not provide for a way for a thread to elevate itself, even with the LogonUser/ImpersonateLoggedOnUser functions; the only way to elevate within-process is to use the COM elevation moniker (Elevation:Administrator!new:{guid} (see http://msdn2.microsoft.com/en-us/library/ms679687.aspx for more information). The problem with copying is that when you perform the copy, you’ve obtained the administrative token already; you’d either need to marshal the copying data across-threads or across process, which, I believe, has restrictions on it (one of the reasons you can’t, for example, drop a Visual Studio 2005 solution file onto Visual Studio running as an administrator).

    My question is – since I don’t have a domain to play around with – does a domain administrator have the same kind of restrictions imposed on the security token when running with UAC? And if so, could granting “Domain Administrators” or your specific domain user account write access to that folder correct the issue?

  4. Yuhong Bao says:

    “it can read from the share using the user’s credentials and write (e.g. by spawning a helper process or something) using the elevated credentials.”
    To elevate, Explorer already have to spawn a helper process, and that is true for both UAC and sudo. So basically you’d have to read the data from a non-elevated process, and then pass the data to the helper process, then have the helper process write the data, which is far harder than just have the helper process do both reading and writing. Also, doing this while properly preserving metadata (and NTFS has a lot of them, some of them are alternate data streams, OS/2 EAs, permissions) is even harder, which is why CopyFile and MoveFile was created in the first place.
    BTW, in UNIX, do sudo have this problem?