Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / October 2007

Tip: Looking for answers? Try searching our database.

Accessing UNC file share with credentials?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Usenet User - 03 Oct 2007 01:33 GMT
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!
Willy Denoyette [MVP] - 03 Oct 2007 10:35 GMT
> 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
[quoted text clipped - 10 lines]
>
> 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.
Usenet User - 03 Oct 2007 17:57 GMT
>> 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
[quoted text clipped - 22 lines]
>
>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?
Usenet User - 03 Oct 2007 18:07 GMT
>>> 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
[quoted text clipped - 27 lines]
>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!
Usenet User - 03 Oct 2007 20:55 GMT
>> 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
[quoted text clipped - 22 lines]
>
>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
);
        }
    }
}
Willy Denoyette [MVP] - 03 Oct 2007 21:58 GMT
>>> 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
[quoted text clipped - 161 lines]
> }
> }

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

Willy.
Ben Voigt [C++ MVP] - 03 Oct 2007 23:58 GMT
> WindowsIdentity newIdentity = new
> WindowsIdentity( dupToken );
[quoted text clipped - 6 lines]
>
> 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();
}
Larry Smith - 03 Oct 2007 18:22 GMT
> 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
[quoted text clipped - 8 lines]
>
> 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.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.