windows-nt/Source/XPSP1/NT/admin/admt/common/commonlib/txtsid.cpp
2020-09-26 16:20:57 +08:00

322 lines
10 KiB
C++

/*---------------------------------------------------------------------------
File: TextualSid.cpp
Comments: Converts a SID to and from its canonical textual representation.
(c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
Proprietary and confidential to Mission Critical Software, Inc.
REVISION LOG ENTRY
Revision By: Christy Boles
Revised on 02/15/99 11:33:52
---------------------------------------------------------------------------
*/
#ifdef USE_STDAFX
#include "stdafx.h"
#else
#include <windows.h>
#include <malloc.h>
#include <stdio.h>
#endif
#include "Mcs.h"
#include "TxtSid.h"
BOOL
GetTextualSid(
PSID pSid, // in - binary Sid
LPTSTR TextualSid, // i/o- buffer for Textual representation of Sid
LPDWORD lpdwBufferLen // in - required/provided TextualSid buffersize
)
{
PSID_IDENTIFIER_AUTHORITY psia;
DWORD dwSubAuthorities;
DWORD dwSidRev=SID_REVISION;
DWORD dwCounter;
DWORD dwSidSize;
// 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);
// Check input buffer length.
// If too small, indicate the proper size and set last error.
if (*lpdwBufferLen < dwSidSize)
{
*lpdwBufferLen = dwSidSize;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
// Add 'S' prefix and revision number to the string.
dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
// Add SID identifier authority to the string.
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) );
}
// Add SID subauthorities to the string. //
for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
{
dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"),
*GetSidSubAuthority(pSid, dwCounter) );
}
return TRUE;
}
PSID // ret- binary representation of SID, or NULL
SidFromString(
WCHAR const * strSid // in - string representation of SID
)
{
BOOL bSuccess = TRUE;
PSID pSid = NULL;
DWORD dwSidRev;
// WCHAR * strPtr = NULL;
WCHAR sidIA[100];
WCHAR sidSubs[100];
int ia0,ia1,ia2,ia3,ia4,ia5;
SID_IDENTIFIER_AUTHORITY sia;
do
{
if ( strSid[0] != L'S' || strSid[1] != L'-' )
{
bSuccess = FALSE;
break;
}
// Read SID revision level
sidSubs[0] = 0;
int result = swscanf(strSid,L"S-%d-%[^-]-%ls",&dwSidRev,sidIA,sidSubs);
if ( result == 3 )
{
// evaluate the IA
if ( sidIA[1] == L'x' )
{
// full format
result = swscanf(sidIA,L"0x%02hx%02hx%02hx%02hx%02hx%02hx",&ia0,&ia1,&ia2,&ia3,&ia4,&ia5);
if ( result == 6 )
{
sia.Value[0] = (BYTE) ia0;
sia.Value[1] = (BYTE) ia1;
sia.Value[2] = (BYTE) ia2;
sia.Value[3] = (BYTE) ia3;
sia.Value[4] = (BYTE) ia4;
sia.Value[5] = (BYTE) ia5;
}
else
{
bSuccess = FALSE;
break;
}
}
else
{
DWORD bignumber;
result = swscanf(sidIA,L"%lu",&bignumber);
sia.Value[0] = 0;
sia.Value[1] = 0;
sia.Value[2] = BYTE( (bignumber & 0xff000000) >> 24);
sia.Value[3] = BYTE( (bignumber & 0x00ff0000) >> 16);
sia.Value[4] = BYTE( (bignumber & 0x0000ff00) >> 8);
sia.Value[5] = BYTE(bignumber & 0x000000ff);
}
// read the subauthorities
DWORD subs[10];
memset(subs,0,(sizeof subs));
result = swscanf(sidSubs,L"%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu",&subs[0],&subs[1],&subs[2],&subs[3],&subs[4],
&subs[5],&subs[6],&subs[7]);
if ( result )
{
if ( !AllocateAndInitializeSid(&sia,(BYTE)result,subs[0],subs[1],subs[2],subs[3],subs[4],subs[5],subs[6],subs[7],&pSid) )
{
pSid = NULL;
bSuccess = FALSE;
}
}
}
} while ( false);
//see if IsValidSid also thinks this is valid
if (pSid)
{
//if not valid, free it and return NULL
if (!IsValidSid(pSid))
{
FreeSid(pSid);
pSid = NULL;
}
}
return pSid;
}
/*****************************************************************************************************/
/* DomainizeSid:
Takes a domain sid, and verifies that its last subauthority value is -1. If the RID is not
-1, DomainizeSid adds a -1 to the end.
/*****************************************************************************************************/
PSID // ret -the sid with RID = -1
DomainizeSid(
PSID psid, // in -sid to check and possibly fix
BOOL freeOldSid // in -whether to free the old sid
)
{
MCSASSERT(psid);
UCHAR len = (* GetSidSubAuthorityCount(psid));
PDWORD sub = GetSidSubAuthority(psid,len-1);
if ( *sub != -1 )
{
DWORD sdsize = GetSidLengthRequired(len+1); // sid doesn't already have -1 as rid
PSID newsid = (SID *)malloc(sdsize); // copy the sid, and add -1 to the end
if (newsid)
{
if ( ! InitializeSid(newsid,GetSidIdentifierAuthority(psid),len+1) ) // make a bigger sid w/same IA
{
MCSASSERT(false);
}
for ( DWORD i = 0 ; i < len ; i++ )
{
sub = GetSidSubAuthority(newsid,i); // copy subauthorities
(*sub) = (*GetSidSubAuthority(psid,i));
}
sub = GetSidSubAuthority(newsid,len);
*sub = -1; // set rid =-1
if ( freeOldSid )
{
FreeSid(psid);
}
psid = newsid;
len++;
}
}
return psid;
}
/*********************************************************************
* *
* Written by: Paul Thompson *
* Date: 4 OCT 2000 *
* *
* This function is responsible for taking the given source and *
* target account SIDs and breaking them up and returning the src *
* domain sid, src account rid, tgt domain sid, and tgt account rid. *
* The caller must call "FreeSid" on the src and tgt domain sid *
* pointers. *
* *
*********************************************************************/
//BEGIN SplitAccountSids
BOOL // ret - Success ? TRUE | FALSE
SplitAccountSids(
PSID srcSid, // in - src account sid
WCHAR *srcDomainSid, // out - src domain sid textual
DWORD *srcRid, // out - src account rid
PSID tgtSid, // in - tgt account sid
WCHAR *tgtDomainSid, // out - tgt domain sid textual
DWORD *tgtRid // out - tgt account rid
)
{
/* local variables */
DWORD sidLen;
UCHAR Count;
PDWORD psubAuth;
BOOL bSuccess = TRUE;
DWORD lenTxt = MAX_PATH;
/* function body */
if ((!IsValidSid(srcSid)) && (!IsValidSid(tgtSid)))
return FALSE;
//split up the src account sid
sidLen = GetLengthSid(srcSid);
PSID srcDomSid = new BYTE[sidLen+1];
if (!srcDomSid)
return FALSE;
if (!CopySid(sidLen+1, srcDomSid, srcSid))
{
delete [] srcDomSid;
return FALSE;
}
//get the RID out of the SID and get the domain SID
Count = (* GetSidSubAuthorityCount(srcDomSid));
psubAuth = GetSidSubAuthority(srcDomSid, Count-1);
if (psubAuth)
{
*srcRid = *psubAuth;
*psubAuth = -1;
}
//convert domain sid to text format
if (srcDomSid)
{
GetTextualSid(srcDomSid,srcDomainSid,&lenTxt);
delete [] srcDomSid;
}
//split up the tgt account sid
sidLen = GetLengthSid(tgtSid);
PSID tgtDomSid = new BYTE[sidLen+1];
if (!tgtDomSid)
return FALSE;
if (!CopySid(sidLen+1, tgtDomSid, tgtSid))
{
delete [] tgtDomSid;
return FALSE;
}
//get the RID out of the SID and get the domain SID
Count = (* GetSidSubAuthorityCount(tgtDomSid));
psubAuth = GetSidSubAuthority(tgtDomSid, Count-1);
if (psubAuth)
{
*tgtRid = *psubAuth;
*psubAuth = -1;
}
//convert domain sid to text format
lenTxt = MAX_PATH;
if (tgtDomSid)
{
GetTextualSid(tgtDomSid,tgtDomainSid,&lenTxt);
delete [] tgtDomSid;
}
return bSuccess;
}
//END SplitAccountSids