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






4.29/5 (4投票s)
2001年12月18日
1分钟阅读

92101

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; }