65.9K
CodeProject 正在变化。 阅读更多。
Home

在 SID 之间进行字符串和二进制转换

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.29/5 (4投票s)

2001年12月18日

1分钟阅读

viewsIcon

92101

downloadIcon

745

如何将 SID 在字符串和二进制表示之间进行转换。

引言

任何使用过 Windows NT 高级安全功能的人可能都遇到过 SID。SID 是安全标识符的缩写。SID 是一种可变长度的结构,用于唯一标识 Windows NT 上的用户或组。SID 通常以字符串形式查看,例如 'S-1-5-21-1431262831-1455604309-1834353910-1000'。但是,所有使用 SID 的 Win32 API 都使用二进制表示形式。因此,程序员可能需要在使用 SID 的字符串和二进制表示形式之间进行转换。

从 Windows 2000 开始,微软添加了两个用于转换 SID 的 API。它们是 ConvertStringSidToSid()ConvertSidToStringSid()。这些 API 的缺点是它们需要 Platform SDK(用于文件 SDDL.H),并且它们不能在 Windows NT 上工作。如果您对这些限制感到满意,那么我鼓励您使用微软的 API。但是,如果您需要在 Windows NT 中转换 SID,那么您需要编写自己的函数。意识到 Windows NT 中没有内置的 SID 转换方法,微软发布了两个知识库文章 Q198907 和 Q131320。这些文章提供了两个处理转换的函数。我采用了这两个函数,修复了一些小错误,并清理了代码,从而得到了以下函数。需要注意的是,没有 SID 转换函数可以在 Win95/98/ME 上工作。只有基于 NT 的操作系统使用 SID,因此只有这些系统包含使用 SID 的 Win32 API。

//***********************************************
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;
}
© . All rights reserved.