The link to "Marshaling SecureString Passwords to String - Mark Nicholson
" at http://dotnet.org.za/markn/archive/2008/10/04/handling-passwords.aspx finally displayed.
So your statement, "C# is using its unsafe code feature to do pointer manipulations," seems to be addressed with "HOW TO: Wrap a UCOMIStream in a Stream Class in Visual Basic .NET" at http://support.microsoft.com/kb/321695. (I searched on "AddrOfPinnedObject".)
I did not read your whole question (link to post always timed out), but are these classes and testing code helpful? The password never lives as a System.String; therefore, you need a SecureStringTextBox implementation as noted in your question.
I dislike adding all this code. Let me know what code is helpful, and I will edit the answer to keep only the helpful stuff.
Imports System.Security
Imports System.Security.Principal
Imports System.Security.Permissions
Imports System.Runtime.InteropServices
''' <summary>
''' Helper class to programmatically impersonate a user, load and unload a user's profile, and perform other maintenance-related tasks for impersonating a user.
''' </summary>
Public Class ImpersonationHelper
Implements IDisposable
#Region " IDisposable Implementaton "
Private _disposed As Boolean
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
''' <summary>
''' Implementation of the <b>IDisposable</b> interface.
''' </summary>
''' <remarks>This method calls <see>Undo</see> if impersonation is still being performed. This method calls the common language runtime version of the Dispose method.</remarks>
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
System.GC.SuppressFinalize(Me)
End Sub
''' <summary>
''' Implementation of the <b>IDisposable</b> interface.
''' </summary>
''' <param name="disposing">If <b>true</b>, the object to be disposed is finalized and collected by the garbage collector; otherwise, <b>false</b>.</param>
''' <remarks>This method calls Undo if impersonation is still being performed. This method calls the common language runtime version of the Dispose method.</remarks>
Protected Overloads Sub Dispose(ByVal disposing As Boolean)
If Not _disposed Then
If disposing Then
If Not IsNothing(_impersonationContext) Then
_impersonationContext.Undo()
_impersonationContext.Dispose()
End If
End If
_impersonationContext = Nothing
End If
_disposed = True
End Sub
#End Region
'2009.02.12 AMJ
' Modified From:
' How to implement impersonation in an ASP.NET application (KB306158)
' http://support.microsoft.com/kb/306158
' Implemented IDisposable based on ImpersonationHelper class of
' Namespace: Microsoft.Office.Excel.Server.Addins.ComputeCluster.Security
' Assembly: Microsoft.Office.Excel.Server.Addins.ComputeCluster (in microsoft.office.excel.server.addins.computecluster.dll)
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Const LOGON32_LOGON_BATCH As Integer = 4
Const LOGON32_LOGON_SERVICE As Integer = 5
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_PROVIDER_WINNT35 As Integer = 1
Private Enum SECURITY_IMPERSONATION_LEVEL
SecurityAnonymous = 0
SecurityIdentification = 1
SecurityImpersonation = 2
SecurityDelegation = 3
End Enum
Private Declare Auto Function LogonUser Lib "advapi32.dll" ( _
ByVal username As String, _
ByVal domain As String, _
ByVal password As IntPtr, _
ByVal logonType As Integer, _
ByVal logonProvider As Integer, _
ByRef token As IntPtr) As Boolean
Private Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _
ByVal ExistingTokenHandle As IntPtr, _
ByVal ImpersonationLevel As SECURITY_IMPERSONATION_LEVEL, _
ByRef DuplicateTokenHandle As IntPtr) As Integer
Private Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Dim _impersonationContext As WindowsImpersonationContext
Dim _domain As String
Dim _login As String
Dim _password As SecureString
#Region " Standard Constructor & Properties "
''' <summary>
''' Initializes a new instance of the ImpersonationHelper class.
''' </summary>
''' <param name="domain">The domain or computer name of the user to impersonate.</param>
''' <param name="userName">The user name of the user to impersonate.</param>
''' <param name="password">The secure string password of UserName. For more information about secure strings, see the <see cref="System.Security.SecureString">SecureString</see> class.</param>
<DebuggerNonUserCode()> _
Public Sub New(ByVal domain As String, ByVal userName As String, ByVal password As SecureString)
Me.Domain = domain
Me.Login = userName
Me.Password = password
End Sub
''' <summary>
''' Do not allow a new instance of the ImpersonationHelper class without credentials.
''' </summary>
Private Sub New()
End Sub
''' <summary>
''' Gets or sets the domain of the user to impersonate.
''' </summary>
''' <value>The domain of the user.</value>
<DebuggerNonUserCode()> _
Public Property Domain() As String
Get
Return _domain
End Get
Set(ByVal value As String)
_domain = value
End Set
End Property
''' <summary>
''' Gets or sets the user name of the user to impersonate.
''' </summary>
''' <value>The user name.</value>
<DebuggerNonUserCode()> _
Public Property Login() As String
Get
Return _login
End Get
Set(ByVal value As String)
_login = value
End Set
End Property
''' <summary>
''' Sets the encrypted password of the user to impersonate.
''' </summary>
''' <value>The encrypted password.</value>
<DebuggerNonUserCode()> _
Public WriteOnly Property Password() As SecureString
Set(ByVal value As SecureString)
_password = value
End Set
End Property
#End Region
''' <summary>
''' Performs the impersonation of the user based on the parameters provided in the constructor.
''' </summary>
''' <remarks>
''' <para>If logon fails using the supplied credentials, an exception is thrown. The exception is thrown because this method is unable to duplicate the logged-on user's token for purposes of impersonation or is unable to create a Windows identity from the user's impersonated token.</para>
''' <para>For details about the direct cause of the impersonation failure, you can inspect the inner exception.</para>
''' </remarks>
<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _
Public Sub ImpersonateUser()
Dim fResult As Boolean = False 'assume impersonation failed
Dim hPassword As IntPtr = IntPtr.Zero
Dim hToken As IntPtr = IntPtr.Zero
Dim hTokenDuplicate As IntPtr = IntPtr.Zero
Dim oException As ImpersonationException = Nothing
If RevertToSelf <> 0 Then
hPassword = Marshal.SecureStringToGlobalAllocUnicode(_password)
If LogonUser(Me.Login, Me.Domain, hPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken) Then
If DuplicateToken(hToken, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, hTokenDuplicate) <> 0 Then
_impersonationContext = New WindowsIdentity(hTokenDuplicate).Impersonate()
If Not _impersonationContext Is Nothing Then
fResult = True
End If
End If
Else
oException = New ImpersonationException(Me.Login, Me.Domain)
End If
If hPassword.Equals(IntPtr.Zero) = False Then
Marshal.ZeroFreeGlobalAllocUnicode(hPassword)
End If
End If
If Not hTokenDuplicate.Equals(IntPtr.Zero) Then
CloseHandle(hTokenDuplicate)
End If
If Not hToken.Equals(IntPtr.Zero) Then
CloseHandle(hToken)
End If
If Not (oException Is Nothing) Then
Throw oException
End If
End Sub
''' <summary>
''' Undoes the impersonation of the user, if it is impersonated.
''' </summary>
''' <remarks>Use this method to free the objects associated with impersonation.</remarks>
<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _
<DebuggerNonUserCode()> _
Public Sub Undo()
_impersonationContext.Undo()
_impersonationContext = Nothing
End Sub
Public Shared Function InvokeAsUser(ByVal userName As String, ByVal domain As String, ByVal password As SecureString, ByVal methodToCall As [Delegate], ByVal ParamArray parameters() As Object) As Object
Dim oResult As Object = Nothing
Using oImpersonation As New ImpersonationHelper(domain, userName, password)
oImpersonation.ImpersonateUser()
oResult = methodToCall.DynamicInvoke(parameters)
End Using
Return oResult
End Function
End Class
Public Class ImpersonationException
Inherits System.Exception
Public ReadOnly Login As String
Public ReadOnly Domain As String
Public Sub New(ByVal userName As String, ByVal domain As String)
MyBase.New(String.Format("Impersonation failure: {1}{0}", userName, domain), New System.ComponentModel.Win32Exception)
End Sub
End Class
Imports Missico.Personal
Imports System.Security
Imports Microsoft.VisualStudio.TestTools.UnitTesting
<TestClass()> _
Public Class ImpersonationHelperTest
Private testContextInstance As TestContext
Public Property TestContext() As TestContext
Get
Return testContextInstance
End Get
Set(ByVal value As TestContext)
testContextInstance = value
End Set
End Property
<TestMethod()> _
Public Sub ImpersonationHelperTest()
'testing only, never initialize the characters of the password in this fashion
'replace with valid password
Dim oPassword As New System.Security.SecureString
oPassword.AppendChar("o"c)
oPassword.AppendChar("o"c)
oPassword.AppendChar("p"c)
oPassword.AppendChar("s"c)
oPassword.AppendChar("!"c)
oPassword.AppendChar(" "c)
oPassword.AppendChar("n"c)
oPassword.AppendChar("o"c)
oPassword.AppendChar(" "c)
oPassword.AppendChar("p"c)
oPassword.AppendChar("a"c)
oPassword.AppendChar("s"c)
oPassword.AppendChar("s"c)
oPassword.Appe