Converting SIDs Between Strings and Binary

Environment: VC5, VC6

Introduction

Anyone who has ever used advanced security in Windows NT has probably run across SIDs before. SID is an acronym for Security IDentifier. A SID is a structure of variable length that uniquely identifies a user or group on Windows NT. SIDs are often viewed in string form, for example 'S-1-5-21-1431262831-1455604309-1834353910-1000'. However all the Win32 API that work with SIDs use the binary representation. As such the programmer may need to convert between string and binary representations of SIDs.

Starting in Windows 2000 Microsoft added two APIs for converting SIDs. They are ConvertStringSidToSid() and ConvertSidToStringSid(). The down-side to these APIs is they require the Platform SDK (for the file SDDL.H) and they don't work on Windows NT. If you are content with these restrictions, then I encourage you to use the Microsoft APIs. But if you need to convert SIDs in Windows NT then you'll need to write your own functions. Realizing there was no built-in way to convert SIDs in Windows NT, Microsoft released two Knowledgebase articles Q198907 and Q131320. These articles provide two functions to handle the conversion. I started with these two functions, fixed a few minor bugs, and cleaned up the code to result in the following functions. It should be noted that no SID conversion functions work on Win95/98/ME. Only NT-based operating systems use SIDs and therefore only those systems contain the Win32 APIs that use SIDs.

//***********************************************
PSID GetBinarySid(LPCTSTR szSid)
{
     // This function is based off the KB article Q198907.
     // This function is the same as ConvertStringSidToSid(),
     // except that function is only on Windows 2000 and newer.
     // The calling function must free the returned SID with FreeSid.

     _ASSERTE(szSid);
     _ASSERTE(lstrlen(szSid));

     PSID pSid = NULL;
     LPTSTR szSidCopy = NULL;

     try
     {
       int i;
       LPTSTR ptr, ptr1;
       SID_IDENTIFIER_AUTHORITY sia; ZeroMemory(&sia, sizeof(sia));
       BYTE nByteAuthorityCount = 0;
       DWORD dwSubAuthority[8] = {0, 0, 0, 0, 0, 0, 0, 0};

       szSidCopy = new TCHAR[lstrlen(szSid) + 1];
       lstrcpy(szSidCopy, szSid);

       // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL

       // Skip 'S'
       if(!(ptr = _tcschr(szSidCopy, _T('-'))))
          return NULL;

       // Skip '-'
       ptr++;

       // Skip SID_REVISION
       if(!(ptr = _tcschr(ptr, _T('-'))))
            return NULL;

       // Skip '-'
       ptr++;

       // Skip IdentifierAuthority
       if(!(ptr1 = _tcschr(ptr, _T('-'))))
            return NULL;
       *ptr1= 0;

       if((*ptr == _T('0')) && (*(ptr + 1) == _T('x')))
       {
         _stscanf(ptr, _T("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
              &sia.Value[0],
              &sia.Value[1],
              &sia.Value[2],
              &sia.Value[3],
              &sia.Value[4],
              &sia.Value[5]);
       }
       else
       {
         DWORD dwValue;
         _stscanf(ptr, _T("%lu"), &dwValue);

         sia.Value[5] = (BYTE)(dwValue & 0x000000FF);
         sia.Value[4] = (BYTE)(dwValue & 0x0000FF00) >> 8;
         sia.Value[3] = (BYTE)(dwValue & 0x00FF0000) >> 16;
         sia.Value[2] = (BYTE)(dwValue & 0xFF000000) >> 24;
       }

       // Skip '-'
       *ptr1 = '-';
       ptr = ptr1;
       ptr1++;

       for(i = 0; i < 8; i++)
       {
         // Get subauthority
         if(!(ptr = _tcschr(ptr, _T('-'))))
            break;
         *ptr = 0;
         ptr++;
         nByteAuthorityCount++;
       }

       for(i = 0; i < nByteAuthorityCount; i++)
       {
         // Get subauthority
         _stscanf(ptr1, _T("%lu"), &dwSubAuthority[i]);
         ptr1 += lstrlen(ptr1) + 1;
       }
       delete[] szSidCopy;
       szSidCopy = NULL;

       if(!AllocateAndInitializeSid(&sia,
            nByteAuthorityCount,
            dwSubAuthority[0],
            dwSubAuthority[1],
            dwSubAuthority[2],
            dwSubAuthority[3],
            dwSubAuthority[4],
            dwSubAuthority[5],
            dwSubAuthority[6],
            dwSubAuthority[7],
            &pSid))
       {
         pSid = NULL;
       }
     }
     catch(...)
     {
          delete[] szSidCopy;
          pSid = NULL;
     }

     return pSid;
}

//***********************************************
bool GetTextualSid(const PSID pSid, LPTSTR szSid, DWORD &dwBufferSize)
{
  // This function is based off the KB article Q131320.
  // This function is the same as ConvertSidToStringSid(),
  // except that function is only on Windows 2000 and newer.

  _ASSERTE(pSid);
  _ASSERTE(szSid);

  bool bRtnVal = true;

  try
  {
    PSID_IDENTIFIER_AUTHORITY psia;
    DWORD dwSidSize, dwSubAuthorities;

    // Validate the binary SID
    if(!IsValidSid(pSid))
      return false;

    // Get the identifier authority value from the SID
    psia = GetSidIdentifierAuthority(pSid);

    // Get the number of subauthorities in the SID.
    dwSubAuthorities = *GetSidSubAuthorityCount(pSid);

    // Compute the buffer length
    // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
    dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);

    // Was the provided buffer large enough?
    if(dwBufferSize < dwSidSize)
    {
      dwBufferSize = dwSidSize;
      SetLastError(ERROR_INSUFFICIENT_BUFFER);
      return false;
    }

    // Add 'S' prefix and revision number to the string
    dwSidSize = _stprintf(szSid, _T("S-%lu-"), SID_REVISION);

    // Add SID identifier authority to the string.
    if((psia->Value[0] != 0) || (psia->Value[1] != 0))
    {
      dwSidSize += _stprintf(szSid + lstrlen(szSid),
           _T("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
           (USHORT)psia->Value[0],
           (USHORT)psia->Value[1],
           (USHORT)psia->Value[2],
           (USHORT)psia->Value[3],
           (USHORT)psia->Value[4],
           (USHORT)psia->Value[5]);
    }
    else
    {
      dwSidSize += _stprintf(szSid + lstrlen(szSid),
           _T("%lu"),
           (ULONG)(psia->Value[5]) +
           (ULONG)(psia->Value[4] << 8) +
           (ULONG)(psia->Value[3] << 16) +
           (ULONG)(psia->Value[2] << 24) );
    }

    // Add SID subauthorities to the string
    for(DWORD dwCounter = 0; dwCounter < dwSubAuthorities; dwCounter++)
    {
      dwSidSize += _stprintf(szSid + dwSidSize, _T("-%lu"),
           *GetSidSubAuthority(pSid, dwCounter));
    }
  }
  catch(...)
  {
    bRtnVal = false;
  }

  return bRtnVal;
}
Download source - 2 Kb


Comments

  • Goal

    Posted by snareenactina on 11/12/2012 11:15pm

    New research supports the notion that instituting temporary short-selling bans during stock market downturns doesn’t do any good. frans Excellent menu and Whitehouse has shown great taste. It is simple as the religion of Islam stands for. Well done. Obama. hopwahopwa payer allegorical servsdarrell enslave

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • A modern mobile IT strategy is no longer an option, it is an absolute business necessity. Today's most productive employees are not tied to a desk, an office, or a location. They are mobile. And your company's IT strategy has to be ready to support them with easy, reliable, 24/7 access to the business information they need, from anywhere in the world, across a broad range of communication devices. Here's how some of the nation's most progressive corporations are meeting the many needs of their mobile workers …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds