When working with server based applications like ASP.NET and WCF or other services, you will for sure be required to use impersonation. I’m not going to describe in this post anything about impersonation, because it is pretty well described topic. Here is the link to ASP.NET related impersonation and this one is for WCF Impersonation.
If you want to understand what this post is about, you have to understand what impersonation is.
Problem Description
Sometimes you will have a service or application which uses impersonation. For exampe in a case of ASP.NET application you will use
<!-- Web.config file. –>
<identity impersonate="true"/>
In a case of WCF would be imperatively in your code : ImpersonationOption.Required
When the request arrives some method or operation at the server side then current identity can be queried as follows:
WindowsIdentity.GetCurrent();
And this is the result of this statement:
{System.Security.Principal.WindowsIdentity} AuthenticationType: "Kerberos" Groups: {System.Security.Principal.IdentityReferenceCollection} ImpersonationLevel: Impersonation IsAnonymous: false IsAuthenticated: true IsGuest: false IsSystem: false Name: "TESTDOMAIN\\myuseraccount" Owner: {S-2-2-32-514} Token: 588 User: {S-1-5-21-000000000-3774364995-3200000000-1112} |
As you see I’m as a caller impersonated: myuseraccount. This is fine, but what if your code contains some statemens which requires identity of the process and not identity of impersonated user? You may asking yourself why somebody would need such crazy requirement? Here are few examples:
- Imagine you have a API which is responsible for logging. Each time you call some method the method simply writes something in the file. To enable access to the file you have to enable all impersonated users to access the file. This will be very often an issue.
- Another example is when you have a method which access one file by using of impersonated identities, but the same method has to asses the database which does not permit any of impersonated users, but the process account only.
- Last but not least, using of DPAPI in context of interactive user (cluster) like
ProtectedData.Protect(Encoding.UTF8.GetBytes(plainValue), entropy, DataProtectionScope.CurrentUser) will be a serius issue in this case.
The solution
The solution in this case is called Reverting or Undo operation. If you have impersonated by yourself as shown below, you can call Undo() to revert the context to the process identity.
WindowsImpersonationContext ctx = WindowsIdentity.Impersonate(IntPtr.Zero); ctx.Undo();
|
However, if you have been impersonated automatically by using of configuration, then you don;t have the context. That means you cannot call
Undo(); But, you can use System32 API
RevertToSelf(); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool RevertToSelf() . . . id = WindowsIdentity.GetCurrent(); // From here: TESTDOMAIN\myuseraccount RevertToSelf(); // From here: TESTDOMAIN\processaccount ... perform some operation in context of process identity… id.Impersonate(); // From here: TESTDOMAIN\myuseraccount |
After calling of RevertToself the identity looks like:
{System.Security.Principal.WindowsIdentity} AuthenticationType: "Kerberos" Groups: {System.Security.Principal.IdentityReferenceCollection} ImpersonationLevel: None IsAnonymous: false IsAuthenticated: true IsGuest: false IsSystem: false Name: "TESTDOMAIN\processaccount" Owner: {A-1-2-32-00000000--3007986800-1000} Token: 2764 User: {A-1-2-32-00000000-389563229-3007986800-0000} |
Posted
May 15 2009, 11:59 PM
by
Damir Dobric