How to get the logon SID in C#

后端 未结 4 563
醉梦人生
醉梦人生 2020-11-30 11:42

How does one retrieve the Windows Logon SID in C# .net? (not the user SID, but the unique new one for each session)

相关标签:
4条回答
  • 2020-11-30 11:57

    I know this is an old post. Just ran into this problem as I had to get the ICA session ID and the RDP session ID to have a program collect the correct variables for each type of remote connection. The current session ID is located in Regedit HKEY_CURRENT_USER\Remote*. As I could not find any alternatives to WTS, I am posting my solution here.

        // Prints out ICA or RDP session ID of current user 
    
    using System;
    using Microsoft.Win32;
    
    namespace ViaRegedit
    {
        class Program03
        {
            static void Main(string[] args)
            {
                // Obtain an instance of RegistryKey for the CurrentUser registry 
                RegistryKey rkCurrentUser = Registry.CurrentUser;
                // Obtain the test key (read-only) and display it.
                RegistryKey rkTest = rkCurrentUser.OpenSubKey("Remote");
                foreach (string valueName in rkTest.GetSubKeyNames())
                {
                    //Getting path to RDP/Citrix session ID
                    string RDPICApath = "";
                    if (rkTest.OpenSubKey(valueName) != null && rkTest.OpenSubKey(valueName) != null) { RDPICApath = rkTest.OpenSubKey(valueName).ToString(); }
                    Console.WriteLine("Getting CurrentUser ICA-RDP path from string = " + RDPICApath);
    
                    //Seperating RDPICApath to get session number
                    string RDPICAnumber = RDPICApath.Substring(RDPICApath.LastIndexOf('\\') + 1);
                    Console.WriteLine("Current User RDPICAnumber = " + RDPICAnumber);
                }
                rkTest.Close();
                rkCurrentUser.Close();
                Console.ReadLine();
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-11-30 11:58

    I just spent a long time getting the SID using TOKEN_USER and so forth, then discovered a shortcut in C#. You still need to get the Process Handle (e.g. https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.handle?view=netcore-3.1) and then the token with P/invoke:

    OpenProcessToken(hProcess, TOKEN_READ, out IntPtr hToken))
    

    But once you have the token, you don't need to do any of the nasty GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenUser... stuff you just use:

    var winId = System.Security.Principal.WindowsIdentity(hToken);
    

    ... and BOOM you can get all the info you want (inc SID) for the user out of winId.

    Don't forget to CloseHandle(hToken) and on hProcess afterwards!

    0 讨论(0)
  • 2020-11-30 12:09

    I'm afraid you have to resort to using P/Invoke. There's an example how to do it at pinvoke.net (please see the bottom of the page):

    Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenSessionId , TokenInformation , TokenInfLength , out TokenInfLength );
    

    Please note that I changed the example by altering just one line, I replaced TOKEN_INFORMATION_CLASS.TokenUser with TOKEN_INFORMATION_CLASS.TokenSessionId which is exactly what you need.

    Hope this helps.

    Update: Here's the working (at least on my machine) code:

    using System;
    using System.Runtime.InteropServices;
    using System.Security.Principal;
    
    namespace LinqTest
    {
        public class ClsLookupAccountName
        {
            public const uint SE_GROUP_LOGON_ID = 0xC0000000; // from winnt.h
            public const int TokenGroups = 2; // from TOKEN_INFORMATION_CLASS
    
            enum TOKEN_INFORMATION_CLASS
            {
                TokenUser = 1,
                TokenGroups,
                TokenPrivileges,
                TokenOwner,
                TokenPrimaryGroup,
                TokenDefaultDacl,
                TokenSource,
                TokenType,
                TokenImpersonationLevel,
                TokenStatistics,
                TokenRestrictedSids,
                TokenSessionId,
                TokenGroupsAndPrivileges,
                TokenSessionReference,
                TokenSandBoxInert,
                TokenAuditPolicy,
                TokenOrigin
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct SID_AND_ATTRIBUTES
            {
                public IntPtr Sid;
                public uint Attributes;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct TOKEN_GROUPS
            {
                public int GroupCount;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
                public SID_AND_ATTRIBUTES[] Groups;
            };
    
            // Using IntPtr for pSID instead of Byte[]
            [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
            static extern bool ConvertSidToStringSid(IntPtr pSID, out IntPtr ptrSid);
    
            [DllImport("kernel32.dll")]
            static extern IntPtr LocalFree(IntPtr hMem);
    
            [DllImport("advapi32.dll", SetLastError = true)]
            static extern bool GetTokenInformation(
                IntPtr TokenHandle,
                TOKEN_INFORMATION_CLASS TokenInformationClass,
                IntPtr TokenInformation,
                int TokenInformationLength,
                out int ReturnLength);
    
            public static string GetLogonId()
            {
                int TokenInfLength = 0;
                // first call gets lenght of TokenInformation
                bool Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero, TokenInfLength, out TokenInfLength);
                IntPtr TokenInformation = Marshal.AllocHGlobal(TokenInfLength);
                Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenGroups, TokenInformation, TokenInfLength, out TokenInfLength);
    
                if (!Result)
                {
                    Marshal.FreeHGlobal(TokenInformation);
                    return string.Empty;
                }
    
                string retVal = string.Empty;
                TOKEN_GROUPS groups = (TOKEN_GROUPS)Marshal.PtrToStructure(TokenInformation, typeof(TOKEN_GROUPS));
                int sidAndAttrSize = Marshal.SizeOf(new SID_AND_ATTRIBUTES());
                for (int i = 0; i < groups.GroupCount; i++)
                {
                    SID_AND_ATTRIBUTES sidAndAttributes = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(
                        new IntPtr(TokenInformation.ToInt64() + i * sidAndAttrSize + IntPtr.Size), typeof(SID_AND_ATTRIBUTES));
                    if ((sidAndAttributes.Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
                    {
                        IntPtr pstr = IntPtr.Zero;
                        ConvertSidToStringSid(sidAndAttributes.Sid, out pstr);
                        retVal = Marshal.PtrToStringAuto(pstr);
                        LocalFree(pstr);
                        break;
                    }
                }
    
                Marshal.FreeHGlobal(TokenInformation);
                return retVal;
            }
        }
    }
    

    N.B. I tested it on my x64 machine, so please pay close attention on TokenInformation.ToInt64() piece of code, maybe you should replace it with TokenInformation.ToInt32()

    0 讨论(0)
  • 2020-11-30 12:20

    System.Security.Principal.WindowsIdentity.GetCurrent().User.AccountDomainSid - might do the trick?

    0 讨论(0)
提交回复
热议问题