Hello Members,
I have a situation where I need to copy files from source to destination.
Problem is that the current user has access to the source, but not the
destination, and the account which has access to the destination doesn't have
access to the source.
Is there a way to make the process impersonate the two users simultaneously.
Here is my code: (And Thanks in advance).
// The current user has access to
// source files, but not destination filesWindowsImpersonationContext newUser =
ImpersonateUser("user", "domain",
"password");
// newUser has access to destination files, but not source files
// How to get access to both?
// Is there a way to union impersonations?
And below is the function ImersonateUser
public static WindowsImpersonationContext ImpersonateUser(string sUsername,
string sDomain, string sPassword)
{
// initialize tokens
IntPtr pExistingTokenHandle = new IntPtr(0);
IntPtr pDuplicateTokenHandle = new IntPtr(0);
pExistingTokenHandle = IntPtr.Zero;
pDuplicateTokenHandle = IntPtr.Zero;
// if domain name was blank, assume local machineif (sDomain == "")
sDomain = System.Environment.MachineName;
try
{
string sResult = null;
const int LOGON32_PROVIDER_DEFAULT = 0;
// create tokenconst int LOGON32_LOGON_INTERACTIVE = 2;
//const int SecurityImpersonation = 2;
// get handle to tokenbool bImpersonated = LogonUser(sUsername,
sDomain, sPassword,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref
pExistingTokenHandle);
// did impersonation fail?if (false == bImpersonated)
{
int nErrorCode = Marshal.GetLastWin32Error();
sResult = "LogonUser() failed with error code: " +
nErrorCode + "\r\n";
// show the reason why LogonUser failed
//MyLogger.MyLogger.myWriteLine("Could not
impersonate");
//MessageBox.Show(this, sResult, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
// Get identity before impersonation
sResult += "Before impersonation: " +
WindowsIdentity.GetCurrent().Name + "\r\n";
bool bRetVal = DuplicateToken(pExistingTokenHandle,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref
pDuplicateTokenHandle);
// did DuplicateToken fail?if (false == bRetVal)
{
int nErrorCode = Marshal.GetLastWin32Error();
CloseHandle(pExistingTokenHandle); // close existing handle
sResult += "DuplicateToken() failed with error code:
" + nErrorCode + "\r\n";
// show the reason why DuplicateToken failed
//MyLogger.MyLogger.myWriteLine("Could not
impersonate");
//MessageBox.Show(this, sResult, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);return null;
}
else
{
// create new identity using new primary token
WindowsIdentity newId = new
WindowsIdentity(pDuplicateTokenHandle);
WindowsImpersonationContext impersonatedUser =
newId.Impersonate();
// check the identity after impersonation
sResult += "After impersonation: " +
WindowsIdentity.GetCurrent().Name + "\r\n";
//MyLogger.MyLogger.myWriteLine("Could not impersonate");
//MessageBox.Show(this, sResult, "Success",
MessageBoxButtons.OK, MessageBoxIcon.Information);return impersonatedUser;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
// close handle(s)if (pExistingTokenHandle != IntPtr.Zero)
CloseHandle(pExistingTokenHandle);
if (pDuplicateTokenHandle != IntPtr.Zero)
CloseHandle(pDuplicateTokenHandle);
}
}
|
One option is to read the source file into a memory stream, impersonate using
destination account, create the destination file & copy the stream contents
to the destination. Based on the file size and count, it may take more time to
complete the operation.
|
A line of code can run under only one identity. To copy a file in to a memory
stream:
FileStream fs = new FileStream (@"D:\i1.jpg", FileMode.Open,
FileAccess.Read);
int l = (int)fs.Length;
MemoryStream ms = new MemoryStream (l);
fs.Read (ms.GetBuffer (), 0, l);
fs.Close ();Back from the memory stream to another file (run after
impersonation):
fs = new FileStream (@"D:\i2.jpg", FileMode.Create, FileAccess.Write);
// New file i2.jpg created
ms.Position = 0;
fs.Write (ms.GetBuffer (), 0, l);
fs.Close ();
ms.Close ();
|