Impersonation on Windows Server 2003

H

Halcyon Woodward

I have an ASP.NET application that I'm developing on Windows 2003 and IIS 6.
I have included the < identity impersonate="true" /> in the web.config file
to force the application code to run under the currently logged in user, and
the site disalows Anonymous access.

The problem I'm running into is this: At key points in the application
code, I need to write to the disk and perform other 'administrative' tasks
that will [in most cases] require code to run under an administrative or
utility account.

I have tried to impersonate the administrative account two different ways:
via an interop call to ImpersonateLoggedOnUser(securityToken) and via
calling the Impersonate() method against a WindowsIdentity object.

Both of these work, however the context I then run under is _severly_
limited. (The second method works better by the way, as you cannot
accidently drop down to the service account.)

For example, when under this impersonation context, I cannot access the
ConfigurationSettings.AppSettings object (which is what I really need), or
even the WindowsIdentity.GetCurrent() method. This is the result even if
the account I impersonate is in the Administrators group on the server.

I know that impersonation works differently on Windows 2000 as opposed to
Windows XP - so I'm assuming that the same is true in Windows 2003; but I
can't seem to find the methodology for doing what I need to in either 2000
or 2003.

Can anyone offer some insight?

Thanks,

hb.
 
Y

Yan-Hong Huang[MSFT]

Hello Halcyon,

Impersonating a windowsidentity did not help the process using the new windows credential. The process would still use the
credentials of aspnet_wp.exe, typically ASPNET.

So for disk writing issue, it is better for you to add ACL to that folder to allow aspnet account to write to it. Besides, we could
use CreateProcessAsUser to spawn a new process under new credential.

Here is one sample for you:

The user credential being used for spawning the process must have Replace A Process Level Token and Adjust Memory
Quotas privs for this to work.


Imports System.Data

Imports System.Data.SqlClient

Imports System.Globalization

Imports System.Diagnostics

Imports System.Runtime.InteropServices

Imports System.Security.Principal

Imports System.Security.Permissions





Public Class WebForm1

Inherits System.Web.UI.Page



<StructLayout(LayoutKind.Sequential)> Public Structure STARTUPINFO

Public cb As Int32

Public lpReserved As String

Public lpDesktop As String

Public lpTitle As String

Public dwX As UInt32

Public dwY As UInt32

Public dwXSize As UInt32

Public dwYSize As UInt32

Public dwXCountChars As UInt32

Public dwYCountChars As UInt32

Public dwFillAttribute As UInt32

Public dwFlags As UInt32

Public wShowWindow As Int16

Public cbReserved2 As Int16

Public lpReserved2 As IntPtr

Public hStdInput As IntPtr

Public hStdOutput As IntPtr

Public hStdError As IntPtr

End Structure



<StructLayout(LayoutKind.Sequential)> Public Structure PROCESS_INFORMATION

Public hProcess As IntPtr

Public hThread As IntPtr

Public dwProcessId As UInt32

Public dwThreadId As UInt32

End Structure



<StructLayout(LayoutKind.Sequential)> Public Structure SECURITY_ATTRIBUTES

Public Length As Int32

Public lpSecurityDescriptor As IntPtr

Public bInheritHandle As Boolean

End Structure



<DllImport("kernel32.dll", EntryPoint:="CloseHandle", SetLastError:=True, CharSet:=CharSet.Auto, CallingConvention:
=CallingConvention.StdCall)> _

Public Shared Function CloseHandle(ByVal handle As IntPtr) As Boolean

End Function



<DllImport("advapi32.dll", EntryPoint:="CreateProcessAsUser", SetLastError:=True, CharSet:=CharSet.Ansi,
CallingConvention:=CallingConvention.StdCall)> _

Public Shared Function CreateProcessAsUser(ByVal hToken As IntPtr, ByVal lpApplicationName As String, ByVal
lpCommandLine As String, ByRef lpProcessAttributes As SECURITY_ATTRIBUTES, _

ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, ByVal bInheritHandle As Boolean, ByVal dwCreationFlags As
Int32, ByVal lpEnvironment As IntPtr, _

ByVal lpCurrentDirectory As String, ByRef lpStartupInfo As STARTUPINFO, ByRef lpProcessInformation As
PROCESS_INFORMATION) As Boolean

End Function



<DllImport("advapi32.dll", EntryPoint:="DuplicateTokenEx")> _

Public Shared Function DuplicateTokenEx(ByVal ExistingTokenHandle As IntPtr, ByVal dwDesiredAccess As Int32, _

ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, ByVal TokenType As Int32, _

ByVal ImpersonationLevel As Int32, ByRef DuplicateTokenHandle As IntPtr) As Boolean

End Function



<DllImport("advapi32.dll")> _

Public Shared Function LogonUser(ByVal lpszUsername As String, ByVal lpszDomain As String, ByVal lpszPassword As
String, _

ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, ByRef phToken As Integer) As Boolean

End Function



Private Sub RunProcessAsUser(ByVal strUid As String, ByVal strPwd As String, ByVal strDomain As String, ByVal
strProcessPath As String)

''The Windows NT user token.

'Dim token1 As Integer



''Get the user token for the specified user, machine, and password using the unmanaged LogonUser method.



''The parameters for LogonUser are the user name, computer name, password,

''Logon type (LOGON32_LOGON_NETWORK_CLEARTEXT), Logon provider (LOGON32_PROVIDER_DEFAULT),

''and user token.

'Dim loggedOn As Boolean = LogonUser(strUid, strDomain, strPwd, 3, 0, token1)

'Dim token2 As IntPtr = New IntPtr(token1)



'Dim mWI2 As WindowsIdentity = New WindowsIdentity(token2)



''Impersonate the user.

'Dim mWIC As WindowsImpersonationContext = mWI2.Impersonate()



Dim Token As IntPtr = New IntPtr(0)

Token = WindowsIdentity.GetCurrent().Token ¡®will either use ASPNET, or the impersonated windows credential if
above section is uncommented



Dim ret As Boolean



Dim sa As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES()

sa.bInheritHandle = False

sa.Length = Marshal.SizeOf(sa)

sa.lpSecurityDescriptor = IntPtr.op_Explicit(0)



Const GENERIC_ALL As Int32 = &H10000000



Const SecurityImpersonation As Int32 = 2

Const TokenType As Int32 = 1

Dim DupedToken As IntPtr = New IntPtr(0)



ret = DuplicateTokenEx(Token, GENERIC_ALL, sa, SecurityImpersonation, TokenType, DupedToken)





Dim si As STARTUPINFO = New STARTUPINFO()

si.cb = Marshal.SizeOf(si)

si.lpDesktop = ""



Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION()



ret = CreateProcessAsUser(DupedToken, strProcessPath, "", sa, sa, False, 0, IntPtr.op_Explicit(0), "c:\\", si, pi)

'ret = CreateProcessAsUser(DupedToken, strProcessPath, "", IntPtr.Zero, IntPtr.Zero, True, 0, IntPtr.Zero, "C:\\", si, pi)



'Revert to previous identity.

'mWIC.Undo()



'ret = CloseHandle(token2)

ret = CloseHandle(DupedToken)



End Sub





End Class



Best regards,
Yanhong Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------
!From: "Halcyon Woodward" <[email protected]>
!Subject: Impersonation on Windows Server 2003
!Date: Wed, 16 Jul 2003 15:29:50 -0700
!Lines: 35
!X-Priority: 3
!X-MSMail-Priority: Normal
!X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
!X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
!Message-ID: <OBefGn#[email protected]>
!Newsgroups: microsoft.public.dotnet.framework.aspnet.security
!NNTP-Posting-Host: nausers.mccann.com 199.4.18.2
!Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!tk2msftngp13.phx.gbl
!Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework.aspnet.security:5921
!X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.security
!
!I have an ASP.NET application that I'm developing on Windows 2003 and IIS 6.
!I have included the < identity impersonate="true" /> in the web.config file
!to force the application code to run under the currently logged in user, and
!the site disalows Anonymous access.
!
!The problem I'm running into is this: At key points in the application
!code, I need to write to the disk and perform other 'administrative' tasks
!that will [in most cases] require code to run under an administrative or
!utility account.
!
!I have tried to impersonate the administrative account two different ways:
!via an interop call to ImpersonateLoggedOnUser(securityToken) and via
!calling the Impersonate() method against a WindowsIdentity object.
!
!Both of these work, however the context I then run under is _severly_
!limited. (The second method works better by the way, as you cannot
!accidently drop down to the service account.)
!
!For example, when under this impersonation context, I cannot access the
!ConfigurationSettings.AppSettings object (which is what I really need), or
!even the WindowsIdentity.GetCurrent() method. This is the result even if
!the account I impersonate is in the Administrators group on the server.
!
!I know that impersonation works differently on Windows 2000 as opposed to
!Windows XP - so I'm assuming that the same is true in Windows 2003; but I
!can't seem to find the methodology for doing what I need to in either 2000
!or 2003.
!
!Can anyone offer some insight?
!
!Thanks,
!
!hb.
!
!
!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top