文章編號: 276208 - 上次校閱: 2007年3月29日 - 版次: 3.3

如何將轉換的一個 SID SDDL 形式為 SAM 帳戶名稱

系統提示本文適用於您使用的作業系統之外的作業系統。與您不相關的文章內容已停用。

在此頁中

全部展開 | 全部摺疊

結論

本文章顯示如何安全性描述元定義語言 (SDDL) 形式的安全性識別元 (SID) 可以轉換成安全性帳戶管理員 (SAM) 帳戶名稱的表單。

比方說假設您想要顯示 SAM 帳戶名稱 (網域 \ 名稱) 的存取控制清單 (ACL) 中列出 trustees 位於遠端工作站上,其中包含 ACL 中的本機帳戶在物件上。您可以使用 ADsSecurity.dll 列舉上遠端工作站上的物件 ACL。信任項值找到使用者的 ACL 中或在本機工作站 SAM 中的群組會出現在 SDDL 格式 (類似於 s-x-x-x-x),不在 SAM 帳戶名稱格式。您必須從 SDDL 表單轉換的 SAM 帳戶名稱格式顯示這些 trustees。在 Windows 2000/XP/2003年使用 ConvertStringSidToSid API 將 [Sid 轉換成字串。此知識庫文件中定義的方法被為了在 Windows NT 4.0 上使用。

其他相關資訊

信任項的 SID 儲存在二進位表單上,將 ACL。 無法人們可讀取二進位的 SID。

[IADsAccessControlEntry 介面可以讓目錄用戶端存取及操作物件的個別存取控制項目 (ACE)。IADsAccessControlEntry 會嘗試使用 LookupAccountSID 函數將信任項的二進位的 SID 轉換成更人們可讀取的表單。

LookupAccountSID 可以從遠端執行。在這種情況下它是本機系統上執行。LookupAccountSID API 會搜尋所有受信任的網域及信任項的 SID 為傳回網域和 userID。不過,在這種情況下信任項會儲存在不受信任遠端工作站 SAM。LookupAccountSID API 都無法解決二進位的 SID。API 失敗時, 信任項是轉換成 SDDL 表單,且置於 IADsAccessControlEntry::Trustee 屬性。

這個處理程序將 SID SDDL 形式轉換成二進位檔可以再用於 LookupAccountSid API 的呼叫來傳回 SAM 帳戶名稱表單的 SID 是,如下所示:
  1. 如此可決定發行單位和局部授權相對識別碼 (RID) IADsAccessControlEntry::Trustee] 屬性中找到的 SID SDDL 形式的剖析。
  2. 初始化 subauthorities 適當數目與二進位的 SID。
  3. 在適當的順序中加入適當 subauthorities 建置二進位的 SID。
  4. 使用新建立的 LookupAccountSid 呼叫,以本機電腦為目標的 SID 已取得 SDDL SID 的二進位檔。

範例程式碼

本章節包含 Microsoft Visual Basic 和 Microsoft Visual C++ 原始程式碼,將 SDDL SID 轉換成 SAM 帳戶名稱。

Visual Basic 程式碼

' This code is meant to be used as an example of how one could convert
' the SDDL form of a SID into the SAM Account Name form.
' The class module defines two functions,
' ConvertSDDLtoSam which takes an SDDL form of a SID along with a target server
' and returns the Domain\user (SAM Account Name ) form of the SID.
'
' GetSubAuthorityFromSDDL, a helper function that walks the sub authorities.
'
Option Explicit

Private SidCount As Integer
Private Osid As New ADsSID
Const LMEM_ZEROINIT = &H40
'
' Declare the APIs needed to manipulate the binary SID
'
Private Declare Function InitializeSid Lib "advapi32.dll" (ByVal Sid As Long, pIndentifierAuthority As Any, ByVal nSubAuthorityCount As Byte) As Long
Private Declare Function GetSidSubAuthority Lib "advapi32.dll" (ByVal Sid As Long, ByVal nSubAuthority As Long) As Long
Private Declare Function GetSidLengthRequired Lib "advapi32.dll" (ByVal nSubAuthorityCount As Byte) As Long
Private Declare Function LookupAccountSid Lib "advapi32.dll" Alias "LookupAccountSidA" _
    (ByVal lpSystemName As String, Sid As Any, ByVal name As String, cbName As Long, _
    ByVal ReferencedDomainName As String, cbReferencedDomainName As Long, peUse As Integer) As Long
'
' Declare the memory management functions.
' Notice there are two definitions for RtlMoveMemory, 
' one takes a value as  Any, the other takes a value ByVal as long
' this is necessary so memory can be copied as follows:
'  From a variable containing a 32 bit value that represents a memory location
'  From a variable that represents a VB allocated memory location
'  (ie: Dim bByte(6) as Byte type of declaration).
'
' LocalAlloc and LocalFree are used to allocate and free memory from the heap,
'respectively.
'
Private Declare Sub CopyByValMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, ByVal Source As Long, ByVal Length As Long)
Private Declare Sub CopyByRefMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, Source As Any, ByVal Length As Long)
Private Declare Function LocalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal wBytes As Long) As Long
Private Declare Function LocalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function ConvertStringSidToSid Lib "advapi32.dll" Alias "ConvertStringSidToSidA" (ByVal StringSid As String, ByRef pSID As Long) As Boolean

'
' ConvertSDDLtoSAM, see above comments for a description.
'
Public Function ConvertSDDLtoSAM(strSDDL As String, Target As String) As String
  Dim stInt As Integer, strEnd As Integer
  Dim iEndPosition As Integer, AuthorityCount As Integer
  Dim AuthorityStrings(15) As String
  Dim Authority As String, lngSSubAuthority As Long
  Dim mByte() As Byte, str As String
  Dim lngSid As Long, clssid As Long
  Dim One As Integer, bRelValue As Long
  Dim strUser As String * 255, strDomain As String * 255
  Dim Retval As Integer, Counter As Integer
  Dim lngRid As Long, cbSidLength As Long
  Dim bIdentifier(1 To 6) As Byte
  '
  ' Fill the AuthorityStrings array with the appropriate values.
  ' AuthorityStrings(1) - The SID revision level
  ' AuthroityStrings(2) - The issuing authority
  ' AuthorityStrings(3) - 0th sub authority RID
  ' .
  ' .
  ' .
  ' AuthorityStrings(n) - Nth sub authority RID
  '
  AuthorityCount = 1
  Authority = GetSubAthorityFromSDDL(strSDDL, 1, iEndPosition)
  AuthorityStrings(AuthorityCount) = Authority
  '
  ' Walk the rest of the sub authorities and place them into
  ' the string array
  '
  Do
    Authority = GetSubAthorityFromSDDL(strSDDL, iEndPosition, iEndPosition)
    If (Len(Authority) > 0) Then
      AuthorityCount = AuthorityCount + 1
      AuthorityStrings(AuthorityCount) = Authority
    End If
  Loop While (iEndPosition > 0)
  '
  ' Initialize the security identifier.  AuthorityCount - 2 should be total
  ' number of sub authorities that need to be added to the
  ' the SID.  Use InitializeSid to create a SID using the proper authority (stored
  ' in the second location of AuthorityStrings) and add the appropriate number of sub
  ' authorities.
  '
  ' Retrieve the SubAuthority count
  '
    Retval = CInt(AuthorityStrings(2))
  '
  ' Place that value into the appropriate Identifier array position.
  ' Just by coincidence, the Issuing Authority array and the
  ' issuing authority portion of the SDDL SID are the same number, so
  ' the structure ends up 0,0,0,0,0,CInt(AuthorityStrings(2))
  '
    bIdentifier(6) = Retval
  '
  ' Get a total SubAuthority count
  '
    SidCount = AuthorityCount - 2
  '
  ' Retrieve the overall required size for the sid
  ' We must know how many bytes will be needed to build the binary
  ' sid, GetSidLengthRequired will return that information
  '
    cbSidLength = GetSidLengthRequired(SidCount)
    ReDim mByte(cbSidLength)
  '
  ' Allocate Memory for the binary SID
  '
    clssid = LocalAlloc(LMEM_ZEROINIT, cbSidLength)
  '
  ' Its time to Initialize the SID.
  ' Call InitializeSid to populate sid buffer. InitializeSid
  ' properly initializes the issuing authority and revision sections
  ' of the binary sid
  '
    lngSid = InitializeSid(clssid, bIdentifier(1), SidCount)
  '
  ' Build the binary sid using GetSidSubAuthoriy API.  The API
  ' returns an pointer to the location for the Sub Authority rid.
  ' Sub authority RIDs are stored in location 3 - AuthorityCount
  ' in the AuthorityStrings array.  Simply convert the string form of
  ' the RID into a long and copy the memory into the pointer returned
  ' by GetSidSubAuthority
  '

    For Counter = 3 To AuthorityCount
        lngSSubAuthority = GetSidSubAuthority(clssid, Counter - 3)
		      If val(AuthorityStrings(Counter))<2147483648# Then
             lngRid = CLng(AuthorityStrings(Counter))
								Else
													lngRid = val(AuthorityStrings(Counter)) - 4294967296#
								End If
        CopyByRefMemory lngSSubAuthority, lngRid, LenB(lngRid)
        CopyByValMemory mByte(0), clssid, cbSidLength
    Next Counter
  '
  ' We need to copy the binary SID into a byte buffer so we can pass it to
  ' the LookupAccountSid API.  This API is targeted to a particular server
  ' Copying the memory allows us to view the contents of the binary sid in the
  ' watch window of our VB application.
  '
    ReDim mByte(cbSidLength)
    CopyByValMemory mByte(0), clssid, cbSidLength
  '
  ' Use LookAccountSid to resolve the  Domain\Username of the
  ' SID.
  '
    bRelValue = LookupAccountSid(Target, mByte(0), strUser, Len(strUser), strDomain, Len(strDomain), 1)
  '
  ' Clean up the domain and userID strings.  the return value of LookupAccountSid should be
  ' checked to be sure that the functions completed successfully
  '
    strUser = Left(strUser, InStr(strUser, Chr(0)) - 1)
    strDomain = Left(strDomain, InStr(strDomain, Chr(0)) - 1)
    ConvertSDDLtoSAM = Trim(strDomain) & "\" & Trim(strUser)
  '
  ' Since we allocated memory for the binary SID, we must release it otherwise we
  ' cause a memory leak.  The leak is not severe, but over time could add up.
  '
    LocalFree clssid
End Function
'
' GetSubAuthorityFromSDDL starts at startposition
' and returns the next "-" at the end as endposition.
' When the end of the descriptor is found, endposition = 0.
'
' If for some reason, a starting "-" is not found, then the function will
' return "" as the authority and endposition = 0.
'
Private Function GetSubAthorityFromSDDL(strSDDL As String, _
                                startposition As Integer, _
                                endposition As Integer) As String
  Dim stInt As Integer
  Dim strEnd As Integer
  Dim subAuthStart As Long
  Dim SubAuthEnd As Long
  Dim Authority As String
  
  
  ' Find the base authority
  '
  subAuthStart = InStr(startposition, strSDDL, "-", vbTextCompare)
  If (subAuthStart = 0) Then
    '
    ' Could not locate the leading "-", set the error condition and return
    '
    endposition = 0
    GetSubAthorityFromSDDL = ""
  Else
     '
     ' Found the leading "-", search for the ending "-"
     '
     SubAuthEnd = InStr(subAuthStart + 1, strSDDL, "-", vbTextCompare)
     If (SubAuthEnd = 0) Then
       '
       ' Did not not locate an ending "-", set
       ' the endposition value to 0 and return everything from the
       ' first "-" to the end of the string
       '
       Authority = Mid(strSDDL, subAuthStart + 1)
       endposition = 0
       GetSubAthorityFromSDDL = Authority
     Else
       '
       ' Found the ending "-", set endposition to its location
       ' and return all the characters from the first "-" to this location
       '
       Authority = Mid(strSDDL, (subAuthStart + 1), ((SubAuthEnd - 1) - subAuthStart))
       endposition = SubAuthEnd
       GetSubAthorityFromSDDL = Authority
     End If
  End If
End Function
				

Visual C++ 程式碼

// SDDLsid.cpp : Defines the entry point for the console application.
// 

#include "stdafx.h"
#define MAX_SUB_AUTHORITIES 15
// 
// Helper Function STUBS
// 
// Function to locate sub authorities
// 
UCHAR FindSubAuthorities( char* pSDDL, char *pAuths[] );
// 
// Take the sub authorities array from FindSubAuthories and 
// build a SID; return a pointer to it.
// 
PSID BuildSidFromAuthorities( char *pAuths[], UCHAR lcAuths);
// 
// 
//-----------------------------------------------------------------
// Main console application executable.
// 
int main(int argc, char* argv[])
{
    char *lpszSDDL;
    char *pStr, *pTarget;
    char *pAuthorities[MAX_SUB_AUTHORITIES];
    UCHAR nAuthorities = 0;
    PSID pRawSID;
    PSID pSysSID = NULL;
    DWORD cbSysSID = 0;
    //char szDomain[256];
    //DWORD cbszDomain = 256;
    SID_NAME_USE pSNU; 
    if( argc < 3 ) 
    {
        printf("Error, need a SDDL form of a SID\nExample: SDDLSid S-1-2-3-55569832-2398475 \\\\Target_Server\n");
        return 0;
    }
    lpszSDDL = (char *)malloc(strlen(argv[1])+1);
    pStr = argv[1];
    pTarget = argv[2];
    strcpy( lpszSDDL, (pStr+2));
    // 
    // Find all of the sub authorities in the SDDL SID
    // See comments on FindSubAuthorities for details
    // 
    nAuthorities = FindSubAuthorities( lpszSDDL, pAuthorities );
    long j = 0;
    printf("Sub authority Count: %d\nSub Authority Values:\n", nAuthorities);
    // 
    // Display the sub-Authority values
    // 
    for ( j = 0; j <= nAuthorities; j++ )
        printf("%s\n",pAuthorities[j]);
    // 
    // Build a binary SID from the sub authorities
    // See comments in BuildSidFromAuthorities for details
    // 
    pRawSID = BuildSidFromAuthorities( pAuthorities, nAuthorities );
/*
    Test code block used to verify that the code is functioning properlly.  Took
    a known SID, converted it to SDDL on Win2k, then used that SDDL sid in the code
    for testing purposes.  

    if( !LookupAccountName("LOCAL_SERVER","FordP", pSysSID, &cbSysSID, szDomain, &cbszDomain, &pSNU) )
    {
        DWORD lstErr = GetLastError();
        if( lstErr == 122 ) 
        {
        pSysSID = (PSID)LocalAlloc(LPTR, cbSysSID);
        LookupAccountName("\\\\maxvdc1","FordP", pSysSID, &cbSysSID, szDomain, &cbszDomain, &pSNU);
        if( EqualSid( pSysSID, pRawSID ))
            printf("Sids are =\n");
        else printf("SIDS are <> \n");
        }
    }
    else printf("%d\n",GetLastError());
*/ 
    if( pRawSID )
    {
        // 
        // Have a binary SID, lets retrieve the domain and user ID
        // 

        char UserID[30];
        char DomainID[256];
        DWORD cbUserId = 30;
        DWORD cbDomainId = 256;
        BOOL bRet;
        bRet= LookupAccountSid(
                               "\\\\maxvdc1",        // name of local or remote computer
                               pRawSID,               // security identifier
                               UserID,                // account name buffer
                               &cbUserId,             // size of account name buffer
                               DomainID,              // domain name
                               &cbDomainId,           // size of domain name buffer
                               &pSNU                   // SID type
                               );
        if( bRet ) 
            printf("SAM account form of %s \n is %s\\%s\n", argv[1], DomainID, UserID);
        else
            printf("Could not locate SID %d\n", GetLastError());

    }
    // 
    // Clean up all the memory allocated by the console application
    // 
    if ( pRawSID )  LocalFree( (HLOCAL)pRawSID );
    if ( lpszSDDL ) free ( lpszSDDL );

	return 0;
}
// 
// long FindSubAuthorities( char *pSDDL, char *pAuths[] );
// 
// The return value is the number of sub authorities in the SID.  
// Basically, the routine takes the SDDL form, searches for "-" characters
// and replaces them with NULLs and places a pointer to the start of 
// the authority in the pAuths array so that each authority is separated by
// nulls.
// 
// Example:
// 
// SDDL SID-> S-1-5-21-853885456-2109860151-3743179773-1190
// would be converted to:
//  S\01\05\021\0853885456\02109860151\03743179773\01190
// and the pAuths pointer array would be filled like:
// pAuths[0] -> pointer to '1'
// pAuths[1] -> pointer to '21'
// pAuths[2] -> pointer to '853885456'
// pAuths[3] -> pointer to '2109860151'
// pAuths[4] -> pointer to '3743179773'
// pAuths[5] -> pointer to '1190'
// 
// The return value would be 5
// 
// RETURN VALUES:
// Number of Sub Authorities found in the SDDL string
// 
UCHAR FindSubAuthorities( char *pSDDL, char *pAuths[] )
{
    char *strt;
    BOOL bEnd = FALSE;
    long lSubs = 0;
    pAuths[lSubs] = pSDDL;
    for( strt = pSDDL; *strt; strt++)
    {
       switch( *strt )
       {
       case '-':
           bEnd = TRUE;
           *strt = NULL;
           lSubs++;
           break;
       default:
           if( bEnd )
           {
               pAuths[lSubs] = strt;
               bEnd = FALSE;
           }
           break;
       }
    }
    return (UCHAR)(lSubs - 1);
}
// 
// PSID BuildSidFromAuthorities( char *pAuths[]);
// This function takes an array that has been parsed by 
// FindSubAuthorities function and converts it to a binary sid.
// 
// RETURN VALUES:
// Returns NULL if the SID could not be created.
// Returns a PSID pointer if the SID was created successfully
// 
PSID BuildSidFromAuthorities( char *pAuths[], UCHAR lcAuths)
{
    // 
    // Allocate memory for the SID, this memory must be freed by the caller
    // 
    PSID pLocalSid = (PSID)LocalAlloc(LPTR, GetSidLengthRequired(lcAuths));
    BOOL bRet;
    // 
    // The Authorities array contains pointer to the start of each sub authority.
    // the pAuths[0] is pointing to the revisoin value, so we skip that one.
    // Then pAuths[1] is pointer to the issuing authority for the SID.  This value is going
    // to be one of the values in the following case statement.
    // 
    // Initialize the SID with the issuing authority and the number of sub authorities
    // 
    switch( pAuths[1][0] )
    {
    case '0':
        {
            // 
            // SECURITY_NULL_SID_AUTHORITY
            // 
            SID_IDENTIFIER_AUTHORITY sAuth = SECURITY_NULL_SID_AUTHORITY;
            bRet = InitializeSid( pLocalSid, &sAuth, lcAuths);
        }

        break;

    case '1':
        {
        // 
        // SECURITY_WORLD_SID_AUTHORITY
        // 
        SID_IDENTIFIER_AUTHORITY sAuth = SECURITY_WORLD_SID_AUTHORITY;
        bRet = InitializeSid( pLocalSid, &sAuth, lcAuths);
        }
        break;
    case '2':
        {
        // 
        // SECURITY_LOCAL_SID_AUTHORITY
        // 
        SID_IDENTIFIER_AUTHORITY sAuth = SECURITY_LOCAL_SID_AUTHORITY;
        bRet = InitializeSid( pLocalSid, &sAuth, lcAuths);
        }
        break;
    case '3':
        {
        // 
        // SECURITY_CREATOR_SID_AUTHORITY
        // 
        SID_IDENTIFIER_AUTHORITY sAuth = SECURITY_CREATOR_SID_AUTHORITY;
        bRet = InitializeSid( pLocalSid, &sAuth, lcAuths);
        }
        break;
    case'5':
        {
        // 
        // SECURITY_NT_AUTHORITY
        // 
        SID_IDENTIFIER_AUTHORITY sAuth = SECURITY_NT_AUTHORITY;
        bRet = InitializeSid( pLocalSid, &sAuth, lcAuths);
        }
        break;
    default:
        break;
    }
    if( bRet )
    {
        // 
        // SID created successfully!, add the sub authorities by
        // walking the pointers in the pAuths array, converting them to 
        // DWORD and shoving back into the SID.
        // 
        // The GetSidSubAuthority API returns a pointer to the location of
        // a given sub authority.  Once the string form of the subauthority is 
        // converted into a DWORD, it must be placed into the address pointed to by
        // the return value of the GetSidSubAuthority API.
        // 
        // All of these operations could be done in a single line of code, but have been
        // seperated for clarity.
        // 
        long j;
        for( j = 2; j <= lcAuths+1; j++)
        {
            DWORD dwValue = (DWORD)atol(pAuths[j]);
            PDWORD pdwSubAuth = GetSidSubAuthority( pLocalSid, (j-2));
            *pdwSubAuth = dwValue;
        }
    }
    else pLocalSid = NULL;
    return pLocalSid;
}
				

?考

如需詳細資訊,請按一下下列的文件編號,檢視 「 Microsoft 知識庫 」 中的文件:
286182? (http://support.microsoft.com/kb/286182/ ) 如何使用 Microsoft Visual Basic,將未經處理的 SID 轉換成字串 SID
也下列平台 SDK 需,請參閱主題 MSDN 線上:
SID 元件
http://msdn2.microsoft.com/en-us/library/aa379597.aspx (http://msdn2.microsoft.com/en-us/library/aa379597.aspx)

IADsAccessControlEntry
http://msdn2.microsoft.com/en-us/library/aa705951.aspx (http://msdn2.microsoft.com/en-us/library/aa705951.aspx)

LookupAccountSID
http://msdn2.microsoft.com/en-us/library/aa379166.aspx (http://msdn2.microsoft.com/en-us/library/aa379166.aspx)

這篇文章中的資訊適用於:
  • Microsoft Windows 2000 Server
  • Microsoft Windows 2000 Advanced Server
  • Microsoft Windows NT Server 4.0 Standard Edition
關鍵字:?
kbmt kbdswadsi2003swept kbhowto KB276208 KbMtzh
機器翻譯機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:276208? (http://support.microsoft.com/kb/276208/en-us/ )
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。