Выдавать себя за пользователя через VPN в настольном приложении - PullRequest
8 голосов
/ 04 июня 2019

У меня проблемы с попыткой выдать себя за пользователя активного каталога в настольном приложении.Каждый раз, когда я использую LogOn API, результат ложен.

Пользователь и домен существуют, так как я также могу аутентифицировать пользователя через DirectoryServices.AccountManagement в том же приложении.

Прочитайте документацию о подражании на сайте Microsoft и даже некоторые посты здесь, в стеке.Кроме того, использовали библиотеку SimpleImpersonation с такими же результатами.

public class Demo
{
    private WindowsImpersonationContext impersonationContext = null;

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

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);
    private void Enter()
    {
        try
        {
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;
            string userName = "myValidUser";
            string domain = "my.domain.example";
            string password = "myValidPassword";

            if (LogonUser(userName, domain, password, (int)LogonType.LOGON32_LOGON_INTERACTIVE, (int)LogonProvider.LOGON32_PROVIDER_WINNT35, ref token) != 0)
            {
                WindowsIdentity WindowsIdentityPrincipal = new WindowsIdentity(token);
                if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                {
                    WindowsIdentity tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                    impersonationContext = tempWindowsIdentity.Impersonate();
                }
                else
                {
                    throw new Win32Exception(new Win32Exception(Marshal.GetLastWin32Error()).Message);
                }
            }
            else
            {
                //throws username or pass incorrect
                throw new Win32Exception(new Win32Exception(Marshal.GetLastWin32Error()).Message);
            }
        }
        catch (Exception exc)
        {
            throw exc;
        }
    }

    public enum LogonProvider
    {
        LOGON32_PROVIDER_DEFAULT = 0,
        LOGON32_PROVIDER_WINNT35 = 1,
        LOGON32_PROVIDER_WINNT40 = 2,
        LOGON32_PROVIDER_WINNT50 = 3
    }

    private enum LogonType
    {
        LOGON32_LOGON_INTERACTIVE = 2,
        LOGON32_LOGON_NETWORK = 3,
        LOGON32_LOGON_BATCH = 4,
        LOGON32_LOGON_SERVICE = 5,
        LOGON32_LOGON_UNLOCK = 7,
        LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
        LOGON32_LOGON_NEW_CREDENTIALS = 9,
    }
}

Я не знаю, причина ли это в том, что мой компьютер работает во внешней сети и подключается / аутентифицируетсяк сети компании через VPN.

Редактировать 1. В результате получается код ошибки 1326 (неизвестное имя пользователя или неверный пароль)

Редактировать 2. Метод пытается получитьтокен для последующего использования при олицетворении потока.

Ответы [ 2 ]

0 голосов
/ 12 июня 2019

Вы не можете использовать LogonUser для входа на удаленный компьютер.Вам необходимо использовать WNetAddConnection2 API-функцию.Пожалуйста, обратитесь к документации MSDN.

для LogonUser: https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-logonuserw

для WNetAddConnection2: https://docs.microsoft.com/en-us/windows/desktop/api/winnetwk/nf-winnetwk-wnetaddconnection2w

здесьэто класс, который я написал:

public class RemoteNetworkConnector : IDisposable
{
    readonly string _networkName;

    public RemoteNetworkConnector(string networkName, NetworkCredential credentials)
    {
        _networkName = networkName;

        NetResource netResource = new NetResource
        {
            Scope = ResourceScope.GlobalNetwork,
            ResourceType = ResourceType.Disk,
            DisplayType = ResourceDisplaytype.Share,
            RemoteName = networkName
        };

        var userName = string.IsNullOrEmpty(credentials.Domain)
            ? credentials.UserName
            : string.Format(@"{0}\{1}", credentials.Domain, credentials.UserName);

        var connectionResult = WNetAddConnection2(
            netResource,
            credentials.Password,
            userName,
            0);

        if (connectionResult != 0)
        {
            throw new Win32Exception(connectionResult, "Error connecting to remote share");
        }
    }

    ~RemoteNetworkConnector()
    {
        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
    }
}

Надеюсь, это поможет.

0 голосов
/ 12 июня 2019

Возможно, вы захотите проверить документацию для функции LogonUser .

Если ваше имя пользователя имеет формат user@domain.example, вам необходимо ввести:

  • lpszUserName = "user@domain.example"
  • lpszDomain = null

Если ваше имя пользователя в формате domain\user, вам необходимо ввести:

  • lpszUserName = "user"
  • lpszDomain = "domain"

Неправильное обращение с полным именем пользователя приведет ккод ошибки, который вы видите.

...