【问题标题】:Impersonating the current computer through WindowsIdentity通过 WindowsIdentity 模拟当前计算机
【发布时间】:2010-12-08 23:35:26
【问题描述】:

我正在尝试获取当前用户登录的计算机帐户的 WindowsIdentity。

目前我正在使用以下代码来获取当前用户的组成员身份:

WindowsIdentity currentIdent = WindowsIdentity.GetCurrent();
foreach (IdentityReference indentity in currentGroups)
{
  String groupName = indentity.Translate(typeof(NTAccount)).ToString();
}

这很好用,但我还需要对当前计算机帐户执行相同操作,最好不要查询 AD。

我相信我必须使用 Impersonation 来执行此操作,但不知道如何操作。

【问题讨论】:

  • “计算机帐户”是什么意思?
  • 计算机域对象及其组成员身份

标签: .net security impersonation


【解决方案1】:

本地计算机上有两个地方会拥有其域帐户组成员身份:域\computer$ 的用户令牌和域\computer$ 的 Kerberos 票证。每当本地计算机需要其用户令牌时,它将被设置为 SYSTEM,而不是 domain\computer$,所以这不是一个选项。从域\计算机$ Kerberos 票证获取用户令牌的唯一方法是以 SYSTEM 身份运行,因为您需要它的密钥来解密票证(此外,您需要作为操作系统特权的一部分,甚至那么我不知道如何从票证中创建令牌)。

所以,你要查询AD:

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System.ComponentModel;
using System.DirectoryServices;

public static SecurityIdentifier[] GetLocalComputerGroups()
{
    string sAMAccountName = PInvoke.GetSYSTEMsAMAccountName();
    DirectorySearcher searcher = new DirectorySearcher("(sAMAccountName=" + sAMAccountName + ")");
    DirectoryEntry entry = searcher.FindOne().GetDirectoryEntry();
    entry.RefreshCache(new string[] { "tokenGroups" });
    List<SecurityIdentifier> groupSids = new List<SecurityIdentifier>();
    foreach(byte[] byteSid in entry.Properties["tokenGroups"])
    {
        groupSids.Add(new SecurityIdentifier(byteSid, 0));
    }
    return groupSids.ToArray();
}

public class PInvoke
{
    public const int STATUS_SUCCESS = 0;
    public static readonly IntPtr NULL = IntPtr.Zero;

    public enum SECURITY_LOGON_TYPE
    {
        UndefinedLogonType = 0,
        Interactive = 2,
        Network,
        Batch,
        Service,
        Proxy,
        Unlock,
        NetworkCleartext,
        NewCredentials,
        RemoteInteractive,
        CachedInteractive,
        CachedRemoteInteractive,
        CachedUnlock
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LARGE_INTEGER
    {
        public uint LowPart;
        public int HighPart;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID
    {
        public uint LowPart;
        public int HighPart;

        public static LUID GetSYSTEMLuid()
        {
            return new LUID() { LowPart = 0x3E7, HighPart = 0 };
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LSA_UNICODE_STRING
    {
        public ushort Length;
        public ushort MaximumLength;
        public IntPtr Buffer;

        public override string ToString()
        {
            if (Buffer == NULL) return null;
            return Marshal.PtrToStringUni(Buffer, Length / UnicodeEncoding.CharSize);
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_LOGON_SESSION_DATA
    {
        public uint Size;
        public LUID LogonId;
        public LSA_UNICODE_STRING UserName;
        public LSA_UNICODE_STRING LogonDomain;
        public LSA_UNICODE_STRING AuthenticationPackage;
        public SECURITY_LOGON_TYPE LogonType;
        public uint Session;
        public IntPtr Sid;
        public LARGE_INTEGER LogonTime;
        public LSA_UNICODE_STRING LogonServer;
        public LSA_UNICODE_STRING DnsDomainName;
        public LSA_UNICODE_STRING Upn;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_LOGON_SESSION_Managed
    {
        public LUID LogonId;
        public string UserName;
        public string LogonDomain;
        public string AuthenticationPackage;
        public SECURITY_LOGON_TYPE LogonType;
        public uint Session;
        public SecurityIdentifier Sid;
        public LARGE_INTEGER LogonTime;
        public string LogonServer;
        public string DnsDomainName;
        public string Upn;

        public SECURITY_LOGON_SESSION_DATA_Managed(IntPtr pSecurityLogonSessionData)
        {
            SECURITY_LOGON_SESSION_DATA data = (SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure(pSecurityLogonSessionData, typeof(SECURITY_LOGON_SESSION_DATA));
            this.LogonId = data.LogonId;
            this.UserName = data.UserName.ToString();
            this.LogonDomain = data.LogonDomain.ToString();
            this.AuthenticationPackage = data.AuthenticationPackage.ToString();
            this.LogonType = data.LogonType;
            this.Session = data.Session;
            this.Sid = new SecurityIdentifier(ConvertPSIDToString(data.Sid));
            this.LogonTime = data.LogonTime;
            this.LogonServer = data.LogonServer.ToString();
            this.DnsDomainName = data.DnsDomainName.ToString();
            this.Upn = data.Upn.ToString();
        }
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr LocalFree(IntPtr hMem);

    [DllImport("advapi32.dll", SetLastError = true)]
    protected static extern bool ConvertSidToStringSidW(IntPtr Sid, out IntPtr StringSid);

    public static string ConvertPSIDToString(IntPtr pSid)
    {
        IntPtr pString;
        if (ConvertSidToStringSidW(pSid, out pString))
        {
            try
            {
                return Marshal.PtrToStringUni(pString);
            }
            finally
            {
                LocalFree(pString);
            }
        }
        else
        {
            throw new Win32Exception();
        }
    }

    [DllImport("advapi32.dll")]
    protected static extern int LsaNtStatusToWinError(uint Status);

    public static Win32Exception NtStatusToWinException(uint ntstatus)
    {
        return new Win32Exception(LsaNtStatusToWinError(ntstatus);
    }

    [DllImport("secur32.dll")]
    public static extern uint LsaFreeReturnBuffer(IntPtr Buffer);

    [DllImport("secur32.dll")]
    protected static extern uint LsaGetLogonSessionData(ref LUID LogonId, out IntPtr ppLogonSessionData);

    public static SECURITY_LOGON_SESSION_DATA_Managed GetLogonSessionData(LUID logonId)
    {
        IntPtr pLogonSessionData;
        uint ntstatus = LsaGetLogonSessionData(ref logonId, out pLogonSessionData);
        if(ntstatus != STATUS_SUCCESS)
        {
            throw NtStatusToWinException(ntstatus);
        }

        try
        {
            return new SECURITY_LOGON_SESSION_DATA_Managed(pLogonSessionData);
        }
        finally
        {
            LsaFreeReturnBuffer(pLogonSessionData);
        }
    }

    public static string GetSYSTEMsAMAccountName()
    {
        LUID systemLuid = LUID.GetSYSTEMLuid();
        SECURITY_LOGON_SESSION_DATA_Managed systemData = GetLogonSessionData(systemLuid);
        return systemData.UserName;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多