HOWTO: Convert a Binary SID to Textual Form

Q131320


The information in this article applies to:


SUMMARY

This article demonstrates how to convert a binary security identifier (SID) to a readable, textual form, for display or manipulation purposes.


MORE INFORMATION

One example of an application that makes use of SIDs in textual form is the Windows NT Event Viewer. If the Event Viewer cannot look up the name associated with the SID of a logged event, the Event Viewer displays a textual representation of the SID.

Windows NT uses textual SIDs when loading user configuration hives into the HKEY_USERS registry key.

Applications that obtain domain and user names can display the textual SID representation when the Win32 LookupAccountSid function cannot obtain domain and user information, which can occur if the network is down or the target computer is unavailable.

Sample Code

The following sample code displays the textual representation of the SID associated with the current user. This source code converts a SID by using the same algorithm that the Windows NT operating system components use.

/*++

A standardized shorthand notation for SIDs makes it simpler to visualize
their components:

S-R-I-S-S...

In the notation shown above,

S identifies the series of digits as a SID, R is the revision level, I is
the identifier-authority value, S is subauthority value(s).

A SID could be written in this notation as follows: S-1-5-32-544

In this example, the SID has a revision level of 1, an identifier-authority
value of 5, first subauthority value of 32, second subauthority value of
544. (Note that the SID represents the local Administrators group.)

The GetTextualSid function converts a binary SID to a textual string.

The resulting string takes one of two forms. If the IdentifierAuthority
value is not greater than 2^32, then the SID is in the form:

S-1-5-21-2127521184-1604012920-1887927527-19009

  ^ ^ ^^ ^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ ^^^^^
  | | |      |          |          |        |
  +-+-+------+----------+----------+--------+--- Decimal


Otherwise, it will take the form:

S-1-0x206C277C6666-21-2127521184-1604012920-1887927527-19009

  ^ ^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ ^^^^^
  |       |        |      |          |          |        |
  |   Hexadecimal  |      |          |          |        |
  +----------------+------+----------+----------+--------+--- Decimal


If the function succeeds, the return value is TRUE. If the function fails,
the return value is FALSE. To get extended error information, call the
Win32 GetLastError function.

Scott Field (sfield)    11-Jul-95

Unicode enabled

Scott Field (sfield)    15-May-95

--*/ 

#include <windows.h>
#include <stdio.h>


BOOL GetTextualSid(
   PSID     pSid,          // binary Sid
   LPSTR    szTextualSid,  // buffer for Textual Sid
   LPDWORD  dwBufferLen    // required/provided buffer size
);


void main(void) { 

   HANDLE        hToken         = NULL;
   PTOKEN_USER   ptgUser        = NULL;
   DWORD         cbBuffer       = 0;
   LPSTR         szTextualSid   = NULL;
   DWORD         cbSid          = 0;

   __try {

      // Obtain current process token.
      if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY,
            &hToken)) {
         
         fprintf(stderr, "OpenProcessToken() failed.  Error %d\n",
               GetLastError());
         __leave;
      }

      // Obtain user identified by current process's access token.
      if (GetTokenInformation(hToken, TokenUser, NULL, 
            0, &cbBuffer)) {

         // Call should have failed due to zero-length buffer.
         __leave;
   
      } else {

         // Call should have failed due to zero-length buffer.
         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
            __leave;
      }

      // Allocate buffer for token information.
      ptgUser = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
            cbBuffer);
      if (!ptgUser)
         __leave;

      if (!GetTokenInformation(hToken, TokenUser, ptgUser,
            cbBuffer, &cbBuffer)) {

         fprintf(stderr, "GetTokenInformation() failed.  Error %d\n",
               GetLastError());
         __leave;
      }

      cbSid = 128;
      szTextualSid = (LPSTR) HeapAlloc(GetProcessHeap(), 
            HEAP_ZERO_MEMORY, cbSid);

      if (!szTextualSid)
         __leave;

      // Obtain the textual representation of the SID.
      if (!GetTextualSid(
            ptgUser->User.Sid, // user binary Sid
            szTextualSid,      // buffer for TextualSid
            &cbSid)) {       // size/required buffer

         fprintf(stderr, "GetTextualSid() failed.  Error %d\n",
               GetLastError());
         __leave;
      }

      // Display the TextualSid representation.
      fprintf(stdout, "%s\n", szTextualSid);
   
   } __finally {

      // Free resources.
      if (hToken)
         CloseHandle(hToken);

      if (ptgUser)
         HeapFree(GetProcessHeap(), 0, ptgUser);

      if (szTextualSid)
         HeapFree(GetProcessHeap(), 0, szTextualSid);
   }

   return;
}


BOOL GetTextualSid(PSID pSid, LPSTR szTextualSid, 
      LPDWORD dwBufferLen) {

   PSID_IDENTIFIER_AUTHORITY psia;
   DWORD dwSubAuthorities;
   DWORD dwSidRev = SID_REVISION;
   DWORD dwCounter;
   DWORD dwSidSize;

   // Test if SID passed in is valid.
   if(!IsValidSid(pSid)) 
      return FALSE;

   // Obtain SidIdentifierAuthority.
   psia = GetSidIdentifierAuthority(pSid);

   // Obtain sidsubauthority count.
   dwSubAuthorities = *GetSidSubAuthorityCount(pSid);

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

   // Check provided buffer length.
   // If not large enough, indicate proper size and setlasterror
   if (*dwBufferLen < dwSidSize) {

     *dwBufferLen = dwSidSize;
     SetLastError(ERROR_INSUFFICIENT_BUFFER);
     return FALSE;
   }

   // Prepare S-SID_REVISION-.
   dwSidSize = wsprintf(szTextualSid, TEXT("S-%lu-"), dwSidRev);

   // Prepare SidIdentifierAuthority.
   if ((psia->Value[0] != 0) || (psia->Value[1] != 0)) {

      dwSidSize += wsprintf(szTextualSid + lstrlen(szTextualSid),
            TEXT("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 += wsprintf(szTextualSid + lstrlen(szTextualSid),
            TEXT("%lu"),
            (ULONG) (psia->Value[5]      ) +
            (ULONG) (psia->Value[4] <<  8) +
            (ULONG) (psia->Value[3] << 16) +
            (ULONG) (psia->Value[2] << 24));
   }

   // Loop through SidSubAuthorities.
   for (dwCounter = 0; dwCounter < dwSubAuthorities; dwCounter++) {

      dwSidSize += wsprintf(szTextualSid + dwSidSize, TEXT("-%lu"),
            *GetSidSubAuthority(pSid, dwCounter));
   }

   return TRUE;
} 

Additional query words:

Keywords : kbAPI kbKernBase kbDSupport kbGrpDSKernBase
Issue type : kbhowto
Technology : kbAudDeveloper kbWin32sSearch kbWin32API


Last Reviewed: November 22, 2000
© 2001 Microsoft Corporation. All rights reserved. Terms of Use.