2009-10-22 88 views
1

我正在嘗試獲取當前用戶登錄到的計算機帳戶的WindowsIdentity。通過WindowsIdentity模擬當前計算機

目前我使用下面的代碼來獲取當前用戶的組成員:

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

這工作得很好,但我也需要做當前計算機帳戶相同的最好沒有查詢AD。

我相信我必須使用模擬來做到這一點,但一直未能找出如何。

+0

你所說的 '計算機帳戶' 是什麼意思? – 2009-10-22 19:01:00

+0

計算機域對象及其組成員身份 – benPearce 2009-10-22 22:15:15

回答

0

本地計算機上有兩個可能具有其域帳戶組成員身份的位置:domain \ computer $的用戶令牌和domain \ computer $的Kerberos票據。每當本地計算機需要它的用戶令牌時,它將被設置爲SYSTEM,而不是domain \ computer $,所以這不是一個選項。從domain \ computer $ Kerberos票證獲取用戶令牌的唯一方法是以SYSTEM身份運行,因爲您需要使用它的密鑰來解密票證(另外,您需要將Act用作操作系統權限的一部分,甚至那麼我不知道如何從票證創建令牌)。

所以,你必須查詢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; 
    } 
}