Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

382 lines
9.5 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
strsd.c
Abstract:
This Module implements wrapper functions to convert from a specialized
string representation of a security descriptor to the security descriptor
itself, and the opposite function.
Author:
Environment:
User Mode
Revision History:
--*/
#include "headers.h"
//#include <lmcons.h>
//#include <secobj.h>
//#include <netlib.h>
//#include <ntsecapi.h>
#include "sddl.h"
#pragma hdrstop
DWORD
ScepGetSecurityInformation(
IN PSECURITY_DESCRIPTOR pSD,
OUT SECURITY_INFORMATION *pSeInfo
);
DWORD
WINAPI
ConvertTextSecurityDescriptor (
IN PWSTR pwszTextSD,
OUT PSECURITY_DESCRIPTOR *ppSD,
OUT PULONG pcSDSize OPTIONAL,
OUT PSECURITY_INFORMATION pSeInfo OPTIONAL
)
{
DWORD rc=ERROR_SUCCESS;
if ( NULL == pwszTextSD || NULL == ppSD ) {
return(ERROR_INVALID_PARAMETER);
}
//
// initialize output buffers
//
*ppSD = NULL;
if ( pSeInfo ) {
*pSeInfo = 0;
}
if ( pcSDSize ) {
*pcSDSize = 0;
}
//
// call SDDL convert apis
//
if ( ConvertStringSecurityDescriptorToSecurityDescriptorW(
pwszTextSD,
SDDL_REVISION_1,
ppSD,
pcSDSize
) ) {
//
// conversion succeeds
//
if ( pSeInfo && *ppSD ) {
//
// get the SeInfo
//
rc = ScepGetSecurityInformation(
*ppSD,
pSeInfo
);
if ( rc != ERROR_SUCCESS ) {
LocalFree(*ppSD);
*ppSD = NULL;
if ( pcSDSize ) {
*pcSDSize = 0;
}
}
}
} else {
rc = GetLastError();
}
return(rc);
}
//
// Replace any of the new SDDL acronyms with SIDs, so we can keep SDDL strings
// compatible with older systems.
//
// Caller is responsible for free'ing the return string unless input string
// is returned directly, when no replacement is performed.
//
// Returns:
// ERROR_SUCCESS
// ERROR_NOT_ENOUGH_MEMORY
//
DWORD
ScepReplaceNewAcronymsInSDDL(
IN LPWSTR pwszOldSDDL,
OUT LPWSTR *ppwszNewSDDL,
ULONG *pcchNewSDDL
)
{
typedef struct _SDDLMapNode
{
PCWSTR pcwszAcronym;
PCWSTR pcwszSid;
DWORD cbSid; // pcwszSid byte size (excluding trailing zero), for optimization
} SDDLMapNode;
static const WCHAR pcwszSidAnonymous[] = L"S-1-5-7";
static const WCHAR pcwszLocalService[] = L"S-1-5-19";
static const WCHAR pcwszNetworkService[] = L"S-1-5-20";
static const WCHAR pcwszRemoteDesktop[] = L"S-1-5-32-555";
static const WCHAR pcwszNetConfigOps[] = L"S-1-5-32-556";
static const WCHAR pcwszPerfmonUsers[] = L"S-1-5-32-558";
static const WCHAR pcwszPerflogUser[] = L"S-1-5-32-559";
static SDDLMapNode SDDLMap[7] = {
{ SDDL_ANONYMOUS, pcwszSidAnonymous, sizeof(pcwszSidAnonymous)-sizeof(WCHAR) },
{ SDDL_LOCAL_SERVICE, pcwszLocalService , sizeof(pcwszLocalService)-sizeof(WCHAR) },
{ SDDL_NETWORK_SERVICE, pcwszNetworkService,sizeof(pcwszNetworkService)-sizeof(WCHAR) },
{ SDDL_REMOTE_DESKTOP, pcwszRemoteDesktop ,sizeof(pcwszRemoteDesktop)-sizeof(WCHAR) },
{ SDDL_NETWORK_CONFIGURATION_OPS, pcwszNetConfigOps , sizeof(pcwszNetConfigOps)-sizeof(WCHAR) },
{ SDDL_PERFMON_USERS, pcwszPerfmonUsers , sizeof(pcwszPerfmonUsers)-sizeof(WCHAR) },
{ SDDL_PERFLOG_USERS, pcwszPerflogUser , sizeof(pcwszPerflogUser)-sizeof(WCHAR) },
};
static const DWORD dwSDDLMapSize = sizeof(SDDLMap)/sizeof(SDDLMapNode);
DWORD dwCrtSDDL;
WCHAR *pch, *pchNew;
DWORD cbNewSDDL;
bool fMatchFound = false;
LPWSTR pwszNewSDDL = NULL;
*ppwszNewSDDL = NULL;
*pcchNewSDDL = 0;
if(!pwszOldSDDL)
{
return ERROR_SUCCESS;
}
//
// We make the following assumptions:
// - all acronyms are two chars long
// - they show up either after a ':' or a ';'
//
// First pass to calculate the size of new string
//
for(pch = pwszOldSDDL, cbNewSDDL = sizeof(WCHAR); // account for trailing zero
*pch != L'\0';
pch++, cbNewSDDL += sizeof(WCHAR))
{
//
// Acronyms always show up only after a ':' or a ';'
//
if(pch > pwszOldSDDL &&
(SDDL_SEPERATORC == *(pch - 1) ||
SDDL_DELIMINATORC == *(pch - 1)))
{
for(dwCrtSDDL = 0; dwCrtSDDL < dwSDDLMapSize; dwCrtSDDL++)
{
if(*pch == SDDLMap[dwCrtSDDL].pcwszAcronym[0] &&
*(pch + 1) == SDDLMap[dwCrtSDDL].pcwszAcronym[1])
{
//
// match found
//
cbNewSDDL += SDDLMap[dwCrtSDDL].cbSid;
pch++; // acronym is 2 chars, need to jump an extra char
fMatchFound = true;
break;
}
}
}
}
//
// optimization, if no replacement needed, immediately return old string
//
if(!fMatchFound)
{
*ppwszNewSDDL = pwszOldSDDL;
return ERROR_SUCCESS;
}
pwszNewSDDL = (LPWSTR)LocalAlloc(0, cbNewSDDL);
if(!pwszNewSDDL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Second pass, copy from old string to new one, replacing new acronyms with their SIDs
//
for(pch = pwszOldSDDL, pchNew = pwszNewSDDL;
*pch != L'\0';
pch++, pchNew++)
{
fMatchFound = false;
//
// Acronyms always show up only after a ':' or a ';'
//
if(pch > pwszOldSDDL &&
(SDDL_SEPERATORC == *(pch - 1) ||
SDDL_DELIMINATORC == *(pch - 1)))
{
for(dwCrtSDDL = 0; dwCrtSDDL < dwSDDLMapSize; dwCrtSDDL++)
{
if(*pch == SDDLMap[dwCrtSDDL].pcwszAcronym[0] &&
*(pch + 1) == SDDLMap[dwCrtSDDL].pcwszAcronym[1])
{
//
// match found
//
fMatchFound = true;
CopyMemory(pchNew, SDDLMap[dwCrtSDDL].pcwszSid, SDDLMap[dwCrtSDDL].cbSid);
pch++; // acronym is 2 chars, need to jump an extra char
pchNew += SDDLMap[dwCrtSDDL].cbSid/sizeof(WCHAR)-1; // minus one jumped in outer loop
break;
}
}
}
if(!fMatchFound)
{
*pchNew = *pch;
}
}
*pchNew = L'\0';
*ppwszNewSDDL = pwszNewSDDL;
*pcchNewSDDL = cbNewSDDL/sizeof(WCHAR);
return ERROR_SUCCESS;
}
DWORD
WINAPI
ConvertSecurityDescriptorToText (
IN PSECURITY_DESCRIPTOR pSD,
IN SECURITY_INFORMATION SecurityInfo,
OUT PWSTR *ppwszTextSD,
OUT PULONG pcTextSize
)
{
PWSTR pwszTempSD = NULL;
ULONG cchSDSize;
if (! ConvertSecurityDescriptorToStringSecurityDescriptorW(
pSD,
SDDL_REVISION_1,
SecurityInfo,
&pwszTempSD,
pcTextSize
) )
{
return(GetLastError());
}
//
// Replace any of the new SDDL acronyms with SIDs, so we can keep SDDL strings
// compatible with older systems.
//
DWORD dwErr = ScepReplaceNewAcronymsInSDDL(pwszTempSD, ppwszTextSD, &cchSDSize);
if(ERROR_SUCCESS != dwErr)
{
LocalFree(pwszTempSD);
return dwErr;
}
if(*ppwszTextSD != pwszTempSD)
{
LocalFree(pwszTempSD);
*pcTextSize = cchSDSize;
}
return ERROR_SUCCESS;
}
DWORD
ScepGetSecurityInformation(
IN PSECURITY_DESCRIPTOR pSD,
OUT SECURITY_INFORMATION *pSeInfo
)
{
PSID Owner = NULL, Group = NULL;
BOOLEAN Defaulted;
NTSTATUS Status;
SECURITY_DESCRIPTOR_CONTROL ControlCode=0;
ULONG Revision;
if ( !pSeInfo ) {
return(ERROR_INVALID_PARAMETER);
}
*pSeInfo = 0;
if ( !pSD ) {
return(ERROR_SUCCESS);
}
Status = RtlGetOwnerSecurityDescriptor( pSD, &Owner, &Defaulted );
if ( NT_SUCCESS( Status ) ) {
if ( Owner && !Defaulted ) {
*pSeInfo |= OWNER_SECURITY_INFORMATION;
}
Status = RtlGetGroupSecurityDescriptor( pSD, &Group, &Defaulted );
}
if ( NT_SUCCESS( Status ) ) {
if ( Group && !Defaulted ) {
*pSeInfo |= GROUP_SECURITY_INFORMATION;
}
Status = RtlGetControlSecurityDescriptor ( pSD, &ControlCode, &Revision);
}
if ( NT_SUCCESS( Status ) ) {
if ( ControlCode & SE_DACL_PRESENT ) {
*pSeInfo |= DACL_SECURITY_INFORMATION;
}
if ( ControlCode & SE_SACL_PRESENT ) {
*pSeInfo |= SACL_SECURITY_INFORMATION;
}
} else {
*pSeInfo = 0;
}
return( RtlNtStatusToDosError(Status) );
}