How to Convert a Binary SID to Textual Form

ID: Q131320

3.10 3.50 3.51 4.00 WINDOWS NT kbprg

The information in this article applies to:

SUMMARY

It may be useful to convert a binary SID (security identifier) to a readable, textual form, for display or manipulation purposes.

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 also makes use of 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 API LookupAccountSid fails to obtain domain and user information. Such a failure can occur if the network is down, or the target machine 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 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 an SID, R is the revision level, I is the identifier-authority value, S is subauthority value(s).

An 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 above Sid represents the local Administrators group)

The GetTextualSid function will convert a binary Sid to a textual string.

The resulting string will take one of two forms. If the IdentifierAuthority value is not greater than 2^32, then the SID will be 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 API GetLastError().

Scott Field (sfield)    11-Jul-95
Unicode enabled

Scott Field (sfield)    15-May-95
--*/

#define RTN_OK 0
#define RTN_ERROR 13

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

BOOL GetTextualSid(
    PSID pSid,          // binary Sid
    LPSTR TextualSID,   // buffer for Textual representation of Sid
    LPDWORD dwBufferLen // required/provided TextualSid buffersize
    );

int main(void)
{
    #define MY_BUFSIZE 256 // all allocations should be dynamic
    HANDLE hToken;
    TOKEN_USER ptgUser[MY_BUFSIZE];
    DWORD cbBuffer=MY_BUFSIZE;
    char szTextualSid[MY_BUFSIZE];
    DWORD cbSid=MY_BUFSIZE;
    BOOL bSuccess;

    // 
    // obtain current process token
    // 
    if(!OpenProcessToken(
                GetCurrentProcess(), // target current process
                TOKEN_QUERY,         // TOKEN_QUERY access
                &hToken              // resultant hToken
                ))
    {
        fprintf(stderr, "OpenProcessToken error! (rc=%lu)\n",
            GetLastError() );
        return RTN_ERROR;
    }

    // 
    // obtain user identified by current process' access token
    // 
    bSuccess=GetTokenInformation(
                hToken,    // identifies access token
                TokenUser, // TokenUser info type
                ptgUser,   // retrieved info buffer
                cbBuffer,  // size of buffer passed-in
                &cbBuffer  // required buffer size
                );

    // close token handle.  do this even if error above
    CloseHandle(hToken);

    if(!bSuccess)
    {
        fprintf(stderr, "GetTokenInformation error! (rc=%lu)\n",
            GetLastError() );
        return RTN_ERROR;
    }

    // 
    // obtain the textual representaion of the Sid
    // 
    if(!GetTextualSid(
                ptgUser->User.Sid, // user binary Sid
                szTextualSid,      // buffer for TextualSid
                &cbSid             // size/required buffer
                ))
    {
        fprintf(stderr, "GetTextualSid error! (rc=%lu)\n",
            GetLastError() );
        return RTN_ERROR;
    }

    // display the TextualSid representation
    fprintf(stdout,"%s\n", szTextualSid);

    return RTN_OK;
}

BOOL GetTextualSid(

    PSID pSid,          // binary Sid
    LPTSTR TextualSid,  // buffer for Textual representaion of Sid
    LPDWORD dwBufferLen // required/provided TextualSid buffersize
    )
{
    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(TextualSid, TEXT("S-%lu-"), dwSidRev );

    // 
    // prepare SidIdentifierAuthority
    // 
    if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
    {
        dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
                    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(TextualSid + lstrlen(TextualSid),
                    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(TextualSid + dwSidSize, TEXT("-%lu"),
                    *GetSidSubAuthority(pSid, dwCounter) );
    }

    return TRUE;
}

KBCategory: kbprg KBSubcategory: BseSecurity CodeSam Additional reference words: 3.10 3.50 3.51 4.00 Convert LookupAccountSid SID String

Keywords          : kbAPI kbKernBase CodeSam kbGrpKernBase 
Version           : 3.10 3.50 3.51 4.00
Platform          : NT WINDOWS

Last Reviewed: December 18, 1996