模拟和目录条目

Posted

技术标签:

【中文标题】模拟和目录条目【英文标题】:Impersonation and DirectoryEntry 【发布时间】:2012-02-15 23:47:06 【问题描述】:

我成功模拟了一个用户帐户,但我无法使用模拟帐户绑定到 AD 并下拉 DirectoryEntry

以下代码输出:

冒充之前我是:DOMAIN\user 冒充后我是:DOMAIN\admin 错误:C:\Users\user\ADSI_Impersonation\bin\Debug\ADSI_Impersonation.exe samaccountname:

我的问题似乎类似于:

How to use the System.DirectoryServices namespace in ASP.NET

我正在获得一个主令牌。我了解我需要使用委托来在远程计算机上使用模拟令牌。我确认该帐户没有选中“帐户敏感且无法委派”标志。我还确认本地组策略和域组策略不会阻止委派:

计算机配置\Windows 设置\安全设置\本地策略\用户权限分配\

我错过了什么?

谢谢!

using System;
using System.DirectoryServices;
using System.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;

namespace ADSI_Impersonation

    class Program
    
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);

        static void Main(string[] args)
        
            const int LOGON32_PROVIDER_DEFAULT = 0;
            const int LOGON32_LOGON_INTERACTIVE = 2;

            string userName = "admin@domain.com";
            string password = "password";

            Console.WriteLine("Before impersonation I am: " + WindowsIdentity.GetCurrent().Name);

            SafeTokenHandle safeTokenHandle;

            try
            
                bool returnValue = LogonUser(userName, null, password,
                    LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                    out safeTokenHandle);

                if (returnValue)
                
                    WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
                    WindowsImpersonationContext impersonatedUser = newId.Impersonate();
                
                else
                
                    Console.WriteLine("Unable to create impersonatedUser.");
                    return;
                
            
            catch (Exception e)
            
                Console.WriteLine("Authentication error.\r\n" + e.Message);
            

            Console.WriteLine("After impersonation I am: " + WindowsIdentity.GetCurrent().Name);

            string OU = "LDAP://dc=domain,dc=com";
            DirectoryEntry entry = new DirectoryEntry(OU);
            entry.AuthenticationType = AuthenticationTypes.Secure;

            DirectorySearcher mySearcher = new DirectorySearcher();
            mySearcher.SearchRoot = entry;
            mySearcher.SearchScope = System.DirectoryServices.SearchScope.Subtree;
            mySearcher.PropertiesToLoad.Add("cn");
            mySearcher.PropertiesToLoad.Add("samaccountname");

            string cn = "fistname mi. lastname";
            string samaccountname = "";

            try
            
                // Create the LDAP query and send the request
                mySearcher.Filter = "(cn=" + cn + ")";

                SearchResultCollection searchresultcollection = mySearcher.FindAll();

                DirectoryEntry ADentry = searchresultcollection[0].GetDirectoryEntry();

                Console.WriteLine("samaccountname: " + ADentry.Properties["samaccountname"].Value.ToString());
            
            catch (Exception e)
            
                Console.WriteLine("Error: " + e.Message);
            

            Console.WriteLine("samaccountname: " + samaccountname);
            Console.ReadLine();
        
    

    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    
        private SafeTokenHandle()
            : base(true)
        
        

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        
            return CloseHandle(handle);
        
    

【问题讨论】:

【参考方案1】:

许多 .NET API 没有考虑您的手动模拟,例如您注意到的 LDAP 查询。因此,您需要改用 DirectoryEntry 的重载构造函数,

http://msdn.microsoft.com/en-us/library/bw8k1as4.aspx

http://msdn.microsoft.com/en-us/library/wh2h7eed.aspx

【讨论】:

感谢您确认这是唯一的方法。我想因为我将拥有用户的用户名/密码,所以没有理由不起作用。 @Lex Li 我问了一个相关的问题,请您检查一下:***.com/questions/18842970/…【参考方案2】:

错误(0x80004005):未指定的错误

我在连接到远程 Windows 时遇到了一些问题,错误是 Error (0x80004005): Unspecified error。我解决如下:

//Define path
//This path uses the full path of user authentication
String path = string.Format("WinNT://0/1,user", server_address, username);
DirectoryEntry deBase = null;
try

    //Try to connect with secure connection
    deBase = new DirectoryEntry(path, username, _passwd, AuthenticationTypes.Secure);

    //Connection test
    //After test define the deBase with the parent of user (root container)
    object nativeObject = deBase.NativeObject;
    deBase = deBase.Parent;


catch (Exception ex)

    //If an error occurred try without Secure Connection
    try
    
        deBase = new DirectoryEntry(path, username, _passwd);

        //Connection test
        //After test define the deBase with the parent of user (root container)
        object nativeObject = deBase.NativeObject;
        deBase = deBase.Parent;
        nativeObject = deBase.NativeObject;

    
    catch (Exception ex2)
    
        //If an error occurred throw the error
        throw ex2;
    

希望对您有所帮助。 小赫尔维奥 www.helviojunior.com.br

【讨论】:

以上是关于模拟和目录条目的主要内容,如果未能解决你的问题,请参考以下文章

删除特定 RawContact 内容目录条目

Numpy基础

OpenLDAP管理命令详解

gsutil 可以创建加速 gcsfuse 所需的伪目录条目吗?

检测 PATH 中是不是有特定的目录条目

如何获取 Google Drive 中目录的条目列表?