I try to impersonate a specific part of my c# winforms application as domain admin but getting permission errors.
The executed code is quite simple. If i execute this bit of code as user "max neumann" it will show a popup "DE123450\max-neumann" and after the impersonator "DE12345\Administrator" which is the domain admin (or local admin), so the impersonation works fine.
MessageBox.Show(WindowsIdentity.GetCurrent().Name);
new Impersonator("Administrator", "DE123450", "Password");
MessageBox.Show(WindowsIdentity.GetCurrent().Name);
if(!Directory.Exists(installationPath))
{
Directory.CreateDirectory(installationPath);
}
On Directory.CreateDirectory I get this error which pointing out, that the actual user has not enough rights to create a directory at this path. I dont understand why thats happening.
System.UnauthorizedAccessException: "Der Zugriff auf den Pfad "C:\Program Files (x86)\TEST" wurde verweigert."
If I run the program as administrator its working as expected. Can someone point me in the right direction?
I used the impersonator class from this website https://www.codeproject.com/Articles/10090/A-small-C-Class-for-impersonating-a-User
Impersonator.cs
namespace AtbasNetClientInstaller.Functions
{
#region Using directives.
// ----------------------------------------------------------------------
using System;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.ComponentModel;
// ----------------------------------------------------------------------
#endregion
/////////////////////////////////////////////////////////////////////////
/// <summary>
/// Impersonation of a user. Allows to execute code under another
/// user context.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <remarks>
/// This class is based on the information in the Microsoft knowledge base
/// article http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158
///
/// Encapsulate an instance into a using-directive like e.g.:
///
/// ...
/// using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
/// {
/// ...
/// [code that executes under the new context]
/// ...
/// }
/// ...
///
/// Please contact the author Uwe Keim (mailto:uwe.keim#zeta-software.de)
/// for questions regarding this class.
/// </remarks>
public class Impersonator :
IDisposable
{
#region Public methods.
// ------------------------------------------------------------------
/// <summary>
/// Constructor. Starts the impersonation with the given credentials.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
public Impersonator(
string userName,
string domainName,
string password )
{
ImpersonateValidUser( userName, domainName, password );
}
// ------------------------------------------------------------------
#endregion
#region IDisposable member.
// ------------------------------------------------------------------
public void Dispose()
{
UndoImpersonation();
}
// ------------------------------------------------------------------
#endregion
#region P/Invoke.
// ------------------------------------------------------------------
[DllImport("advapi32.dll", SetLastError=true)]
private static extern int LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(
IntPtr handle);
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
// ------------------------------------------------------------------
#endregion
#region Private member.
// ------------------------------------------------------------------
/// <summary>
/// Does the actual impersonation.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
private void ImpersonateValidUser(
string userName,
string domain,
string password )
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
try
{
if ( RevertToSelf() )
{
if ( LogonUser(
userName,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref token ) != 0 )
{
if ( DuplicateToken( token, 2, ref tokenDuplicate ) != 0 )
{
tempWindowsIdentity = new WindowsIdentity( tokenDuplicate );
impersonationContext = tempWindowsIdentity.Impersonate();
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
finally
{
if ( token!= IntPtr.Zero )
{
CloseHandle( token );
}
if ( tokenDuplicate!=IntPtr.Zero )
{
CloseHandle( tokenDuplicate );
}
}
}
/// <summary>
/// Reverts the impersonation.
/// </summary>
private void UndoImpersonation()
{
if ( impersonationContext!=null )
{
impersonationContext.Undo();
}
}
private WindowsImpersonationContext impersonationContext = null;
// ------------------------------------------------------------------
#endregion
}
/////////////////////////////////////////////////////////////////////////
}
Related
this is my code and I want to know how to use network credentials in my code
string filePath = Path.Combine(#"\\192.168.5.90\uploads", newfilename);
using (var filestream = new FileStream(filePath, FileMode.Create,FileAccess.Write))
{
await uploadfile.CopyToAsync(filestream);
}
return Ok(newfilename);
Windows uses the identity of the user running the process of the app for this authentication.
You will need to impersonate an alternative user and execute the code that writes that file in that impersonation context. Look into WindowsIdentity.RunImpersonated method
https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.runimpersonated?view=netcore-3.1
you can use this link
You can use a impersonator instead:
using (var impersonator = new Impersonator(username, password))
{
File.Copy(source, destination, true);
}
this is a copy past from our implementation, so please adjust your domain name
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
public class Impersonator : IDisposable
{
/// <summary>
/// The Impersonator class is used to access a network share with other credentials.
/// </summary>
private readonly WindowsImpersonationContext _impersonatedUser;
private readonly IntPtr _userHandle;
/// <summary>
/// Constructor
/// </summary>
/// <param name="username">The user of the network share</param>
/// <param name="password">The password of the network share</param>
public Impersonator(string username, string password, string userDomain = "YOURDOMAIN")
{
_userHandle = new IntPtr(0);
bool returnValue = LogonUser(username, userDomain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
ref _userHandle);
if (!returnValue)
throw new ApplicationException(
"The applications wasn't able to impersonate the user with the specified credentials!");
var newId = new WindowsIdentity(_userHandle);
_impersonatedUser = newId.Impersonate();
}
#region IDisposable Members
public void Dispose()
{
if (_impersonatedUser != null)
{
_impersonatedUser.Undo();
CloseHandle(_userHandle);
}
}
#endregion
#region Interop imports/constants
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_LOGON_SERVICE = 3;
public const int LOGON32_PROVIDER_DEFAULT = 0;
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern bool LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType,
int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
#endregion
}
Ok, so I've been searching for a while and the title explains pretty much what I want to do.
Also, there is no problem hard-coding the admin credentials in the code.
Initially I wrote some code in c# that ALMOST solved the problem:
private void button2_Click(object sender, EventArgs e)
{
DirectoryInfo myDirectoryInfo = new DirectoryInfo(textBox1.Text);
DirectorySecurity myDirectorySecurity = myDirectoryInfo.GetAccessControl();
string User = System.Environment.UserDomainName + "\\" + comboBox1.SelectedItem.ToString();
myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(User, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));
//myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(User, FileSystemRights.Write, InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));
myDirectoryInfo.SetAccessControl(myDirectorySecurity);
MessageBox.Show("Permissions Altered Successfully" + User);
}
This works just fine if I use on a folder that I already have permission, but what I need is a method that uses admin credentials to grant permission to a folder that a regular user don't have.
Later I tried to write some stuff in vbscript:
strHomeFolder = "C:\test"
strUser = " DOMAIN\user"
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "%COMSPEC% /c Echo Y| cacls "& strHomeFolder & " /e /c /g "& strUser &":F", 2, True
But i couldn't find a way to pass the admin credentials.
So lastly I wrote another code to try to get it done:
private void button1_Click(object sender, EventArgs e)
{
try
{
//string passwordPre = "PASSWORD";
//char[] passwordChars = passwordPre.ToCharArray();
//SecureString password = new SecureString();
//foreach (char c in passwordChars)
//{
// password.AppendChar(c);
//}
ProcessStartInfo p = new ProcessStartInfo(#"D:\\test.vbs");
//p.UseShellExecute = false;
//p.UserName = "username";
//p.Domain = "DOMAIN";
//p.Password = password;
Process.Start(p);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This time I just tried to pass admin credentials using a process, but it generated the message: The specified executable is not a valid application for this OS plataform.
So, is there any method that I can use to pass credentials? (Can be in c# or vbscript).
Thanks in advance.
Impersonation will solve your problem. When you execute the code within the impersonated context, logic placed within that context will be executed with the previlege of the impersonated user. Following class reards the impersonation configuration values from the web.config file. You can modify it read from app.config or whatever the source.
Required configurations
User Name
Password
Domain Name
Impersonation Class
public class Impersonator : IDisposable
{
#region Win32 Advanced API calls
/// <summary>
/// Logons the user.
/// </summary>
/// <param name="lpszUserName">Name of the LPSZ user.</param>
/// <param name="lpszDomain">The LPSZ domain.</param>
/// <param name="lpszPassword">The LPSZ password.</param>
/// <param name="dwLogOnType">Type of the dw log on.</param>
/// <param name="dwLogOnProvider">The dw log on provider.</param>
/// <param name="phToken">The ph token.</param>
/// <returns></returns>
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true,
BestFitMapping = false, ThrowOnUnmappableChar = true)]
private static extern int LogonUser(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogOnType,
int dwLogOnProvider,
ref IntPtr phToken);
/// <summary>
/// Duplicates the token.
/// </summary>
/// <param name="hToken">The h token.</param>
/// <param name="impersonationLevel">The impersonation level.</param>
/// <param name="hNewToken">The h new token.</param>
/// <returns></returns>
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true,
BestFitMapping = false, ThrowOnUnmappableChar = true)]
private static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
/// <summary>
/// Reverts to self.
/// </summary>
/// <returns></returns>
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true,
BestFitMapping = false, ThrowOnUnmappableChar = true)]
private static extern bool RevertToSelf();
/// <summary>
/// Closes the handle.
/// </summary>
/// <param name="handle">The handle.</param>
/// <returns></returns>
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true,
BestFitMapping = false, ThrowOnUnmappableChar = true)]
private static extern bool CloseHandle(IntPtr handle);
#endregion
#region Fields
/// <summary>
/// Field to hold the impersonation Context
/// </summary>
WindowsImpersonationContext impersonationContext;
/// <summary>
/// Track whether Dispose has been called.
/// </summary>
private bool disposed;
#region Constants
/// <summary>
/// Logon32 Logon Interactive
/// </summary>
public const int INTERACTIVE_NUMBER = 2;
/// <summary>
/// Logon32 Provider Default
/// </summary>
public const int DEFAULT_NUMBER = 0;
/// <summary>
/// Impersonating user name key
/// </summary>
public const string ImpersonatingUserNameKey = "ImpersonatingUserName";
/// <summary>
/// Impersonating user password key
/// </summary>
public const string ImpersonatingPasswordKey = "ImpersonatingUserPassword";
/// <summary>
/// Impersonating user domain key
/// </summary>
public const string ImpersonatingDomainNameKey = "ImpersonatingDomain";
#endregion
#endregion
#region Construction/Destruction/Initialization
/// <summary>
/// Constructor of the impersonator
/// </summary>
public Impersonator()
{
if (!ImpersonateUser(ConfigurationManager.AppSettings[ImpersonatingUserNameKey],
ConfigurationManager.AppSettings[ImpersonatingDomainNameKey],
ConfigurationManager.AppSettings[ImpersonatingPasswordKey]))
{
//TODO: Log Exception
}
}
#endregion
#region Public Methods
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
/// <summary>
/// Impersonate User with the given user credentials
/// </summary>
/// <param name="userName">User Name</param>
/// <param name="domain">Domain</param>
/// <param name="password">Password</param>
/// <returns>True if success, false otherwise</returns>
private bool ImpersonateUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (RevertToSelf())
{
if (LogonUser(userName, domain, password, INTERACTIVE_NUMBER,
DEFAULT_NUMBER, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
/// <summary>
/// Undo impersonation
/// </summary>
private void StopImpersonation()
{
impersonationContext.Undo();
}
#endregion
#region Protected Methods
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
StopImpersonation();
}
// Note disposing has been done.
disposed = true;
}
}
#endregion
}
How to call the method
Using(Impersonator impersonator = new Impersonator())
{
//Write the folder accessing logic here
}
I am using the code to impersonate a user account to get access to a file share.
public class Impersonator :
IDisposable
{
#region Public methods.
// ------------------------------------------------------------------
/// <summary>
/// Constructor. Starts the impersonation with the given credentials.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
public Impersonator(
string userName,
string domainName,
string password )
{
ImpersonateValidUser( userName, domainName, password );
}
// ------------------------------------------------------------------
#endregion
#region IDisposable member.
// ------------------------------------------------------------------
public void Dispose()
{
UndoImpersonation();
}
// ------------------------------------------------------------------
#endregion
#region P/Invoke.
// ------------------------------------------------------------------
[DllImport("advapi32.dll", SetLastError=true)]
private static extern int LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(
IntPtr handle);
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
// ------------------------------------------------------------------
#endregion
#region Private member.
// ------------------------------------------------------------------
/// <summary>
/// Does the actual impersonation.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
private void ImpersonateValidUser(
string userName,
string domain,
string password )
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
try
{
if ( RevertToSelf() )
{
if ( LogonUser(
userName,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref token ) != 0 )
{
if ( DuplicateToken( token, 2, ref tokenDuplicate ) != 0 )
{
tempWindowsIdentity = new WindowsIdentity( tokenDuplicate );
impersonationContext = tempWindowsIdentity.Impersonate();
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
finally
{
if ( token!= IntPtr.Zero )
{
CloseHandle( token );
}
if ( tokenDuplicate!=IntPtr.Zero )
{
CloseHandle( tokenDuplicate );
}
}
}
/// <summary>
/// Reverts the impersonation.
/// </summary>
private void UndoImpersonation()
{
if ( impersonationContext!=null )
{
impersonationContext.Undo();
}
}
private WindowsImpersonationContext impersonationContext = null;
// ------------------------------------------------------------------
#endregion
}
Then using:
using (new Impersonator("username", "domain", "password"))
{
Process.Start("explorer.exe", #"/root,\\server01-Prod\abc");
}
I get an "Access Denied" error.
This user supposely has access to this share. I can map a drive, use "net use" but this code will not work. Now I am thinking it is the code. Does anyone see anything? Is there a better way of doing this?
try this :
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr phToken);
Usage :
IntPtr userToken = IntPtr.Zero;
bool success = External.LogonUser(
"john.doe",
"domain.com",
"MyPassword",
(int) AdvApi32Utility.LogonType.LOGON32_LOGON_INTERACTIVE, //2
(int) AdvApi32Utility.LogonProvider.LOGON32_PROVIDER_DEFAULT, //0
out userToken);
if (!success)
{
throw new SecurityException("Logon user failed");
}
using (WindowsIdentity.Impersonate(userToken))
{
Process.Start("explorer.exe", #"/root,\\server01-Prod\abc");
}
If I'm understanding correctly, your intention is to run the process in the impersonation context.
The doc from CreateProcess (which is used by Process.Start) says:
If the calling process is impersonating another user, the new process uses the token for the calling process, not the impersonation token. To run the new process in the security context of the user represented by the impersonation token, use the CreateProcessAsUser or CreateProcessWithLogonW function.
So, you're using the wrong API for doing that.
Instead of using your Impersonator class, what happens when you call Process.Start and pass in a ProcessStartInfo instance that contains the username, password and domain that you want to run the process as?
Perhaps, if that works, then your Impersonator class should create a ProcessStartInfo instance and use that to create new processes (encapsulate that within the class itself).
var psi = new ProcessStartInfo("explorer.exe", #"/root,\\server01-Prod\abc");
psi.Domain = domain;
psi.UserName = username;
psi.Password = password;
psi.WorkingDirectory = workingDir;
Process.Start(psi);
Also, per the MSDN docs...
Setting the Domain, UserName, and the Password properties in a
ProcessStartInfo object is the recommended practice for starting a
process with user credentials.
You should also set the working directory when starting a process with different user creds.
How do I use impersonation to run a C# Winforms application with admin privileges?
Can anyone throw some light on this?
Following line of code may help you to achieve your goal. I found this in a "Code Project" article.
check full article : http://www.codeproject.com/KB/dotnet/UserImpersonationInNET.aspx
using System.Security.Principal;
using System.Runtime.InteropServices;
//the following code executed before you perform your task
if ( ! ImpersonationUtil.Impersonate( _userName, _password, _domain ) )
{
MessageBox.Show("Impersonation failed.");
return;
}
//Perform task as this user here...
//After your task, do this:
ImpersonationUtil.UnImpersonate();
Here is the code for the ImpersonationUtil class:
/// <summary>
/// Impersonate a windows logon.
/// </summary>
public class ImpersonationUtil {
/// <summary>
/// Impersonate given logon information.
/// </summary>
/// <param name="logon">Windows logon name.</param>
/// <param name="password">password</param>
/// <param name="domain">domain name</param>
/// <returns></returns>
public static bool Impersonate( string logon, string password, string
domain ) {
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if( LogonUser( logon, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0 ) {
if ( DuplicateToken( token, 2, ref tokenDuplicate ) != 0 ) {
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if ( null != impersonationContext ) return true;
}
}
return false;
}
/// <summary>
/// Unimpersonate.
/// </summary>
public static void UnImpersonate() {
impersonationContext.Undo();
}
[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
public static extern int LogonUser(
string lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken );
[DllImport("advapi32.dll",
CharSet=System.Runtime.InteropServices.CharSet.Aut o,
SetLastError=true)]
public extern static int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken );
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_LOGON_NETWORK_CLEARTEXT = 4;
private const int LOGON32_PROVIDER_DEFAULT = 0;
private static WindowsImpersonationContext impersonationContext;
}
There is a similar question on SO:
How to run c# application with admin creds?
There are some codeproject impersonation resources:
http://www.codeproject.com/KB/cs/cpimpersonation1.aspx
http://www.codeproject.com/KB/cs/zetaimpersonator.aspx
Check out WindowsIdentity class in System.Security.Principal.
There is an Impersonate() method that will do what you are trying to
accomplish. The missing link with this class is that you have to obtain an
access token handle to use it. The only way I know of doing this is by
pinvoking one of the Win32 security functions like LogonUser().
Source:
http://www.developmentnow.com/g/36_2005_4_0_0_511838/Run-with-Administrator-Credentials.htm
You can also set up special XML in application manifest, which will force your application to always run as an administrator.
http://www.enusbaum.com/blog/2007/08/26/how-to-run-your-c-application-as-administrator-in-windows-vista/
If you simply want "Run as admin" you could perhaps use RunElevated?
If I want to instantiate a DirectoryInfo object with an UNC path
DirectoryInfo myDI = new DirectoryInfo (#"\\server\share");
how can I pass a username / password that is required to access that share?
Thanks
In .NET 4 this class works perfectly for me to logon in none windows server via UNC.
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Web.Security;
namespace toolsforimpersonations
{
public class Impersonator
{
#region "Consts"
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
#endregion
#region "External API"
[DllImport("advapi32.dll", SetLastError = true)]
public static extern int LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int CloseHandle(IntPtr hObject);
#endregion
#region "Methods"
//Public Sub PerformImpersonatedTask(ByVal username As String, ByVal domain As String, ByVal password As String, ByVal logonType As Integer, ByVal logonProvider As Integer, ByVal methodToPerform As Action)
public void PerformImpersonatedTask(string username, string domain, string password, int logonType, int logonProvider, Action methodToPerform)
{
IntPtr token = IntPtr.Zero;
if (RevertToSelf()) {
if (LogonUser(username, domain, password, logonType, logonProvider, ref token) != 0) {
dynamic identity = new WindowsIdentity(token);
dynamic impersonationContext = identity.Impersonate();
if (impersonationContext != null) {
methodToPerform.Invoke();
impersonationContext.Undo();
}
// do logging
} else {
}
}
if (token != IntPtr.Zero) {
CloseHandle(token);
}
}
#endregion
}
public class UserImpersonation
{
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_BATCH = 4;
const int LOGON32_LOGON_SERVICE = 5;
const int LOGON32_LOGON_UNLOCK = 7;
const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_PROVIDER_WINNT35 = 1;
const int LOGON32_PROVIDER_WINNT40 = 2;
const int LOGON32_PROVIDER_WINNT50 = 3;
WindowsImpersonationContext impersonationContext;
[DllImport("advapi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int LogonUserA(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int DuplicateToken(IntPtr ExistingTokenHandle, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern long RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern long CloseHandle(IntPtr handle);
public bool impersonateUser(string userName, string domain, string password)
{
return impersonateValidUser(userName, domain, password);
}
public void undoimpersonateUser()
{
undoImpersonation();
}
private bool impersonateValidUser(string userName, string domain, string password)
{
bool functionReturnValue = false;
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
functionReturnValue = false;
//if (RevertToSelf()) {
if (LogonUserA(userName, domain, password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, ref token) != 0) {
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) {
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if ((impersonationContext != null)) {
functionReturnValue = true;
}
}
}
//}
if (!tokenDuplicate.Equals(IntPtr.Zero)) {
CloseHandle(tokenDuplicate);
}
if (!token.Equals(IntPtr.Zero)) {
CloseHandle(token);
}
return functionReturnValue;
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
}
}
And this is how to use from your programm
UserImpersonation impersonator = new UserImpersonation();
impersonator.impersonateUser("username", "", "password"); //No Domain is required
List<FileInfo> OcDialerlfinfo = null;
OcDialerlfinfo = GetFileList("*", "\\\\10.11.11.122\\shared_folder");
impersonator.undoimpersonateUser();
and for the sake of the test you need to use this little function to list all the files in the directory
public static List<FileInfo> GetFileList(string fileSearchPattern, string rootFolderPath)
{
DirectoryInfo rootDir = new DirectoryInfo(rootFolderPath);
List<DirectoryInfo> dirList = new List<DirectoryInfo>(rootDir.GetDirectories("*", SearchOption.AllDirectories));
dirList.Add(rootDir);
List<FileInfo> fileList = new List<FileInfo>();
foreach (DirectoryInfo dir in dirList)
{
fileList.AddRange(dir.GetFiles(fileSearchPattern, SearchOption.TopDirectoryOnly));
}
return fileList;
}
Try this approach:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Principal;
namespace Tools.Network
{
public enum LogonType
{
LOGON32_LOGON_INTERACTIVE = 2,
LOGON32_LOGON_NETWORK = 3,
LOGON32_LOGON_BATCH = 4,
LOGON32_LOGON_SERVICE = 5,
LOGON32_LOGON_UNLOCK = 7,
LOGON32_LOGON_NETWORK_CLEARTEXT = 8, // Win2K or higher
LOGON32_LOGON_NEW_CREDENTIALS = 9 // Win2K or higher
};
public enum LogonProvider
{
LOGON32_PROVIDER_DEFAULT = 0,
LOGON32_PROVIDER_WINNT35 = 1,
LOGON32_PROVIDER_WINNT40 = 2,
LOGON32_PROVIDER_WINNT50 = 3
};
public enum ImpersonationLevel
{
SecurityAnonymous = 0,
SecurityIdentification = 1,
SecurityImpersonation = 2,
SecurityDelegation = 3
}
class Win32NativeMethods
{
[DllImport("advapi32.dll", SetLastError = true)]
public static extern int LogonUser( string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken( IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
}
/// <summary>
/// Allows code to be executed under the security context of a specified user account.
/// </summary>
/// <remarks>
///
/// Implements IDispose, so can be used via a using-directive or method calls;
/// ...
///
/// var imp = new Impersonator( "myUsername", "myDomainname", "myPassword" );
/// imp.UndoImpersonation();
///
/// ...
///
/// var imp = new Impersonator();
/// imp.Impersonate("myUsername", "myDomainname", "myPassword");
/// imp.UndoImpersonation();
///
/// ...
///
/// using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
/// {
/// ...
/// [code that executes under the new context]
/// ...
/// }
///
/// ...
/// </remarks>
public class Impersonator : IDisposable
{
private WindowsImpersonationContext _wic;
/// <summary>
/// Begins impersonation with the given credentials, Logon type and Logon provider.
/// </summary>
///
<param name="userName">Name of the user.</param>
///
<param name="domainName">Name of the domain.</param>
///
<param name="password">The password. <see cref="System.String"/></param>
///
<param name="logonType">Type of the logon.</param>
///
<param name="logonProvider">The logon provider. <see cref="Mit.Sharepoint.WebParts.EventLogQuery.Network.LogonProvider"/></param>
public Impersonator(string userName, string domainName, string password, LogonType logonType, LogonProvider logonProvider)
{
Impersonate(userName, domainName, password, logonType, logonProvider);
}
/// <summary>
/// Begins impersonation with the given credentials.
/// </summary>
///
<param name="userName">Name of the user.</param>
///
<param name="domainName">Name of the domain.</param>
///
<param name="password">The password. <see cref="System.String"/></param>
public Impersonator(string userName, string domainName, string password)
{
Impersonate(userName, domainName, password, LogonType.LOGON32_LOGON_INTERACTIVE, LogonProvider.LOGON32_PROVIDER_DEFAULT);
}
/// <summary>
/// Initializes a new instance of the <see cref="Impersonator"/> class.
/// </summary>
public Impersonator()
{}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
UndoImpersonation();
}
/// <summary>
/// Impersonates the specified user account.
/// </summary>
///
<param name="userName">Name of the user.</param>
///
<param name="domainName">Name of the domain.</param>
///
<param name="password">The password. <see cref="System.String"/></param>
public void Impersonate(string userName, string domainName, string password)
{
Impersonate(userName, domainName, password, LogonType.LOGON32_LOGON_INTERACTIVE, LogonProvider.LOGON32_PROVIDER_DEFAULT);
}
/// <summary>
/// Impersonates the specified user account.
/// </summary>
///
<param name="userName">Name of the user.</param>
///
<param name="domainName">Name of the domain.</param>
///
<param name="password">The password. <see cref="System.String"/></param>
///
<param name="logonType">Type of the logon.</param>
///
<param name="logonProvider">The logon provider. <see cref="Mit.Sharepoint.WebParts.EventLogQuery.Network.LogonProvider"/></param>
public void Impersonate(string userName, string domainName, string password, LogonType logonType, LogonProvider logonProvider)
{
UndoImpersonation();
IntPtr logonToken = IntPtr.Zero;
IntPtr logonTokenDuplicate = IntPtr.Zero;
try
{
// revert to the application pool identity, saving the identity of the current requestor
_wic = WindowsIdentity.Impersonate(IntPtr.Zero);
// do logon & impersonate
if (Win32NativeMethods.LogonUser(userName,
domainName,
password,
(int)logonType,
(int)logonProvider,
ref logonToken) != 0)
{
if (Win32NativeMethods.DuplicateToken(logonToken, (int)ImpersonationLevel.SecurityImpersonation, ref logonTokenDuplicate) != 0)
{
var wi = new WindowsIdentity(logonTokenDuplicate);
wi.Impersonate(); // discard the returned identity context (which is the context of the application pool)
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
finally
{
if (logonToken != IntPtr.Zero)
Win32NativeMethods.CloseHandle(logonToken);
if (logonTokenDuplicate != IntPtr.Zero)
Win32NativeMethods.CloseHandle(logonTokenDuplicate);
}
}
/// <summary>
/// Stops impersonation.
/// </summary>
private void UndoImpersonation()
{
// restore saved requestor identity
if (_wic != null)
_wic.Undo();
_wic = null;
}
}
}