|< Windows Access Control Programming 13 | Main | Windows Access Control Programming 15 >| Site Index | Download |


 

 

 

 

 

MODULE L

WINDOWS OS SECURITY

::ACCESS CONTROL::

PART 14 - EXAMPLES

 

 

 

 

 

 

What do we have in this Module?

 

  1. SID conversion: String-to-Binary-to-String program example.

  2. Getting the Logon SID program example.

 

 

 

 

 

 

 

 

 

 

 

 

My Training Period: xx  hours. Before you begin, read some instruction here. This is continuation from Windows Access Control Programming 13.  All the program examples run in the Debug mode, the WinXp machine logged as normal/restricted user Mike, who is a member of Administrators group except whenever mentioned.  Beware the codes that span more than one line.

 

SID conversion: String-to-Binary-to-String

 

The ConvertSidToStringSid() and ConvertStringSidToSid() functions convert a SID to and from string format.  For Windows NT 4.0 and earlier the ConvertSidToStringSid() and ConvertStringSidToSid() are not supported.

 

// Playing with SID format

// For Win Xp

#define _WIN32_WINNT 0x0501

#include <windows.h>

#include <stdio.h>

#include <sddl.h>

#include <aclapi.h>

 

int main()

{

DWORD SidSize, SidSize2;

PSID TheSID = NULL;

LPTSTR pSid = "";

 

SidSize = SECURITY_MAX_SID_SIZE;

 

printf("Create a well known \"WinLocalSystemSid\" SID.\n");

printf("--------------------------------------------\n");

// Allocate enough memory for the largest possible SID.

if(!(TheSID = LocalAlloc(LMEM_FIXED, SidSize)))

{

    printf("Could not allocate memory, error %u.\n", GetLastError());

    // Just exit

    exit(1);

}

else

    printf("Memory allocated successfully.\n");

 

// Create a SID for the Local system on the local computer.

if(!CreateWellKnownSid(

   WinLocalSystemSid,  // Well known Local system SID

   NULL,       // Domain SID, NULL for local computer

   TheSID,   // Pointer to memory for new SID

   &SidSize // Pointer in DWORD the number of byte of TheSid

   ))

{

    printf("CreateWellKnownSid() error %u.\n\n", GetLastError());

}

else

{

    printf("CreateWellKnownSid() for Local system is OK.\n\n", GetLastError());

    printf("Convert the \"WinLocalSystemSid\" SID to string SID.\n");

    printf("--------------------------------------------------\n");

    // Get the string version of the SID (S-R-I-I...)

    if(!(ConvertSidToStringSid(

       TheSID,  // Pointer to the SID structure to be converted

       &pSid))) // Pointer to variable that receives the null-terminated SID string

    {

        printf("ConvertSidToStringSid() error %u\n", GetLastError());

        exit(1);

    }

else

{

printf("ConvertSidToStringSid() is OK.\n");

printf("The SID string for WinLocalSystemSid is: %s\n", pSid);

}

}

 

if(IsValidSid(TheSID))

printf("The SID is valid\n");

else

printf("The SID is not valid!\n");

 

//**********************************************************

// TODO: Then, use the string SID as needed.

// ...

// When done, don't forget to release the memory used.

//**********************************************************

 

if(LocalFree(TheSID) == NULL)

printf("Memory is freed up...\n");

 

//************************************************************

 

LPTSTR StringSid = "S-1-5-18"; // or "SY" - a well known Local System

PSID TheSID2 = NULL;

SidSize2 = SECURITY_MAX_SID_SIZE;

 

// S-R-5-18 and equal to...

// SECURITY_NT_AUTHORITY\\SECURITY_LOCAL_SYSTEM_RID

// But they are stored as in binary format in a SID structure

printf("\nConvert the \"S-1-5-18\" string SID to SID and then reconvert.\n");

printf("------------------------------------------------------------\n");

if(!(TheSID2 = LocalAlloc(LMEM_FIXED, SidSize2)))

{

    printf("Could not allocate memory, error %u.\n", GetLastError());

    exit(1);

}

else

    printf("Memory allocated successfully.\n");

 

//*************************************************

if(!ConvertStringSidToSid(

   StringSid,     // Pointer to a null-terminated string containing the string-format SID to convert

   &TheSID2))  // Pointer to a variable that receives a pointer to the converted SID

{

   printf("ConvertStringSidToSid() for Local system error %u\n", GetLastError());

   exit(1);

}

else

{

   printf("ConvertStringSidToSid() for Local system is OK.\n");

}

 

if(!(ConvertSidToStringSid(

       TheSID2,         // Pointer to the SID structure to be converted

       &StringSid)))   // Pointer to variable that receives the null-terminated SID string

{

    printf("Reconversion-ConvertSidToStringSid() error %u\n", GetLastError());

    exit(1);

}

else

{

     printf("Reconversion-ConvertSidToStringSid() is OK.\n");

     printf("The SID string for WinLocalSystemSid is: %s\n", pSid);

}

 

if(IsWellKnownSid(TheSID2, WinLocalSystemSid))

   printf("The SID is a well known SID.\n");

else

   printf("It is non well known SID, error %u.\n", GetLastError());

 

//**************************************************

if(IsValidSid(TheSID2))

   printf("The SID is valid.\n");

else

   printf("The SID is not valid!, error %u\n", GetLastError());

 

if(LocalFree(TheSID2) == NULL)

   printf("Memory is freed up...\n");

return 0;

}

 

A sample output:

 

Create a well known "WinLocalSystemSid" SID.

--------------------------------------------

Memory allocated successfully.

CreateWellKnownSid() for Local system is OK.

 

Convert the "WinLocalSystemSid" SID to string SID.

--------------------------------------------------

ConvertSidToStringSid() is OK.

The SID string for WinLocalSystemSid is: S-1-5-18

The SID is valid

Memory is freed up...

 

Convert the "S-1-5-18" string SID to SID and then reconvert.

------------------------------------------------------------

Memory allocated successfully.

ConvertStringSidToSid() for Local system is OK.

Reconversion-ConvertSidToStringSid() is OK.

The SID string for WinLocalSystemSid is: S-1-5-18

The SID is a well known SID.

The SID is valid.

Memory is freed up...

Press any key to continue

 

Getting the Logon SID

 

A logon security identifier (SID) identifies the logon session associated with an access token.  A typical use of a logon SID is in an ACE that allows access for the duration of a client's logon session.  For example, a Windows service can use the LogonUser() function to start a new logon session.  The LogonUser() function returns an access token from which the service can extract the logon SID.  The service can then use the SID in an ACE that allows the client's logon session to access the interactive window station and desktop. The following example gets the logon SID from an access token.  It uses the GetTokenInformation() function to fill a TOKEN_GROUPS buffer with an array of the group SIDs from an access token.  This array includes the logon SID, which is identified by the SE_GROUP_LOGON_ID attribute.  The example function allocates a buffer for the logon SID and it is the caller's responsibility to free the buffer.

 

// Getting the Logon SID

// For Win Xp

#define _WIN32_WINNT 0x0501

#include <windows.h>

#include <stdio.h>

#include <sddl.h>

#include <aclapi.h>

 

//************************************************************

void Cleanup(PTOKEN_GROUPS ptgrp)

{

   // Release the buffer for the token groups.

   if(ptgrp != NULL)

      HeapFree(GetProcessHeap(), 0, (LPVOID)ptgrp);

}

//***************************************************************

 

//**************************************************************

// Get the logon SID and convert it to SID string...

BOOL GetLogonSID(HANDLE hToken, PSID ppsid)

{

   BOOL bSuccess = FALSE;

   DWORD dwIndex;

   DWORD dwLength = 0;

   PTOKEN_GROUPS ptgrp = NULL;

   // Again, dummy initialization...

   LPTSTR pSid = "";

   // Verify the parameter passed in is not NULL.

   // Although we just provide an empty buffer...

   if(ppsid == NULL)

   {

       printf("The ppsid pointer is NULL lol!\n");

       Cleanup(ptgrp);

   }

   else

       printf("The ppsid pointer is OK.\n");

   // Get the required buffer size and allocate the TOKEN_GROUPS buffer.

   if(!GetTokenInformation(

         hToken,               // handle to the access token

         TokenGroups,    // get information about the token's groups

         (LPVOID) ptgrp, // pointer to TOKEN_GROUPS buffer

         0,                         // size of buffer

         &dwLength        // receives required buffer size

      ))

   {

    if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)

       Cleanup(ptgrp);

    else

       ptgrp = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);

    if(ptgrp == NULL)

       Cleanup(ptgrp);

    else

       printf("Buffer for TOKEN_GROUPS is OK.\n");

   }

   else

       printf("GetTokenInformation()-Getting all the buffer and their size is OK\n");

   // Get the token group information from the access token.

   if(!GetTokenInformation(

         hToken,         // handle to the access token

         TokenGroups,    // get information about the token's groups

         (LPVOID) ptgrp, // pointer to TOKEN_GROUPS buffer

         dwLength,       // size of buffer

         &dwLength       // receives required buffer size

         ))

   { Cleanup(ptgrp); }

   else

         printf("GetTokenInformation()-Getting the group info is OK\n");

   // Loop through the groups to find the logon SID.

   for(dwIndex = 0; dwIndex < ptgrp->GroupCount; dwIndex++)

      if((ptgrp->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) ==  SE_GROUP_LOGON_ID)

      {

         // If the logon SID is found then make a copy of it.

         dwLength = GetLengthSid(ptgrp->Groups[dwIndex].Sid);

         // Allocate a storage

         ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);

        // and verify again...

         if(ppsid == NULL)

             Cleanup(ptgrp);

         else

             printf("The ppsid pointer is OK.\n");

        // If Copying the SID fails...

         if(!CopySid(dwLength,

                      ppsid,    // Destination

                      ptgrp->Groups[dwIndex].Sid))  // Source

         {

             HeapFree(GetProcessHeap(), 0, (LPVOID)ppsid);

             Cleanup(ptgrp);

         }

         else

             printf("CopySid() is OK lol!\n");

   //*******************************************************

   // Convert the logon sid to SID string format

   if(!(ConvertSidToStringSid(

       ppsid,  // Pointer to the SID structure to be converted

       &pSid))) // Pointer to variable that receives the null-terminated SID string

    {

        printf("ConvertSidToStringSid() error %u\n", GetLastError());

        Cleanup(ptgrp);

        exit(1);

    }

   else

   {

     printf("ConvertSidToStringSid() is OK.\n");

     printf("The logon SID string is: %s\n", pSid);

    }

}

 

// If everything OK, returns a clean slate...

  bSuccess = TRUE;

  return bSuccess;

}

// The following function release the buffer allocated by the GetLogonSID() function.

BOOL FreeLogonSID(PSID ppsid)

 

{

    HeapFree(GetProcessHeap(), 0, (LPVOID)ppsid);

       return TRUE;

}

 

int main()

{

   // Handle to token

   HANDLE hToken;

   // Just a dummy initial size of SID to avoid a NULL pointer

   BYTE sidBuffer[256];

   PSID ppsid = (PSID)&sidBuffer;

    // Open a handle to the access token for the calling process that is the currently login access token

    if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))

    {

       printf("OpenProcessToken()-Getting the handle to access token failed: %u\n", GetLastError());

    }

    else

       printf("OpenProcessToken()-Getting the handle to access token is OK\n");

// Call the GetLogonSID()

if(GetLogonSID(hToken, ppsid))

    printf("GetLogonSID() is OK. Error if any: %u\n\n", GetLastError());

else

    printf("GetLogonSID() is not OK, error %u\n\n", GetLastError());

// Release the allocation for ppsid

if(FreeLogonSID(ppsid))

    printf("The ppsid has been freed...\n");

// Close the handle lol

if(CloseHandle(hToken))

    printf("The handle to the process is closed.\n");

return 0;

}

 

A sample output:

OpenProcessToken()-Getting the handle to access token is OK

The ppsid pointer is OK.

Buffer for TOKEN_GROUPS is OK.

GetTokenInformation()-Getting the group info is OK

The ppsid pointer is OK.

CopySid() is OK lol!

ConvertSidToStringSid() is OK.

The logon SID string is: S-1-5-5-0-55363

GetLogonSID() is OK. Error if any: 0

 

The ppsid has been freed...

The handle to the process is closed.

Press any key to continue

The SID string is S-1-5-5-0-55363 is a logon session SID for the machine that used to run the program example.  This is used for process in a given logon session, gaining access to the window-station objects for that session.  The constant format is S-1-5-5-X-Y (SECURITY_LOGON_IDS_RID).  The X and Y values for these SIDs are different for each logon session.  The value of the SECURITY_LOGON_IDS_RID_COUNT is the number of RIDs in this identifier (5-X-Y).

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

 

  1. For Multibytes, Unicode characters and Localization please refer to Locale, wide characters & Unicode (Story) and Windows users & groups programming tutorials (Implementation).

  2. Structure, enum, union and typedef story can be found C/C++ struct, enum, union & typedef.

  3. Notation used in MSDN is Hungarian Notation instead of CamelCase and is discussed Windows programming notations.

  4. Windows data type information is in Windows data types used in Win32 programming.

  5. Check the best selling C, C++ and Windows books at Amazon.com.

  6. Microsoft Visual C++, online MSDN.

  7. MSDN library.

 

 

 

 

 

 

|< Windows Access Control Programming 13 | Main | Windows Access Control Programming 15 >| Site Index | Download |