Our Products:   CompleteFTP  edtFTPnet/Free  edtFTPnet/PRO  edtFTPj/Free  edtFTPj/PRO
0 votes
2.5k views
in .NET FTP by (51.6k points)
A customer asked:
Is there a way to tell EdtFtpNetPro to use a particular set of credentials to access the network share folder?


You can do this by calling Impersonate() on a WindowsIdentity object. In the next post is a class called WindowsImpersonation. This has a public method called GetWindowsIdentity(), which takes a domain-name, a user-name and a password. Use this method to get a WindowsIdentity object then place the following code around your UploadFile call:

using (WindowsImpersonation.GetWindowsIdentity(domain, username, password))
{
      ftpConnection.UploadFile(localFilePath, remoteFileName);
}


You'll need to import the System.Security.Principal namespaces.

(additional keywords: security, authentication, permission)

- Hans (EnterpriseDT)

1 Answer

0 votes
by (51.6k points)
The code in the following class was adapted from the code in http://msdn2.microsoft.com/en-us/librar ... text(VS.71).aspx.

If you incorporate this code into a DLL, be sure to demand FullTrust.

public class WindowsImpersonation
{
    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public static WindowsIdentity GetWindowsIdentity(string domainName, string userName, string password)
    {
        IntPtr tokenHandle = IntPtr.Zero;
        IntPtr dupeTokenHandle = IntPtr.Zero;
        try
        {
            const int SecurityImpersonation = 2;

            tokenHandle = IntPtr.Zero;
            dupeTokenHandle = IntPtr.Zero;

            if (!LogonUser(userName, domainName, password, (int)LogonSessionType.Interactive, (int)LogonProvider.Default, ref tokenHandle))
                throw new ImpersonationException("Could not log on user {0}\\{1} (LogonUser).  Error was {2}",
                    domainName, userName, GetErrorMessage(Marshal.GetLastWin32Error()));

            if (!DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle))
                throw new ImpersonationException("Could not log on user {0}\\{1} (DuplicateToken).  Error was {2}",
                    domainName, userName, GetErrorMessage(Marshal.GetLastWin32Error()));

            // The token that is passed to the following constructor must 
            // be a primary token in order to use it for impersonation.
            return new WindowsIdentity(dupeTokenHandle);
        }
        catch (Exception ex)
        {
            throw new ImpersonationException(ex, "Error while authenticating user {0}\\{1}", domainName, userName);
        }
        finally
        {
            if (tokenHandle != IntPtr.Zero)
                CloseHandle(tokenHandle);
            if (dupeTokenHandle != IntPtr.Zero)
                CloseHandle(dupeTokenHandle);
        }
    }

    private enum LogonSessionType : uint
    {
        Interactive = 2,
        Network,
        Batch,
        Service,
        Proxy,
        Unlock,
        NetworkCleartext,
        NewCredentials,
        RemoteInteractive,
        CachedInteractive,
        CachedRemoteInteractive,
        CachedUnlock
    }

    private enum LogonProvider : uint
    {
        Default = 0, // default for platform (use this!)
        WinNT35,     // sends smoke signals to authority
        WinNT40,     // uses NTLM
        WinNT50      // negotiates Kerb or NTLM
    }

    [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 = System.Runtime.InteropServices.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)]
    private extern static bool CloseHandle(IntPtr handle);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
        int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);


    // GetErrorMessage formats and returns an error message
    // corresponding to the input errorCode.
    private 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 errorCode = 0x5; //ERROR_ACCESS_DENIED
        //throw new System.ComponentModel.Win32Exception(errorCode);

        int messageSize = 255;
        String lpMsgBuf = "";
        int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;

        IntPtr ptrlpSource = IntPtr.Zero;
        IntPtr prtArguments = IntPtr.Zero;

        int retVal = FormatMessage(dwFlags, ref ptrlpSource, errorCode, 0, ref lpMsgBuf, messageSize, &prtArguments);
        if (0 == retVal)
        {
            throw new Exception("Failed to format message for error code " + errorCode + ". ");
        }

        return lpMsgBuf;
    }
}

public class ImpersonationException : Exception
{
    public ImpersonationException(Exception innerException, string message, params object[] args)
        : base(string.Format(message, args), innerException)
    {
    }

    public ImpersonationException(string message, params object[] args)
        : this(null, message, args)
    {
    }
}

Categories

...