Олицетворение текущего компьютера через WindowsIdentity - PullRequest
2 голосов
/ 22 октября 2009

Я пытаюсь получить WindowsIdentity для учетной записи компьютера, в которой находится текущий пользователь.

В настоящее время я использую следующий код для получения членства в группе текущего пользователя:

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

Это работает нормально, но мне также нужно сделать то же самое для текущей учетной записи компьютера, желательно не запрашивая AD.

Я полагаю, что мне придется сделать это, используя Олицетворение, но не смог выяснить, как.

1 Ответ

1 голос
/ 19 июня 2012

Есть два места на локальном компьютере, которые будут иметь членство в группе учетных записей домена: токен пользователя для домена \ компьютера $ и билет Kerberos для домена \ компьютера $. Всякий раз, когда локальному компьютеру нужен свой токен пользователя, он будет настроен как SYSTEM, а не домен \ компьютер $, так что это не вариант. Единственный способ получить токен пользователя из билета 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;
    }
}
...