Accessing UNC file share with credentials?
Accessing UNC file share with credentials?
am 03.10.2007 02:33:00 von Usenet User
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!
Re: Accessing UNC file share with credentials?
am 03.10.2007 11:35:49 von willy.denoyette
"Usenet User" wrote in message
news:oao5g35stu0k962247kplddo1s8e4k1v87@4ax.com...
> 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.
Re: Accessing UNC file share with credentials?
am 03.10.2007 18:57:28 von Usenet User
On Wed, 3 Oct 2007 11:35:49 +0200, "Willy Denoyette [MVP]"
wrote:
>"Usenet User" wrote in message
>news:oao5g35stu0k962247kplddo1s8e4k1v87@4ax.com...
>> 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.
>
Thank you for the info. BTW, I need to move the files from the remote
location to a local one, i.e., by using File.Move(...). This method,
obviously, would access both remote and local resources
simultaneously. How can it be done, then?
Re: Accessing UNC file share with credentials?
am 03.10.2007 19:07:03 von Usenet User
On Wed, 03 Oct 2007 09:57:28 -0700, Usenet User wrote:
>On Wed, 3 Oct 2007 11:35:49 +0200, "Willy Denoyette [MVP]"
> wrote:
>
>>"Usenet User" wrote in message
>>news:oao5g35stu0k962247kplddo1s8e4k1v87@4ax.com...
>>> 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.
>>
>
>Thank you for the info. BTW, I need to move the files from the remote
>location to a local one, i.e., by using File.Move(...). This method,
>obviously, would access both remote and local resources
>simultaneously. How can it be done, then?
Never mind. I misunderstood you at first, by I got the idea after
reading the remarks in the documentaion.
Thanks a lot!
Re: Accessing UNC file share with credentials?
am 03.10.2007 19:22:08 von Larry Smith
> 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?
I'm not sure what .NET offers natively but you can always rely on
"NetUseAdd()" in the WinAPI. This is how you would normally handle it
outside of .NET. Just change the credentials to that of the remote account
and you can then access the machine normally. Note that the domain name you
pass should be something that the remote server doesn't recognize however
(an empty string probably though I haven't done this in some years). This
ensures that authentication will occur using the remote machine's local
account which will happen anyway if the remote machine isn't part of a
domain at all.
Re: Accessing UNC file share with credentials?
am 03.10.2007 21:55:20 von Usenet User
On Wed, 3 Oct 2007 11:35:49 +0200, "Willy Denoyette [MVP]"
wrote:
>"Usenet User" wrote in message
>news:oao5g35stu0k962247kplddo1s8e4k1v87@4ax.com...
>> 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;
///
/// The main entry point for the application.
///
[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
);
}
}
}
Re: Accessing UNC file share with credentials?
am 03.10.2007 22:58:54 von willy.denoyette
"Usenet User" wrote in message
news:4gs7g3hd87fjek43g08nuc8l4r64ot2g23@4ax.com...
> On Wed, 3 Oct 2007 11:35:49 +0200, "Willy Denoyette [MVP]"
> wrote:
>
>>"Usenet User" wrote in message
>>news:oao5g35stu0k962247kplddo1s8e4k1v87@4ax.com...
>>> 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;
>
> ///
> /// The main entry point for the application.
> ///
> [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
> );
> }
> }
> }
Right, note that you don't have to call DuplicateToken, the token obtained
from LogonUser can be used to impersonate as is.
Willy.
Re: Accessing UNC file share with credentials?
am 04.10.2007 00:58:38 von rbv
> WindowsIdentity newIdentity = new
> WindowsIdentity( dupToken );
> WindowsImpersonationContext impersonatedUser =
> newIdentity.Impersonate();
>
> DirectoryInfo dirInfo = new DirectoryInfo(
> @"\\192.19.12.46\sharedfolder" );
> FileInfo[] files = dirInfo.GetFiles();
>
> impersonatedUser.Undo();
Very serious vulnerability here, the impersonation is not undone in case an
exception is thrown.
WindowsImpersonationContext implements IDisposable, so try:
WindowsIdentity newIdentity = new WindowsIdentity( dupToken );
using (newIdentity.Impersonate())
{
DirectoryInfo dirInfo = new
DirectoryInfo(@"\\192.19.12.46\sharedfolder" );
FileInfo[] files = dirInfo.GetFiles();
}