Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get machine SID (including primary domain controller)

Tags:

c#

windows

sid

I need to get machine SID (not computer account's SID) in C#. Computer is specified be host name, it is't necessarily local computer and it can be domain computer or workgroup computer. I using this helper class to call LookupAccountName API function:

    private static class Helper
    {
        internal enum SID_NAME_USE
        {
            SidTypeUser = 1,
            SidTypeGroup,
            SidTypeDomain,
            SidTypeAlias,
            SidTypeWellKnownGroup,
            SidTypeDeletedAccount,
            SidTypeInvalid,
            SidTypeUnknown,
            SidTypeComputer
        }

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool LookupAccountName(
            string systemName,
            string accountName,
            byte[] sid,
            ref int sidLen,
            System.Text.StringBuilder domainName,
            ref int domainNameLen,
            out SID_NAME_USE peUse);

        public static SecurityIdentifier LookupAccountName(
            string systemName,
            string accountName,
            out string strDomainName,
            out SID_NAME_USE accountType)
        {
            const int ERROR_INSUFFICIENT_BUFFER = 122;

            int lSidSize = 0;
            int lDomainNameSize = 0;

            //First get the required buffer sizes for SID and domain name.
            LookupAccountName(systemName,
                              accountName,
                              null,
                              ref lSidSize,
                              null,
                              ref lDomainNameSize,
                              out accountType);

            if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
            {
                //Allocate the buffers with actual sizes that are required
                //for SID and domain name.
                byte[] sid = new byte[lSidSize];
                var sbDomainName = new System.Text.StringBuilder(lDomainNameSize);

                if (LookupAccountName(systemName,
                                      accountName,
                                      sid,
                                      ref lSidSize,
                                      sbDomainName,
                                      ref lDomainNameSize,
                                      out accountType))
                {
                    strDomainName = sbDomainName.ToString();
                    return new SecurityIdentifier(sid, 0);
                }
            }

            throw new Win32Exception();
        }
    }

and using it like this:

Helper.SID_NAME_USE accountType;
string refDomain;
SecurityIdentifier sid = Helper.LookupAccountName("falcon.mydomain.local", "falcon", out refDomain, out accountType);  //Domain computer

SecurityIdentifier sid = Helper.LookupAccountName("rat", "rat", out refDomain, out accountType);  //Workgroup computer

My only problem is, that this is not working if computer is primary domain controller (i need to obtain domain SID in that case).

like image 412
Tomáš Holan Avatar asked Feb 12 '10 19:02

Tomáš Holan


1 Answers

It appears that for most computers you do the following:

LookupAccountName("", "ComputerName", ...); ConvertSidToStringSid(...)

But for domain controllers you have to add a dollar sign to the computer name parameter, and then delete the last segment in the returned SID.

like image 164
John Smith Avatar answered Oct 29 '22 09:10

John Smith