Question

I have a server A which hosts an app to write files to it's hard drive. I have 2 other server B and C. B and C can be accessed by UNC shares on A.

I want any files written to hard-drive on A be copied over under similar directory structure to server B and C. I've tried using File.Copy but that gives me a Access Denied everytime. How would I set the security up to get this to work? Or is there a way to impersonate a user?

Thanks

Was it helpful?

Solution

If you're just trying to access a network share that requires credentials, you can do the following:

  1. Call WinAPI LogonUser to get a network credentials token.
  2. Wrap the token in a WindowsIdentity object.
  3. Call Impersonate on the WindowsIdentity.
  4. Access the network resource.
  5. Dispose the WindowsImpersonationContext and WindowsIdentity.
  6. Call WinAPI CloseHandle.

I created a disposable class that implements this behavior.

...

    using (new NetworkImpersonationContext("domain", "username", "password"))
    {
        // access network here
    }

...

public class NetworkImpersonationContext : IDisposable
{
    private readonly WindowsIdentity _identity;
    private readonly WindowsImpersonationContext _impersonationContext;
    private readonly IntPtr _token;
    private bool _disposed;

    public NetworkImpersonationContext(string domain, string userName, string password)
    {
        if (!LogonUser(userName, domain, password, 9, 0, out _token))
            throw new Win32Exception();
        _identity = new WindowsIdentity(_token);
        try
        {
            _impersonationContext = _identity.Impersonate();
        }
        catch
        {
            _identity.Dispose();
            throw;
        }
    }

    #region IDisposable Members

    public void Dispose()
    {
        GC.SuppressFinalize(this);
        Dispose(true);
    }

    #endregion

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        out IntPtr phToken
        );

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool CloseHandle(IntPtr hHandle);

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            return;
        _disposed = true;

        if (disposing)
        {
            _impersonationContext.Dispose();
            _identity.Dispose();
        }

        if (!CloseHandle(_token))
            throw new Win32Exception();
    }

    ~NetworkImpersonationContext()
    {
        Dispose(false);
    }
}

OTHER TIPS

I would not try and tackle this in C#. There are already numerous file-replication products out there, including DFS Replication that's built in for Windows Server 2003 and later.

I wouldn't attempt to program the security to support this. Your best bet is to configure this using Windows (assuming that you're using Windows servers). You'll have to ensure that server B and C have rights assigned to allow server A to write to the UNC shares.

At that point, assuming this is Windows, you could assign rights to the machine name of server B and C, or you could put server B & C into a group, and assign rights to that group on server A.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top