PC Review


Reply
Thread Tools Rate Thread

Accessing UNC file share with credentials?

 
 
Usenet User
Guest
Posts: n/a
 
      3rd Oct 2007
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!
 
Reply With Quote
 
 
 
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      3rd Oct 2007
"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.


 
Reply With Quote
 
Usenet User
Guest
Posts: n/a
 
      3rd Oct 2007
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.
>


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?
 
Reply With Quote
 
Usenet User
Guest
Posts: n/a
 
      3rd Oct 2007
On Wed, 03 Oct 2007 09:57:28 -0700, Usenet User <(E-Mail Removed)> wrote:

>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.
>>

>
>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!
 
Reply With Quote
 
Larry Smith
Guest
Posts: n/a
 
      3rd Oct 2007
> 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.


 
Reply With Quote
 
Usenet User
Guest
Posts: n/a
 
      3rd Oct 2007
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
);
}
}
}
 
Reply With Quote
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      3rd Oct 2007
"Usenet User" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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
> );
> }
> }
> }




Right, note that you don't have to call DuplicateToken, the token obtained
from LogonUser can be used to impersonate as is.

Willy.

 
Reply With Quote
 
Ben Voigt [C++ MVP]
Guest
Posts: n/a
 
      3rd Oct 2007
> 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();
}


 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Accessing File Servers with other credentials djm0001 Windows XP Accessibility 0 15th Aug 2008 04:20 PM
Accessing UNC file share with credentials? Usenet User Microsoft Dot NET Framework 7 3rd Oct 2007 11:58 PM
Accessing UNC file share with credentials? Usenet User Microsoft Dot NET 7 3rd Oct 2007 11:58 PM
Accessing a Share Using Windows Credentials =?Utf-8?B?Q2FybA==?= Microsoft VB .NET 3 17th Mar 2006 06:19 PM
How can I use a file share and pass credentials? kevin Microsoft Dot NET Framework 2 9th Feb 2004 06:21 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 07:48 PM.