Sto tentando di impersonare un utente del dominio in un servizio Windows con il servizio connesso come account di sistema locale.Impersonare l'utente nel servizio Windows
Finora, sono in grado di farlo funzionare solo registrando il servizio e impostando il processo utilizzando le credenziali dell'utente, come nel seguito.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = CommandDetails.Command;
startInfo.WorkingDirectory = Settings.RoboCopyWorkingDirectory;
startInfo.Arguments = commandLine;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
// Credentials
startInfo.Domain = ImperDomain;
startInfo.UserName = ImperUsername;
startInfo.Password = ImperPasswordSecure;
process = Process.Start(startInfo);
Il mio obiettivo è quello di non avere il registro servizio in un utente di dominio, ma piuttosto come sistema locale dal momento che rappresenta il dominio password viene reimpostato.
Quando uso il sistema locale, vengo Accesso negato
Tutte le idee come come per ottenere questo risultato?
StackTace
Access is denied
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at Ace.WindowsService.ProcessCmd.ProcessCommand.StartProcess(ProcessStartInfo startInfo) in
ho cercato avvolgendo il codice nel codice Rappresenta elencato di seguito senza successo.
Rappresenta Codice
public class Impersonation2 : IDisposable
{
private WindowsImpersonationContext _impersonatedUserContext;
// Declare signatures for Win32 LogonUser and CloseHandle APIs
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool LogonUser(
string principal,
string authority,
string password,
LogonSessionType logonType,
LogonProvider logonProvider,
out IntPtr token);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool RevertToSelf();
// ReSharper disable UnusedMember.Local
enum LogonSessionType : uint
{
Interactive = 2,
Network,
Batch,
Service,
NetworkCleartext = 8,
NewCredentials
}
// ReSharper disable InconsistentNaming
enum LogonProvider : uint
{
Default = 0, // default for platform (use this!)
WinNT35, // sends smoke signals to authority
WinNT40, // uses NTLM
WinNT50 // negotiates Kerb or NTLM
}
// ReSharper restore InconsistentNaming
// ReSharper restore UnusedMember.Local
/// <summary>
/// Class to allow running a segment of code under a given user login context
/// </summary>
/// <param name="user">domain\user</param>
/// <param name="password">user's domain password</param>
public Impersonation2(string domain, string username, string password)
{
var token = ValidateParametersAndGetFirstLoginToken(username, domain, password);
var duplicateToken = IntPtr.Zero;
try
{
if (DuplicateToken(token, 2, ref duplicateToken) == 0)
{
throw new Exception("DuplicateToken call to reset permissions for this token failed");
}
var identityForLoggedOnUser = new WindowsIdentity(duplicateToken);
_impersonatedUserContext = identityForLoggedOnUser.Impersonate();
if (_impersonatedUserContext == null)
{
throw new Exception("WindowsIdentity.Impersonate() failed");
}
}
finally
{
if (token != IntPtr.Zero)
CloseHandle(token);
if (duplicateToken != IntPtr.Zero)
CloseHandle(duplicateToken);
}
}
private static IntPtr ValidateParametersAndGetFirstLoginToken(string domain, string username, string password)
{
if (!RevertToSelf())
{
throw new Exception("RevertToSelf call to remove any prior impersonations failed");
ErrorLogger.LogEvent("RevertToSelf call to remove any prior impersonations failed", System.Diagnostics.EventLogEntryType.Error, "");
}
IntPtr token;
var result = LogonUser(domain, username,
password,
LogonSessionType.Interactive,
LogonProvider.Default,
out token);
if (!result)
{
var errorCode = Marshal.GetLastWin32Error();
ErrorLogger.LogEvent(string.Format("Could not impersonate the elevated user. LogonUser: {2}\\{1} returned error code: {0}.", errorCode, username, domain), System.Diagnostics.EventLogEntryType.Error, "");
throw new Exception("Logon for user " + username + " failed.");
}
return token;
}
public void Dispose()
{
// Stop impersonation and revert to the process identity
if (_impersonatedUserContext != null)
{
_impersonatedUserContext.Undo();
_impersonatedUserContext = null;
}
}
Aggiornamento
Questo funziona bene se io sono solo in esecuzione se sto solo eseguirlo. Ma quando è in esecuzione come servizio, non funzionerà
Update 2
Non ricevo l'accesso negato dalla Process.Start quando cambio la login si rappresenta a LogonSessionType.NewCredentials e rimuovere la crednetials dal processo. Ma ora vedo un errore durante l'esecuzione del comando robocopy. Quando io ho le credenziali sul processo non produce un file di registro dal comando robocopy
errore
2016/07/16 09:19:12 ERROR 5 (0x00000005)
Accessing Source Directory \\[server]\[path]\
Access is denied.
Change
var result = LogonUser(domain, username,
password,
LogonSessionType.NewCredentials,
LogonProvider.Default,
out token);
Update 3
Le funzioni di copia e spostamento funzionano. Ma la creazione di sub process non lo è. Ho giocato con CreateProcessAsUser come suggerito da Hary Johnston.
Stai dicendo che il tuo servizio è in esecuzione come "Sistema locale" e che il tuo servizio sta avviando un altro processo utilizzando l'account di un utente del dominio? – wablab
In tal caso, questa domanda è probabilmente un duplicato di http://stackoverflow.com/questions/559719/windows-impersonation-from-c-sharp – wablab
Quale riga di codice genera l'errore "accesso negato"? –