B
BethC327
I need to save a file from an ASP.Net page to a folder on a separate file
server. The file server is on a different domain than the web server. I
have been told that due to a complex networking structure, I must use a UNC
to access the folder on the file server. Both servers are running Win2K.
The web server is running IIS6.
I followed the following example in the .Net Developer's guide to try to
impersonate a user with the proper permissions on the file server:
Sometimes you might need to obtain a Windows NT account token to impersonate
a Windows account. For example, your ASP.NET-based application might have to
act on behalf of several users at different times. Your application might
accept a token that represents an administrator from Internet Information
Services (IIS), impersonate that user, perform an operation, and revert to
the previous identity. Next, it might accept a token from IIS that represents
a user with fewer rights, perform some operation, and revert again.
In situations where your application must impersonate a Windows account that
has not been attached to the current thread by IIS, you must retrieve that
account's token and use it to activate the account. You can do this by
performing the following tasks:
Retrieve an account token for a particular user by making a call to the
unmanaged LogonUser method. This method is not in the .NET Framework base
class library, but is located in the unmanaged advapi32.dll. Accessing
methods in unmanaged code is an advanced operation and is beyond the scope of
this discussion. For more information, see Interoperating with Unmanaged
Code. For more information about the LogonUser method and advapi32.dll, see
the Platform SDK documentation.
Create a new instance of the WindowsIdentity class, passing the token. The
following code demonstrates this call, where hToken represents a Windows
token.
[C#]
WindowsIdentity ImpersonatedIdentity = new WindowsIdentity(hToken);
[Visual Basic]
Dim ImpersonatedIdentity As New WindowsIdentity(hToken)
Begin impersonation by creating a new instance of the
WindowsImpersonationContext class and initializing it with the
WindowsIdentity.Impersonate method of the initialized class, as shown in the
following code.
[C#]
WindowsImpersonationContext MyImpersonation =
ImpersonatedIdentity.Impersonate();
[Visual Basic]
WindowsImpersonationContext MyImpersonation =
ImpersonatedIdentity.Impersonate()
When you no longer need to impersonate, call the
WindowsImpersonationContext.Undo method to revert the impersonation, as shown
in the following code.
[C#]
MyImpersonation.Undo();
[Visual Basic]
MyImpersonation.Undo()
If trusted code has already attached a WindowsPrincipal object to the
thread, you can call the instance method Impersonate, which does not take an
account token. Note that this is only useful when the WindowsPrincipal object
on the thread represents a user other than the one under which the process is
currently executing. For example, you might encounter this situation using
ASP.NET with Windows authentication turned on and impersonation turned off.
In this case, the process is running under an account configured in Internet
Information Services (IIS) while the current principal represents the Windows
user that is accessing the page.
Note that neither Impersonate nor Undo changes the Principal object
associated with the current call context. Rather, impersonation and reverting
change the token associated with the current operating system process..
BELOW IS THE CODE FOR THE ASP.NET PAGE RUNNING ON MY WEB SERVER:
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Web
Imports System.Web.SessionState
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls
Imports System.Security.Principal
Imports System.Security.Permissions
Imports System.Runtime.InteropServices
Imports System.Environment
Public Class ImageUpload
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
'NOTE: The following placeholder declaration is required by the Web Form
Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
Dim fileName As String
If Request.Files.Count <> 0 Then
' Save the file to the server.
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_LOGON_NETWORK As Integer = 3
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Dim tokenHandle As New IntPtr(0)
tokenHandle = IntPtr.Zero
LogonUser("Webuser", "ct.fileserver.com", "webuser",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle)
Dim ImpersonatedIdentity As New WindowsIdentity(tokenHandle)
Dim MyImpersonation As WindowsImpersonationContext
MyImpersonation = ImpersonatedIdentity.Impersonate(tokenHandle)
fileName = "\\fileserver\uploads\123\" &
Request.Files(0).FileName.ToString
Request.Files(0).SaveAs(fileName)
CloseHandle(tokenHandle)
MyImpersonation.Undo()
End If
End Sub
<DllImport("advapi32.dll", SetLastError:=True)> _
Private 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 IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
Private Function CloseHandle(ByVal handle As IntPtr) As Boolean
End Function
End Class
Webuser is a user in the ct.fileserver.com domain. The password for user
Webuser is "webuser". The "\\fileserver\uploads\123" folder has Full Control
set for the Everyone group in the fileserver domain.
When I run the application I receive the error "Token cannot be zero".
Any insights into what I'm doing wrong here would be appreciated.
server. The file server is on a different domain than the web server. I
have been told that due to a complex networking structure, I must use a UNC
to access the folder on the file server. Both servers are running Win2K.
The web server is running IIS6.
I followed the following example in the .Net Developer's guide to try to
impersonate a user with the proper permissions on the file server:
Sometimes you might need to obtain a Windows NT account token to impersonate
a Windows account. For example, your ASP.NET-based application might have to
act on behalf of several users at different times. Your application might
accept a token that represents an administrator from Internet Information
Services (IIS), impersonate that user, perform an operation, and revert to
the previous identity. Next, it might accept a token from IIS that represents
a user with fewer rights, perform some operation, and revert again.
In situations where your application must impersonate a Windows account that
has not been attached to the current thread by IIS, you must retrieve that
account's token and use it to activate the account. You can do this by
performing the following tasks:
Retrieve an account token for a particular user by making a call to the
unmanaged LogonUser method. This method is not in the .NET Framework base
class library, but is located in the unmanaged advapi32.dll. Accessing
methods in unmanaged code is an advanced operation and is beyond the scope of
this discussion. For more information, see Interoperating with Unmanaged
Code. For more information about the LogonUser method and advapi32.dll, see
the Platform SDK documentation.
Create a new instance of the WindowsIdentity class, passing the token. The
following code demonstrates this call, where hToken represents a Windows
token.
[C#]
WindowsIdentity ImpersonatedIdentity = new WindowsIdentity(hToken);
[Visual Basic]
Dim ImpersonatedIdentity As New WindowsIdentity(hToken)
Begin impersonation by creating a new instance of the
WindowsImpersonationContext class and initializing it with the
WindowsIdentity.Impersonate method of the initialized class, as shown in the
following code.
[C#]
WindowsImpersonationContext MyImpersonation =
ImpersonatedIdentity.Impersonate();
[Visual Basic]
WindowsImpersonationContext MyImpersonation =
ImpersonatedIdentity.Impersonate()
When you no longer need to impersonate, call the
WindowsImpersonationContext.Undo method to revert the impersonation, as shown
in the following code.
[C#]
MyImpersonation.Undo();
[Visual Basic]
MyImpersonation.Undo()
If trusted code has already attached a WindowsPrincipal object to the
thread, you can call the instance method Impersonate, which does not take an
account token. Note that this is only useful when the WindowsPrincipal object
on the thread represents a user other than the one under which the process is
currently executing. For example, you might encounter this situation using
ASP.NET with Windows authentication turned on and impersonation turned off.
In this case, the process is running under an account configured in Internet
Information Services (IIS) while the current principal represents the Windows
user that is accessing the page.
Note that neither Impersonate nor Undo changes the Principal object
associated with the current call context. Rather, impersonation and reverting
change the token associated with the current operating system process..
BELOW IS THE CODE FOR THE ASP.NET PAGE RUNNING ON MY WEB SERVER:
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Web
Imports System.Web.SessionState
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls
Imports System.Security.Principal
Imports System.Security.Permissions
Imports System.Runtime.InteropServices
Imports System.Environment
Public Class ImageUpload
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
'NOTE: The following placeholder declaration is required by the Web Form
Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
Dim fileName As String
If Request.Files.Count <> 0 Then
' Save the file to the server.
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_LOGON_NETWORK As Integer = 3
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Dim tokenHandle As New IntPtr(0)
tokenHandle = IntPtr.Zero
LogonUser("Webuser", "ct.fileserver.com", "webuser",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle)
Dim ImpersonatedIdentity As New WindowsIdentity(tokenHandle)
Dim MyImpersonation As WindowsImpersonationContext
MyImpersonation = ImpersonatedIdentity.Impersonate(tokenHandle)
fileName = "\\fileserver\uploads\123\" &
Request.Files(0).FileName.ToString
Request.Files(0).SaveAs(fileName)
CloseHandle(tokenHandle)
MyImpersonation.Undo()
End If
End Sub
<DllImport("advapi32.dll", SetLastError:=True)> _
Private 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 IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
Private Function CloseHandle(ByVal handle As IntPtr) As Boolean
End Function
End Class
Webuser is a user in the ct.fileserver.com domain. The password for user
Webuser is "webuser". The "\\fileserver\uploads\123" folder has Full Control
set for the Everyone group in the fileserver domain.
When I run the application I receive the error "Token cannot be zero".
Any insights into what I'm doing wrong here would be appreciated.