November 28, 2012

C# - Accessing Remote File By Using Impersonation

Sometime we may face “Could not create the file” or “Access denied on 'Some file Name' ” or "Unable to copy file. Access to the path is denied"  error while try to access or modify a file on a remote machine. After reviewing the code you find out, that because the current user does not have access on a remote machine.

Now we want to force your application to do some restricted activity by a user that who not having privileges to do. we call this procedure Impersonation.

In General Impersonation is, A person act like another.

Unprivileged user can access remote machine like privileged one by using privileged users credentials.

We can achieve Impersonation in may ways, I`m taking "WNetCancelConnection2" function from  GAC dll ("mpr.dll").

Note:
mpr.dll is a module containing functions used to handle communication between the Windows operating system and the installed network providers.

Download Here or copy and use below Remote Access Helper class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Net;
 
namespace SomeNamespace.Utility
{
    public class RemoteAccessHelper
    {
        public class NetworkConnection : IDisposable
        {
            string _networkName;
 
            public NetworkConnection(string networkName, NetworkCredential credentials)
            {
                _networkName = networkName;
 
                var netResource = new NetResource()
                {
                    Scope = ResourceScope.GlobalNetwork,
                    ResourceType = ResourceType.Disk,
                    DisplayType = ResourceDisplaytype.Share,
                    RemoteName = networkName
                };
 
                var result = WNetAddConnection2(
                    netResource,
                    credentials.Password,
                    credentials.UserName,
                    0);
 
                if (result != 0)
                {
                    throw new Win32Exception(result, "Error connecting to remote share");
                }
            }
 
            ~NetworkConnection()
            {
                Dispose(false);
            }
 
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
 
            protected virtual void Dispose(bool disposing)
            {
                WNetCancelConnection2(_networkName, 0, true);
            }
 
            [DllImport("mpr.dll")]
            private static extern int WNetAddConnection2(NetResource netResource,
                string password, string username, int flags);
 
            [DllImport("mpr.dll")]
            private static extern int WNetCancelConnection2(string name, int flags,
                bool force);
        }
 
        [StructLayout(LayoutKind.Sequential)]
        public class NetResource
        {
            public ResourceScope Scope;
            public ResourceType ResourceType;
            public ResourceDisplaytype DisplayType;
            public int Usage;
            public string LocalName;
            public string RemoteName;
            public string Comment;
            public string Provider;
        }
 
        public enum ResourceScope : int
        {
            Connected = 1,
            GlobalNetwork,
            Remembered,
            Recent,
            Context
        };
 
        public enum ResourceType : int
        {
            Any = 0,
            Disk = 1,
            Print = 2,
            Reserved = 8,
        }
 
        public enum ResourceDisplaytype : int
        {
            Generic = 0x0,
            Domain = 0x01,
            Server = 0x02,
            Share = 0x03,
            File = 0x04,
            Group = 0x05,
            Network = 0x06,
            Root = 0x07,
            Shareadmin = 0x08,
            Directory = 0x09,
            Tree = 0x0a,
            Ndscontainer = 0x0b
        }
    }
}


Below i`m describing some piece of code to show, how to use RemoteAccessHelper.cs ?

var oNetworkCredential = 
    new System.Net.NetworkCredential()
    {
        Domain = "domainName",
        UserName = "domainName" + "\\" + "admin login name",
        Password = "admin password"
    };
            
using (new RemoteAccessHelper.NetworkConnection(@"\\" + "domainName", oNetworkCredential))
{
    String[] sFolderNames = Directory.GetDirectories( "domainName" + "\\FolderName");
    foreach (String sFolderName in sFolderNames)
    {
        string[] sarrZipFiles = Directory.GetFiles(sFolderName, "*.txt");
        foreach (String sFile in sarrZipFiles)
        {
            // Some unprivileged operations
        }
    }
}

4 comments:

  1. Hello. I am getting code: 53 error, Can You help me to do resolve this please?

    ReplyDelete
  2. You stole this from Stack Overflow

    http://stackoverflow.com/questions/295538/how-to-provide-user-name-and-password-when-connecting-to-a-network-share/1197430#1197430

    Trash

    ReplyDelete

Recommended Post Slide Out For Blogger