Run as Administrator, then execute something as the user

Z

Zarborg

I'm writing a little program that will run when a user logs in, checks their
password expiration and also installs a piece of monitoring software if
necessary.
The program has to run on Vista so I got my first experience writing for UAC.

I've worked though the signed manifest and all the other little quirky stuff
I have to do to get my app to run as Administrator (System.DirectoryServices
said it required admin rights) and everything is working just dandy.

But, I would also like to map drives for the user as I do this. Problem is
that when I map the drive using the Admin split token privs, it actually maps
the drive for the admin user, not the lower priv user token. So I see that
it works, it reports that it works, even checking the existence of the drive
letter work but the drive letters don't show for the end user.

Now for the weird $50 question.

Is there a way while my program is running under the Admin token to execute
something as the user? Like open a cmd shell and run a simple net use
command?

I have this code running the mapping. Works great on XP, and works under
Vista but I just don't see the drives as the user on Vista. (comments
removed for space)

Dim myProcess As Process = New Process
myProcess.StartInfo.FileName = "cmd.exe"
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
myProcess.StartInfo.CreateNoWindow = True
myProcess.StartInfo.Arguments = "/C net use K: \\vail\vmdk /persistent:no"
myProcess.Start()
myProcess.WaitForExit(10000)
If System.IO.Directory.Exists(strDrive) Then
txtStatus.Text = txtStatus.Text & "->Success "
Else
txtStatus.Text = txtStatus.Text & "->Failed "
End If


Really hoping that made sense....
 
M

Michel Posseth [MCP]

Hmm $50,-- :)

I have written a class that can solve this problem , i use this class to
write to a locations where normall users do not have access rights




### CLASS CODE ###
'Michel Posseth [MCP] 10-07-2008 , written to run parts of code in another
user context during runtime

Imports System.Security

Imports System.Security.Principal

Imports System.Runtime.InteropServices

Public Class ImpersonateSpecificUser

Implements IDisposable

Private Const LOGON32_LOGON_INTERACTIVE As Integer = 2

Private Const LOGON32_PROVIDER_DEFAULT As Integer = 0

Private impersonationContext As WindowsImpersonationContext

Declare Function LogonUserA Lib "advapi32.dll" (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 Integer

Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _

ByVal ExistingTokenHandle As IntPtr, _

ByVal ImpersonationLevel As Integer, _

ByRef DuplicateTokenHandle As IntPtr) As Integer

Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long

Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As
IntPtr) As Long

Public Event eSpecificUserImpersonation(ByVal Success As Boolean)

Private _Impersonated As Boolean

''' <summary>

''' Gets or sets a value indicating whether this <see
cref="ImpersonateSpecificUser" /> is impersonated.

''' </summary>

''' <value><c>true</c> if impersonated; otherwise, <c>false</c>.</value>

Public Property Impersonated() As Boolean

Get

Return _Impersonated

End Get

Private Set(ByVal value As Boolean)

_Impersonated = value

End Set

End Property

''' <summary>

''' Initializes a new instance of the <see cref="ImpersonateSpecificUser" />
class.

''' </summary>

''' <param name="UserName">Name of the user.</param>

''' <param name="Password">The password.</param>

''' <param name="Domain">The domain.</param>

Public Sub New(ByVal UserName As String, ByVal Password As String, ByVal
Domain As String)

If impersonateValidUser(UserName, Domain, Password) Then

RaiseEvent eSpecificUserImpersonation(True)

Else

'Your impersonation failed. Therefore, include a fail-safe mechanism here.

RaiseEvent eSpecificUserImpersonation(False)

End If

End Sub

''' <summary>

''' Impersonates the valid user.

''' </summary>

''' <param name="userName">Name of the user.</param>

''' <param name="domain">The domain.</param>

''' <param name="password">The password.</param>

''' <returns></returns>

Private Function impersonateValidUser(ByVal userName As String, ByVal domain
As String, ByVal password As String) As Boolean

Dim tempWindowsIdentity As WindowsIdentity

Dim token As IntPtr = IntPtr.Zero

Dim tokenDuplicate As IntPtr = IntPtr.Zero

impersonateValidUser = False

If RevertToSelf() Then

If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token) <> 0 Then

If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then

tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)

impersonationContext = tempWindowsIdentity.Impersonate()

If Not impersonationContext Is Nothing Then

impersonateValidUser = True

End If

End If

End If

End If

If Not tokenDuplicate.Equals(IntPtr.Zero) Then

CloseHandle(tokenDuplicate)

End If

If Not token.Equals(IntPtr.Zero) Then

CloseHandle(token)

End If

End Function

''' <summary>

''' Undoes the impersonation.

''' </summary>

Public Sub undoImpersonation()

impersonationContext.Undo()

Impersonated = False

End Sub

#Region " IDisposable Support "

Private disposedValue As Boolean = False ' To detect redundant calls

' IDisposable

Protected Overridable Sub Dispose(ByVal disposing As Boolean)

If Not Me.disposedValue Then

If disposing Then

' TODO: free other state (managed objects).

End If

If Impersonated Then 'wees er zeer van dat we weer in een normale context
draaien

undoImpersonation()

End If

' TODO: free your own state (unmanaged objects).

' TODO: set large fields to null.

End If

Me.disposedValue = True

End Sub



' This code added by Visual Basic to correctly implement the disposable
pattern.

Public Sub Dispose() Implements IDisposable.Dispose

' Do not change this code. Put cleanup code in Dispose(ByVal disposing As
Boolean) above.

Dispose(True)

GC.SuppressFinalize(Me)

End Sub

#End Region

''' <summary>

''' Impersonates the specific user_e specific user impersonation.

''' </summary>

''' <param name="Success">if set to <c>true</c> [success].</param>

Private Sub ImpersonateSpecificUser_eSpecificUserImpersonation(ByVal Success
As Boolean) Handles Me.eSpecificUserImpersonation

Me.Impersonated = Success

End Sub

End Class

### CLASS CODE ###



Usage :

Using UImp As New UserImpersonate.ImpersonateSpecificUser("Username",
"password", "Domain")

IF UImp.Impersonated Then

'all code here that must run in the user context or the method calls to
other procedures

End If

End Using

after this point the code runs in "Normall" modus

HTH
Michel Posseth [MCP]
 
M

Michel Posseth [MCP]

Hello Zarborg

Did the previous post solve your problem or can i give you anny further
assistance ?

regards

Michel
 
Z

Zarborg

Just getting a chance to work on this one again, got sidetracked with having
to install SCCM, SCOM, SharePoint 2007 integrated with Report Server 2005 and
2 brand new SQL servers. Doh!

I'll update again with either yea or nea next week. Thanks for the class btw!
 
Z

Zarborg

Oh, but I do have a question on the code though.

Because this is running as the user already, just under their admin level
token I don't have access to their password, nor would I want them to have to
enter it again during the login process. I'm going to look at this code to
see if I can get it to impersonate the non-admin token of the currently
logged in user, but if you knew how already that would be swell.

-Z
 

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

Top