On Wed, 3 Oct 2007 11:35:49 +0200, "Willy Denoyette [MVP]"
<(E-Mail Removed)> wrote:
>"Usenet User" <(E-Mail Removed)> wrote in message
>news
(E-Mail Removed)...
>> From a .NET 1.1 app: need to access a file share on a remote server by
>> its UNC path, i.e., \\server\folder\subfolder\, using specific
>> username and password.
>>
>> The problem is that the credentials are local to the remote server.
>> Therefore, impersonating that user when accessing the share is not
>> possible.
>>
>> One solution is to map a network drive using the credentials, but it
>> seems kind of ugly and old school.
>>
>> Is there any other way?
>>
>> Thanks!
>
>
>Create a new logon session by calling LogonUser (advapi32.dll) using the
>remote credentials (user, password and machinename)with logon type =
>LOGON32_LOGON_NEW_CREDENTIALS (int value=9). Create a new WindowsIdentity
>using the token returned from LogonUser and impersonate that new identity
>when you need to access the remote resource. The new impersonated token is
>used to access the remote share only , all local resources are still using
>the current users token.
>Please read the SDK doc's remarks on LogonUser's dwLogonType, this option
>requires.
>
>Willy.
>
It worked! Below is what I came up with. Note that in my situation
192.19.12.46 is not even a Windows machine, yet an AS/400 server.
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.IO;
namespace RemoteCredentials
{
class MainClass
{
[DllImport( "advapi32.dll", SetLastError = true )]
private static extern bool LogonUser( string
lpszUsername, string lpszDomain, string lpszPassword,
int dwLogonType, int dwLogonProvider, ref
IntPtr phToken );
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private unsafe static extern int FormatMessage(int
dwFlags, ref IntPtr lpSource,
int dwMessageId, int dwLanguageId, ref String
lpBuffer, int nSize, IntPtr *arguments);
[DllImport( "kernel32.dll", CharSet = CharSet.Auto,
SetLastError = true )]
private static extern bool CloseHandle( IntPtr handle
);
[DllImport("advapi32.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public extern static bool DuplicateToken( IntPtr
existingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr
duplicateTokenHandle );
// logon types
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
// logon providers
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_PROVIDER_WINNT50 = 3;
const int LOGON32_PROVIDER_WINNT40 = 2;
const int LOGON32_PROVIDER_WINNT35 = 1;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
IntPtr token = IntPtr.Zero;
IntPtr dupToken = IntPtr.Zero;
bool isSuccess = LogonUser( "userId",
"192.19.12.46", "password",
LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT, ref token );
if( !isSuccess )
{
RaiseLastError();
}
isSuccess = DuplicateToken( token, 2, ref
dupToken );
if( !isSuccess )
{
RaiseLastError();
}
WindowsIdentity newIdentity = new
WindowsIdentity( dupToken );
WindowsImpersonationContext impersonatedUser =
newIdentity.Impersonate();
DirectoryInfo dirInfo = new DirectoryInfo(
@"\\192.19.12.46\sharedfolder" );
FileInfo[] files = dirInfo.GetFiles();
impersonatedUser.Undo();
foreach( FileInfo file in files )
{
Console.WriteLine( file.FullName );
}
isSuccess = CloseHandle( token );
if( !isSuccess )
{
RaiseLastError();
}
}
// GetErrorMessage formats and returns an error
message
// corresponding to the input errorCode.
public unsafe static string GetErrorMessage( int
errorCode )
{
int FORMAT_MESSAGE_ALLOCATE_BUFFER =
0x00000100;
int FORMAT_MESSAGE_IGNORE_INSERTS =
0x00000200;
int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
int messageSize = 255;
string lpMsgBuf = "";
int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
IntPtr ptrlpSource = IntPtr.Zero;
IntPtr ptrArguments = IntPtr.Zero;
int retVal = FormatMessage(dwFlags, ref
ptrlpSource, errorCode, 0, ref lpMsgBuf, messageSize, &ptrArguments);
if( retVal == 0 )
{
throw new ApplicationException(
string.Format( "Failed to
format message for error code '{0}'.", errorCode ) );
}
return lpMsgBuf;
}
private static void RaiseLastError()
{
int errorCode = Marshal.GetLastWin32Error();
string errorMessage = GetErrorMessage(
errorCode );
throw new ApplicationException( errorMessage
);
}
}
}