windows-nt/Source/XPSP1/NT/ds/security/tools/dsacls/dsacls.cpp

1611 lines
47 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1996 - 1998 Microsoft Corporation
Module Name:
dsacls.c
Abstract:
This Module implements the delegation tool, which allows for the management
of access to DS objects
Author:
Mac McLain (MacM) 10-15-96
Environment:
User Mode
Revision History:
Hitesh Raigandhi (hiteshr 6-29-98)
1: Changed the code to Old NTMART API's
2: Redesigned the structure
--*/
#include "stdafx.h"
#include "utils.h"
#include "dsace.h"
#include "dsacls.h"
#define DSACL_DBG 1
//
// Local helper macros
//
#define FLAG_ON(flag,bits) ((flag) & (bits))
#define IS_CMD_FLAG( string ) (*(string) == L'-' || *(string) == L'/' )
DSACLS_ARG DsAclsArgs[] = {
{ MSG_TAG_CI, NULL, 0, 0, MSG_TAG_CI, 0, FALSE, DSACLS_EXTRA_INFO_REQUIRED },
{ MSG_TAG_CN, NULL, 0, 0, MSG_TAG_CN, 0, FALSE, DSACLS_EXTRA_INFO_NONE },
{ MSG_TAG_CP, NULL, 0, 0, MSG_TAG_CP, 0, FALSE, DSACLS_EXTRA_INFO_REQUIRED },
{ MSG_TAG_CG, NULL, 0, 0, MSG_TAG_CG, 0, TRUE, DSACLS_EXTRA_INFO_NONE },
{ MSG_TAG_CD, NULL, 0, 0, MSG_TAG_CD, 0, TRUE, DSACLS_EXTRA_INFO_NONE },
{ MSG_TAG_CR, NULL, 0, 0, MSG_TAG_CR, 0, TRUE, DSACLS_EXTRA_INFO_NONE },
{ MSG_TAG_CS, NULL, 0, 0, MSG_TAG_CS, 0, FALSE, DSACLS_EXTRA_INFO_NONE },
{ MSG_TAG_CT, NULL, 0, 0, MSG_TAG_CT, 0, FALSE, DSACLS_EXTRA_INFO_NONE },
{ MSG_TAG_CA, NULL, 0, 0, MSG_TAG_CA, 0, FALSE, DSACLS_EXTRA_INFO_NONE },
{ MSG_TAG_GETSDDL,NULL, 0, 0, MSG_TAG_GETSDDL, 0, FALSE, DSACLS_EXTRA_INFO_OPTIONAL },
{ MSG_TAG_SETSDDL,NULL, 0, 0, MSG_TAG_SETSDDL, 0, FALSE, DSACLS_EXTRA_INFO_REQUIRED }
};
DSACLS_INHERIT DsAclsInherit[] = {
{ MSG_TAG_IS, NULL, 0, TRUE, CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE},
{ MSG_TAG_IT, NULL, 0, TRUE, CONTAINER_INHERIT_ACE },
{ MSG_TAG_IP, NULL, 0, TRUE, INHERIT_NO_PROPAGATE },
{ MSG_TAG_ID, NULL, 0, FALSE, INHERITED_ACCESS_ENTRY }
};
DSACLS_RIGHTS DsAclsRights[] = {
{ MSG_TAG_GR, NULL,MSG_TAG_GR_EX,NULL, 0, GENERIC_READ },
{ MSG_TAG_GE, NULL,MSG_TAG_GE_EX,NULL, 0, GENERIC_EXECUTE },
{ MSG_TAG_GW, NULL,MSG_TAG_GW_EX,NULL, 0, GENERIC_WRITE },
{ MSG_TAG_GA, NULL,MSG_TAG_GA_EX,NULL, 0, GENERIC_ALL },
{ MSG_TAG_SD, NULL,MSG_TAG_SD_EX,NULL, 0, DELETE },
{ MSG_TAG_RC, NULL,MSG_TAG_RC_EX,NULL, 0, READ_CONTROL },
{ MSG_TAG_WD, NULL,MSG_TAG_WD_EX,NULL, 0, WRITE_DAC },
{ MSG_TAG_WO, NULL,MSG_TAG_WO_EX,NULL, 0, WRITE_OWNER },
{ MSG_TAG_CC, NULL,MSG_TAG_CC_EX,NULL, 0, ACTRL_DS_CREATE_CHILD },
{ MSG_TAG_DC, NULL,MSG_TAG_DC_EX,NULL, 0, ACTRL_DS_DELETE_CHILD },
{ MSG_TAG_LC, NULL,MSG_TAG_LC_EX,NULL, 0, ACTRL_DS_LIST },
{ MSG_TAG_WS, NULL,MSG_TAG_WS_EX,NULL, 0, ACTRL_DS_SELF },
{ MSG_TAG_WP, NULL,MSG_TAG_WP_EX,NULL, 0, ACTRL_DS_WRITE_PROP },
{ MSG_TAG_RP, NULL,MSG_TAG_RP_EX,NULL, 0, ACTRL_DS_READ_PROP },
{ MSG_TAG_DT, NULL,MSG_TAG_DT_EX,NULL, 0, ACTRL_DS_DELETE_TREE },
{ MSG_TAG_LO, NULL,MSG_TAG_LO_EX,NULL, 0, ACTRL_DS_LIST_OBJECT },
{ MSG_TAG_AC, NULL,MSG_TAG_AC_EX,NULL, 0, ACTRL_DS_CONTROL_ACCESS } //This is only for input
};
DSACLS_PROTECT DsAclsProtect[] = {
{ MSG_TAG_PY, NULL, 0, PROTECTED_DACL_SECURITY_INFORMATION },
{ MSG_TAG_PN, NULL, 0, UNPROTECTED_DACL_SECURITY_INFORMATION }
};
/*
Displays The security Descriptor
*/
DWORD
DumpAccess (
IN PSECURITY_DESCRIPTOR pSD,
IN BOOL bDisplayAuditAndOwner
)
{
DWORD dwErr = ERROR_SUCCESS;
SECURITY_DESCRIPTOR_CONTROL wSDControl = 0;
DWORD dwRevision;
PSID psidOwner = NULL;
PSID psidGroup = NULL;
PACL pDacl = NULL;
PACL pSacl = NULL;
BOOL bDefaulted;
BOOL bPresent;
LPWSTR pOwnerName = NULL;
LPWSTR pGroupName = NULL;
CAcl * pCSacl = NULL;
CAcl * pCDacl = NULL;
UINT nLen1 = 0;
UINT nLen2 = 0;
UINT nAllowDeny = 0;
UINT nAudit = 0;
WCHAR szLoadBuffer[1024];
if( !GetSecurityDescriptorControl(pSD, &wSDControl, &dwRevision) )
{
dwErr = GetLastError();
goto CLEAN_RETURN;
}
if( !GetSecurityDescriptorOwner(pSD, &psidOwner, &bDefaulted) )
{
dwErr = GetLastError();
goto CLEAN_RETURN;
}
if( !GetSecurityDescriptorGroup(pSD, &psidGroup, &bDefaulted) )
{
dwErr = GetLastError();
goto CLEAN_RETURN;
}
if( !GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefaulted) )
{
dwErr = GetLastError();
goto CLEAN_RETURN;
}
if( !GetSecurityDescriptorSacl(pSD, &bPresent, &pSacl, &bDefaulted) )
{
dwErr = GetLastError();
goto CLEAN_RETURN;
}
//Find out the Max len out of ( ALLOW, DENY ) and ( FAILURE, SUCCESS, BOTH)
nLen1 = LoadStringW( g_hInstance, MSG_DSACLS_ALLOW, szLoadBuffer, 1023 );
nLen2 = LoadStringW( g_hInstance, MSG_DSACLS_DENY, szLoadBuffer, 1023 );
nAllowDeny = ( nLen1 > nLen2 ) ? nLen1 : nLen2;
nLen1 = LoadStringW( g_hInstance, MSG_DSACLS_AUDIT_SUCCESS, szLoadBuffer, 1023 );
nLen2 = LoadStringW( g_hInstance, MSG_DSACLS_AUDIT_FAILURE, szLoadBuffer, 1023 );
nAudit = ( nLen1 > nLen2 ) ? nLen1 : nLen2;
nLen1 = LoadStringW( g_hInstance, MSG_DSACLS_AUDIT_ALL, szLoadBuffer, 1023 );
nAudit = ( nLen1 > nAudit ) ? nLen1 : nAudit;
if( bDisplayAuditAndOwner )
{
pCSacl = new CAcl();
CHECK_NULL( pCSacl, CLEAN_RETURN );
dwErr = pCSacl->Initialize(wSDControl & SE_SACL_PROTECTED,
pSacl,
nAllowDeny,
nAudit );
if( dwErr != ERROR_SUCCESS )
return dwErr;
}
pCDacl = new CAcl();
CHECK_NULL( pCDacl,CLEAN_RETURN );
dwErr = pCDacl->Initialize(wSDControl & SE_DACL_PROTECTED,
pDacl,
nAllowDeny,
nAudit);
if( dwErr != ERROR_SUCCESS )
return dwErr;
if( ( dwErr = g_Cache->BuildCache() ) != ERROR_SUCCESS )
return dwErr;
pCDacl->GetInfoFromCache();
if( bDisplayAuditAndOwner )
{
if( ( dwErr = GetAccountNameFromSid( g_szServerName, psidOwner, &pOwnerName ) ) != ERROR_SUCCESS )
goto CLEAN_RETURN;
DisplayMessageEx( 0, MSG_DSACLS_OWNER, pOwnerName );
if( ( dwErr = GetAccountNameFromSid( g_szServerName, psidGroup, &pGroupName ) ) != ERROR_SUCCESS )
goto CLEAN_RETURN;
DisplayMessageEx( 0, MSG_DSACLS_GROUP, pGroupName );
DisplayNewLine();
DisplayMessageEx( 0, MSG_DSACLS_AUDIT );
pCSacl->Display();
DisplayNewLine();
}
DisplayMessageEx( 0, MSG_DSACLS_ACCESS );
pCDacl->Display();
CLEAN_RETURN:
if( pOwnerName )
LocalFree( pOwnerName );
if( pGroupName )
LocalFree( pGroupName );
if( pCSacl )
delete pCSacl;
if( pCDacl )
delete pCDacl;
return dwErr;
}
/*
This Function process the command line argument for /D /R /G
options and add the corresponding aces to pAcl.
*/
DWORD
ProcessCmdlineUsers ( IN WCHAR *argv[],
IN PDSACLS_ARG AclsArg,
IN DSACLS_OP Op,
IN ULONG Inheritance,
IN ULONG RightsListCount,
IN PDSACLS_RIGHTS RightsList,
OUT CAcl *pAcl )
{
DWORD dwErr = ERROR_SUCCESS;
ULONG i, j;
ULONG AccIndex, Access;
PEXPLICIT_ACCESS pListOfExplicitEntries = NULL;
PWSTR pObjectId = NULL;
PWSTR pTrustee = NULL;
PWSTR pInheritId = NULL;
ACCESS_MODE AccessMode;
CAce * pAce = NULL;
switch ( Op ) {
case REVOKE:
AccessMode = REVOKE_ACCESS;
break;
case GRANT:
AccessMode = GRANT_ACCESS;
break;
case DENY:
AccessMode = DENY_ACCESS;
break;
default:
dwErr = ERROR_INVALID_PARAMETER;
break;
}
if ( dwErr != ERROR_SUCCESS )
goto FAILURE_RETURN;
for ( i = 0; i < AclsArg->SkipCount && dwErr == ERROR_SUCCESS; i++ )
{
dwErr = ParseUserAndPermissons( argv[AclsArg->StartIndex + 1 + i],
Op,
RightsListCount,
RightsList,
&pTrustee,
&Access,
&pObjectId,
&pInheritId );
if( dwErr != ERROR_SUCCESS )
goto FAILURE_RETURN;
pAce = new CAce();
CHECK_NULL( pAce , FAILURE_RETURN);
dwErr= pAce->Initialize( pTrustee,
pObjectId,
pInheritId,
AccessMode,
Access,
Inheritance );
if( dwErr != ERROR_SUCCESS )
return dwErr;
pAcl->AddAce( pAce );
if( pObjectId )
{
LocalFree( pObjectId );
pObjectId = NULL;
}
if( pInheritId )
{
LocalFree( pInheritId );
pInheritId = NULL;
}
if( pTrustee )
{
LocalFree( pTrustee );
pTrustee = NULL;
}
}
FAILURE_RETURN:
if( pObjectId )
{
LocalFree( pObjectId );
pObjectId = NULL;
}
if( pInheritId )
{
LocalFree( pInheritId );
pInheritId = NULL;
}
if( pTrustee )
{
LocalFree( pTrustee );
pTrustee = NULL;
}
return( dwErr );
}
//These five are global variables used by the dsacls
LPWSTR g_szSchemaNamingContext;
LPWSTR g_szConfigurationNamingContext;
HMODULE g_hInstance;
LPWSTR g_szServerName;
CCache *g_Cache;
__cdecl
main (
IN INT argc,
IN CHAR *argv[]
)
{
DWORD dwErr = ERROR_SUCCESS;
ULONG Length, Options = 0;
PWSTR pszObjectPath = NULL;
PWSTR pszLDAPObjectPath = NULL;
PSTR SddlString = NULL, TempString;
LPWSTR FileName = NULL;
CHAR ReadString[ 512 ];
BOOLEAN Mapped;
LPWSTR CurrentInherit = NULL;
LPWSTR CurrentProtect = NULL;
ULONG Inheritance = 0;
SECURITY_INFORMATION Protection = 0;
ULONG SddlStringLength = 0;
WCHAR ** wargv = NULL;
ULONG i = 0;
ULONG j = 0;
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pDacl = NULL;
SECURITY_INFORMATION SecurityInformation = DACL_SECURITY_INFORMATION;
PSECURITY_DESCRIPTOR pTempSD = NULL;
PACL pNewDacl = NULL;
CAcl * pCAclOld = NULL;
CAcl *pCAclNew = NULL;
BOOL bErrorShown = FALSE;
//Initialize Com Library
HRESULT hr = CoInitialize(NULL);
CHECK_HR(hr, CLEAN_RETURN);
//Get Instance Handle
g_hInstance = GetModuleHandle(NULL);
//Create global instance of Cache
g_Cache = new CCache();
CHECK_NULL(g_Cache,CLEAN_RETURN);
setlocale( LC_CTYPE, "" );
//Initialize Global Arrays
if( ( dwErr = InitializeGlobalArrays() ) != ERROR_SUCCESS )
goto CLEAN_RETURN;
if ( argc == 1 )
{
DisplayMessage( 0, MSG_DSACLS_USAGE );
goto CLEAN_RETURN;
}
//Convert argv to Unicode
wargv = (LPWSTR*)LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, argc * sizeof(LPWSTR) );
CHECK_NULL(wargv, CLEAN_RETURN );
if( ( dwErr = ConvertArgvToUnicode( wargv, argv, argc ) ) != ERROR_SUCCESS )
goto CLEAN_RETURN;
//First Argument is Object Path or /?
if( IS_CMD_FLAG( wargv[ 1 ] ) )
{
if ( _wcsicmp( wargv[ 1 ] + 1, L"?" ) != 0 )
DisplayMessageEx( 0, MSG_DSACLS_PARAM_UNEXPECTED, wargv[1] );
DisplayMessage(0,MSG_DSACLS_USAGE);
goto CLEAN_RETURN;
}
Length = wcslen( wargv[1] );
pszObjectPath = (LPWSTR)LocalAlloc( LMEM_FIXED,
( Length + 1 ) * sizeof( WCHAR ) );
if ( !pszObjectPath )
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto CLEAN_RETURN;
} else
{
wcscpy( pszObjectPath,
wargv[ 1 ] );
}
//Get the name of server
dwErr = GetServerName( pszObjectPath, &g_szServerName );
if( dwErr != ERROR_SUCCESS )
goto CLEAN_RETURN;
if( ( dwErr = BuildLdapPath( &pszLDAPObjectPath,
g_szServerName,
pszObjectPath ) ) != ERROR_SUCCESS )
goto CLEAN_RETURN;
//Get Schema and Configuration naming context
dwErr = GetGlobalNamingContexts( g_szServerName,
&g_szSchemaNamingContext,
&g_szConfigurationNamingContext );
if( dwErr != ERROR_SUCCESS )
goto CLEAN_RETURN;
//
// Parse the command line
//
i = 2;
while ( i < ( ULONG )argc && dwErr == ERROR_SUCCESS )
{
if ( IS_CMD_FLAG( wargv[ i ] ) )
{
if ( !_wcsicmp( wargv[ i ] + 1, L"?" ) ) {
DisplayMessage( 0, MSG_DSACLS_USAGE );
goto CLEAN_RETURN;
}
Mapped = FALSE;
for ( j = 0; j < ( sizeof( DsAclsArgs ) / sizeof( DSACLS_ARG ) ); j++ )
{
if ( !wcsncmp( wargv[ i ] + 1, DsAclsArgs[ j ].String,DsAclsArgs[ j ].Length ) )
{
if( DsAclsArgs[ j ].ExtraInfo )
{
if( ( DsAclsArgs[ j ].ExtraInfo == DSACLS_EXTRA_INFO_REQUIRED &&
wargv[ i ][ DsAclsArgs[ j ].Length + 1 ] == ':' &&
wargv[ i ][ DsAclsArgs[ j ].Length + 2 ] != '\0' ) ||
(DsAclsArgs[ j ].ExtraInfo == DSACLS_EXTRA_INFO_OPTIONAL &&
( ( wargv[ i ][ DsAclsArgs[ j ].Length + 1 ] == ':' &&
wargv[ i ][ DsAclsArgs[ j ].Length + 2 ] != '\0' ) ||
wargv[ i ][ DsAclsArgs[ j ].Length + 1 ] == '\0' ) ) )
{
Mapped = TRUE;
}
} else
{
Mapped = TRUE;
}
break;
}
}//For
if ( Mapped )
{
DsAclsArgs[ j ].StartIndex = i;
Options |= DsAclsArgs[ j ].Flag;
if ( DsAclsArgs[ j ].SkipNonFlag )
{
while ( i + 1 < ( ULONG )argc && !IS_CMD_FLAG( wargv[ i + 1 ] ) )
{
i++;
DsAclsArgs[ j ].SkipCount++;
}
if ( DsAclsArgs[ j ].SkipCount == 0 )
{
DisplayMessageEx( 0, MSG_DSACLS_NO_UA,
wargv[i] );
dwErr = ERROR_INVALID_PARAMETER;
goto CLEAN_RETURN;
}
}
}
else
{
DisplayMessageEx( 0, MSG_DSACLS_PARAM_UNEXPECTED, wargv[i] );
dwErr = ERROR_INVALID_PARAMETER;
goto CLEAN_RETURN;
}
} else
{
DisplayMessageEx( 0, MSG_DSACLS_PARAM_UNEXPECTED, wargv[i] );
dwErr = ERROR_INVALID_PARAMETER;
goto CLEAN_RETURN;
}
i++;
}//While
//Validate the command line argument
/*
if ( !FLAG_ON( Options, MSG_TAG_CR | MSG_TAG_CD | MSG_TAG_CG | MSG_TAG_CT | MSG_TAG_CS ) )
{
if ( FLAG_ON( Options, MSG_TAG_GETSDDL ) )
{
if ( dwErr == ERROR_SUCCESS )
{
if ( !ConvertSecurityDescriptorToStringSecurityDescriptorA( pSD,
SDDL_REVISION,
SecurityInformation,
&SddlString,
NULL ) )
{
dwErr = GetLastError();
} else
{
//
// Get the file name to write it to if necessary
//
for ( j = 0; j < ( sizeof( DsAclsArgs ) / sizeof( DSACLS_ARG ) ); j++ )
{
if ( DsAclsArgs[ j ].Flag == MSG_TAG_GETSDDL )
{
FileName = wcschr( wargv[ DsAclsArgs[ j ].StartIndex ] , L':' );
if ( FileName )
{
FileName++;
}
break;
}
}
if ( FileName )
{
HANDLE FileHandle = CreateFile( FileName,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL );
if ( FileHandle == INVALID_HANDLE_VALUE )
{
dwErr = GetLastError();
} else
{
ULONG BytesWritten;
if ( WriteFile( FileHandle,
( PVOID )SddlString,
strlen( SddlString ),
&BytesWritten,
NULL ) == FALSE )
{
dwErr = GetLastError();
} else
{
ASSERT( strlen( SddlString ) == BytesWritten );
}
CloseHandle( FileHandle );
}
} else
{
printf( "%s\n", SddlString );
}
LocalFree( SddlString );
}
//LocalFree( SD );
}
} else {
DumpAccess( pSD,
FLAG_ON( Options, MSG_TAG_CA ),
sizeof( DsAclsInherit ) / sizeof( DSACLS_INHERIT ),
DsAclsInherit,
sizeof( DsAclsRights ) / sizeof( DSACLS_RIGHTS ),
DsAclsRights );
}
}
*/
/*
//
// If we are parsing an SDDL file, go ahead and do that now...
//
if ( FLAG_ON( Options, MSG_TAG_SETSDDL ) )
{
//
// First, open the file
//
HANDLE FileHandle = INVALID_HANDLE_VALUE;
//
// Get the file name to write it to if necessary
//
for ( j = 0; j < ( sizeof( DsAclsArgs ) / sizeof( DSACLS_ARG ) ); j++ ) {
if ( DsAclsArgs[ j ].Flag == MSG_TAG_SETSDDL ) {
FileName = wcschr( wargv[ DsAclsArgs[ j ].StartIndex ] , L':' );
if ( FileName ) {
FileName++;
}
break;
}
}
if ( !FileName ) {
dwErr = ERROR_INVALID_PARAMETER;
goto CLEAN_RETURN;
}
FileHandle = CreateFile( FileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
if ( FileHandle == INVALID_HANDLE_VALUE ) {
dwErr = GetLastError();
goto CLEAN_RETURN;
}
//
// Now, parse it...
//
SddlStringLength = 0;
SddlString = NULL;
while ( TRUE ) {
ULONG Read = 0, Len = 0;
PSTR ReadPtr, TempPtr;
if ( ReadFile( FileHandle,
ReadString,
sizeof( ReadString ) / sizeof( CHAR ),
&Read,
NULL ) == FALSE ) {
dwErr = GetLastError();
break;
}
if ( Read == 0 ) {
break;
}
if ( *ReadString == ';' ) {
continue;
}
Len = SddlStringLength + ( Read / sizeof( CHAR ) );
TempString = (LPSTR)LocalAlloc( LMEM_FIXED,
Len + sizeof( CHAR ) );
if ( TempString ) {
if ( SddlString ) {
strcpy( TempString, SddlString );
} else {
*TempString = '\0';
}
TempPtr = TempString + SddlStringLength;
ReadPtr = ReadString;
while( Read-- > 0 ) {
if ( !isspace( *ReadPtr ) ) {
*TempPtr++ = *ReadPtr;
SddlStringLength++;
}
ReadPtr++;
}
*TempPtr = '\0';
LocalFree( SddlString );
SddlString = TempString;
} else {
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
}
if ( dwErr == ERROR_SUCCESS ) {
//
// Convert it to a security descriptor, then to an access list, then set it.
//
if ( ConvertStringSecurityDescriptorToSecurityDescriptorA( SddlString,
SDDL_REVISION,
&pTempSD,
NULL ) == FALSE ) {
dwErr = GetLastError();
} else {
dwErr = WriteObjectSecurity( pszObjectPath,
DACL_SECURITY_INFORMATION,
pTempSD );
LocalFree( pTempSD );
}
}
LocalFree( SddlString );
if ( FileHandle != INVALID_HANDLE_VALUE ) {
CloseHandle( FileHandle );
}
goto CLEAN_RETURN;
}
*/
//
// Get the inheritance flags set
//
if ( FLAG_ON( Options, MSG_TAG_CI ) )
{
for ( j = 0; j < ( sizeof( DsAclsArgs ) / sizeof( DSACLS_ARG ) ); j++ )
{
if ( DsAclsArgs[ j ].Flag == MSG_TAG_CI )
{
CurrentInherit = wargv[ DsAclsArgs[ j ].StartIndex ] + 3;
while ( CurrentInherit && *CurrentInherit && dwErr == ERROR_SUCCESS )
{
for ( i = 0; i < ( sizeof( DsAclsInherit ) / sizeof( DSACLS_INHERIT ) ); i++ )
{
if ( !_wcsnicmp( CurrentInherit,
DsAclsInherit[ i ].String,
DsAclsInherit[ i ].Length ) )
{
if ( !DsAclsInherit[ i ].ValidForInput )
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
Inheritance |= DsAclsInherit[ i ].InheritFlag;
CurrentInherit += DsAclsInherit[ i ].Length;
break;
}
}
if ( i == ( sizeof( DsAclsInherit ) / sizeof( DSACLS_INHERIT ) ) )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CLEAN_RETURN;
}
}
break;
}
}
}
//Get the protection flag
if ( FLAG_ON( Options, MSG_TAG_CP ) )
{
for ( j = 0; j < ( sizeof( DsAclsArgs ) / sizeof( DSACLS_ARG ) ); j++ )
{
if ( DsAclsArgs[ j ].Flag == MSG_TAG_CP )
{
CurrentProtect = wargv[ DsAclsArgs[ j ].StartIndex ] + DsAclsArgs[ j ].Length + 2;
while ( CurrentProtect && *CurrentProtect )
{
for ( i = 0; i < ( sizeof( DsAclsProtect ) / sizeof( DSACLS_PROTECT ) ); i++ )
{
if ( !_wcsnicmp( CurrentProtect,
DsAclsProtect[ i ].String,
DsAclsProtect[ i ].Length ) )
{
Protection |= DsAclsProtect[ i ].Right;
CurrentProtect += DsAclsProtect[ i ].Length;
break;
}
}
if ( i == ( sizeof( DsAclsProtect ) / sizeof( DSACLS_PROTECT ) ) )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CLEAN_RETURN;
}
}
break;
}
}
}
//
// Start processing them in order
//
if ( FLAG_ON( Options, MSG_TAG_CR | MSG_TAG_CD | MSG_TAG_CG | MSG_TAG_CP ) )
{
//
// Get the current information, if required
//
if( !FLAG_ON( Options, MSG_TAG_CN ) )
{
SecurityInformation = DACL_SECURITY_INFORMATION;
dwErr = GetNamedSecurityInfo( pszLDAPObjectPath,
SE_DS_OBJECT_ALL,
SecurityInformation,
NULL,
NULL,
&pDacl,
NULL,
&pSD );
if ( dwErr != ERROR_SUCCESS ) {
goto CLEAN_RETURN;
}
//pCAclOld represents existing ACL
pCAclOld = new CAcl();
CHECK_NULL( pCAclOld, CLEAN_RETURN );
dwErr = pCAclOld->Initialize( FALSE, pDacl,0 ,0 );
if( dwErr != ERROR_SUCCESS )
goto CLEAN_RETURN;
if( !FLAG_ON( Options, MSG_TAG_CP ) )
{
dwErr = GetProtection( pSD, &Protection );
if( dwErr != ERROR_SUCCESS )
goto CLEAN_RETURN;
}
}
pCAclNew = new CAcl();
CHECK_NULL( pCAclNew, CLEAN_RETURN );
//
// Grant
//
if ( dwErr == ERROR_SUCCESS && FLAG_ON( Options, MSG_TAG_CG ) ) {
for ( j = 0; j < ( sizeof( DsAclsArgs ) / sizeof( DSACLS_ARG ) ); j++ ) {
if ( DsAclsArgs[ j ].Flag == MSG_TAG_CG ) {
dwErr = ProcessCmdlineUsers( wargv,
&DsAclsArgs[ j ],
GRANT,
Inheritance,
sizeof( DsAclsRights ) / sizeof( DSACLS_RIGHTS ),
DsAclsRights,
pCAclNew );
if ( dwErr != ERROR_SUCCESS ) {
goto CLEAN_RETURN;
}
break;
}
}
}
if ( dwErr == ERROR_SUCCESS && FLAG_ON( Options, MSG_TAG_CD ) ) {
for ( j = 0; j < ( sizeof( DsAclsArgs ) / sizeof( DSACLS_ARG ) ); j++ ) {
if ( DsAclsArgs[ j ].Flag == MSG_TAG_CD ) {
dwErr = ProcessCmdlineUsers( wargv,
&DsAclsArgs[ j ],
DENY,
Inheritance,
sizeof( DsAclsRights ) / sizeof( DSACLS_RIGHTS ),
DsAclsRights,
pCAclNew );
if ( dwErr != ERROR_SUCCESS ) {
goto CLEAN_RETURN;
}
break;
}
}
}
if ( dwErr == ERROR_SUCCESS && FLAG_ON( Options, MSG_TAG_CR ) ) {
for ( j = 0; j < ( sizeof( DsAclsArgs ) / sizeof( DSACLS_ARG ) ); j++ ) {
if ( DsAclsArgs[ j ].Flag == MSG_TAG_CR ) {
dwErr = ProcessCmdlineUsers( wargv,
&DsAclsArgs[ j ],
REVOKE,
Inheritance,
sizeof( DsAclsRights ) / sizeof( DSACLS_RIGHTS ),
DsAclsRights,
pCAclNew );
if ( dwErr != ERROR_SUCCESS ) {
goto CLEAN_RETURN;
}
break;
}
}
}
//Build Cache
g_Cache->BuildCache();
//Verify that we have been able to convert all ObjectType and InheritedObjectType
// names to GUIDs
pCAclNew->GetInfoFromCache();
if( !pCAclNew->VerifyAllNames() )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CLEAN_RETURN;
}
if( pCAclOld )
pCAclOld->GetInfoFromCache();
if( pCAclOld )
{
pCAclOld->MergeAcl( pCAclNew );
if(( dwErr = pCAclOld->BuildAcl( &pNewDacl ) ) != ERROR_SUCCESS )
goto CLEAN_RETURN;
}
else
{
if( ( dwErr = pCAclNew->BuildAcl( &pNewDacl ) ) != ERROR_SUCCESS )
goto CLEAN_RETURN;
}
SecurityInformation = DACL_SECURITY_INFORMATION | Protection;
dwErr = SetNamedSecurityInfo ( pszLDAPObjectPath,
SE_DS_OBJECT_ALL,
SecurityInformation,
NULL,
NULL,
pNewDacl,
NULL );
if( dwErr != ERROR_SUCCESS )
goto CLEAN_RETURN;
}
//
// Now, see if we have to restore any security to the defaults
//
if ( FLAG_ON( Options, MSG_TAG_CS ) ) {
dwErr = SetDefaultSecurityOnObjectTree( pszObjectPath,
( BOOLEAN )( FLAG_ON( Options, MSG_TAG_CT ) ?
TRUE : FALSE ),Protection );
if( dwErr != ERROR_SUCCESS )
goto CLEAN_RETURN;
}
//Display the security
if( pSD )
{
LocalFree( pSD );
pSD = NULL;
}
SecurityInformation = DACL_SECURITY_INFORMATION;
if ( FLAG_ON( Options, MSG_TAG_CA ) )
{
SecurityInformation |= SACL_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
OWNER_SECURITY_INFORMATION;
}
dwErr = GetNamedSecurityInfo( pszLDAPObjectPath,
SE_DS_OBJECT_ALL,
SecurityInformation,
NULL,
NULL,
NULL,
NULL,
&pSD );
if( dwErr != ERROR_SUCCESS )
{
if( dwErr == ERROR_FILE_NOT_FOUND )
{
DisplayMessageEx( 0, MSG_INVALID_OBJECT_PATH );
bErrorShown = TRUE;
}
goto CLEAN_RETURN;
}
dwErr = DumpAccess( pSD,
FLAG_ON( Options, MSG_TAG_CA )
);
CLEAN_RETURN:
if ( dwErr == ERROR_SUCCESS )
{
DisplayMessageEx( 0, MSG_DSACLS_SUCCESS );
} else {
if(!bErrorShown)
DisplayErrorMessage( dwErr );
DisplayMessageEx( 0, MSG_DSACLS_FAILURE );
}
//Free Unicode Command Line Arguments
if( wargv )
{
//delete wargv and stuff
for( j = 0; j < argc; ++ j )
{
if( wargv[j] )
LocalFree(wargv[j] );
}
LocalFree( wargv );
}
if( pszObjectPath )
LocalFree( pszObjectPath );
if( pSD )
LocalFree( pSD );
if( pNewDacl )
LocalFree( pNewDacl );
//Free the Global Stuff
for ( j = 0; j < ( sizeof( DsAclsArgs ) / sizeof( DSACLS_ARG ) ); j++ ) {
if( DsAclsArgs[ j ].String )
LocalFree( DsAclsArgs[ j ].String );
}
for ( j = 0; j < ( sizeof( DsAclsInherit ) / sizeof( DSACLS_INHERIT ) ); j++ ) {
if( DsAclsInherit[ j ].String )
LocalFree( DsAclsInherit[ j ].String );
}
for ( j = 0; j < ( sizeof( DsAclsRights ) / sizeof( DSACLS_RIGHTS ) ); j++ ) {
if( DsAclsRights[ j ].String )
LocalFree( DsAclsRights[ j ].String );
if( DsAclsRights[ j ].StringEx )
LocalFree( DsAclsRights[ j ].StringEx );
}
if( pCAclOld )
delete pCAclOld ;
if( pCAclNew )
delete pCAclNew;
if( g_szSchemaNamingContext )
LocalFree( g_szSchemaNamingContext );
if( g_szConfigurationNamingContext )
LocalFree( g_szConfigurationNamingContext );
if( g_szServerName )
LocalFree( g_szServerName );
if( g_Cache )
delete g_Cache;
return( dwErr );
}
DWORD
InitializeGlobalArrays()
{
HMODULE hCurrentModule;
WCHAR LoadBuffer[ 1024 ];
int j = 0;
hCurrentModule = GetModuleHandle( NULL );
for ( j = 0; j < ( sizeof( DsAclsArgs ) / sizeof( DSACLS_ARG )); j++ )
{
long Length = LoadString( hCurrentModule,
DsAclsArgs[ j ].ResourceId,
LoadBuffer,
sizeof( LoadBuffer ) / sizeof ( WCHAR ) - 1 );
if ( Length == 0 )
{
return GetLastError();
} else {
DsAclsArgs[ j ].String = (LPWSTR)LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT,
( Length + 1 )*sizeof(WCHAR) );
if ( !DsAclsArgs[ j ].String )
{
return ERROR_NOT_ENOUGH_MEMORY;
}
DsAclsArgs[ j ].Length = Length;
wcsncpy( DsAclsArgs[ j ].String, LoadBuffer, Length + 1 );
}
}
//
// Load the inherit strings
//
for ( j = 0; j < ( sizeof( DsAclsInherit ) / sizeof( DSACLS_INHERIT ) ); j++ )
{
long Length = LoadString( hCurrentModule,
DsAclsInherit[ j ].ResourceId,
LoadBuffer,
sizeof( LoadBuffer ) / sizeof ( WCHAR ) - 1 );
if ( Length == 0 ) {
return GetLastError();
} else
{
DsAclsInherit[ j ].String = (LPWSTR)LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT,
( Length + 1 ) * sizeof( WCHAR ) );
if ( !DsAclsInherit[ j ].String )
return ERROR_NOT_ENOUGH_MEMORY;
wcsncpy( DsAclsInherit[ j ].String, LoadBuffer, Length + 1 );
DsAclsInherit[ j ].Length = Length;
}
}
//
//Load The protect flags
//
for( j = 0; j < ( sizeof( DsAclsProtect ) / sizeof( DSACLS_PROTECT ) ); j++ )
{
long Length = LoadString( hCurrentModule,
DsAclsProtect[ j ].ResourceId,
LoadBuffer,
sizeof( LoadBuffer ) / sizeof ( WCHAR ) - 1 );
if ( Length == 0 ) {
return GetLastError();
} else
{
DsAclsProtect[ j ].String = (LPWSTR)LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT,
( Length + 1 ) * sizeof( WCHAR ) );
if ( !DsAclsProtect[ j ].String )
return ERROR_NOT_ENOUGH_MEMORY;
wcsncpy( DsAclsProtect[ j ].String, LoadBuffer, Length + 1 );
DsAclsProtect[ j ].Length = Length;
}
}
//
// Load the access rights
//
for ( j = 0; j < ( sizeof( DsAclsRights ) / sizeof( DSACLS_RIGHTS ) ); j++ )
{
long Length = LoadString( hCurrentModule,
DsAclsRights[ j ].ResourceId,
LoadBuffer,
sizeof( LoadBuffer ) / sizeof ( WCHAR ) - 1 );
if ( Length == 0 ) {
return GetLastError();
} else
{
DsAclsRights[ j ].String = (LPWSTR)LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT,
( Length + 1 ) * sizeof( WCHAR ) );
if ( !DsAclsRights[ j ].String ) {
return ERROR_NOT_ENOUGH_MEMORY;
}
wcsncpy( DsAclsRights[ j ].String, LoadBuffer, Length + 1 );
DsAclsRights[ j ].Length = Length;
}
//Load Ex . Ex String are used for displaying the access rights
if( DsAclsRights[ j ].ResourceIdEx != -1 )
{
Length = LoadString( hCurrentModule,
DsAclsRights[ j ].ResourceIdEx,
LoadBuffer,
sizeof( LoadBuffer ) / sizeof ( WCHAR ) - 1 );
if ( Length == 0 ) {
return GetLastError();
} else
{
DsAclsRights[ j ].StringEx = (LPWSTR)LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT,
( Length + 1 ) * sizeof( WCHAR ) );
if ( !DsAclsRights[ j ].StringEx ) {
return ERROR_NOT_ENOUGH_MEMORY;
}
wcsncpy( DsAclsRights[ j ].StringEx, LoadBuffer, Length + 1 );
}
}
}
return ERROR_SUCCESS;
}
/*******************************************************************
NAME: ConvertArgvToUnicode
SYNOPSIS: Converts Command Line Arguments to UNICODE
RETURNS: ERROR_SUCCESS if success
ERROR_NOT_ENOUGH_MEMORY
********************************************************************/
DWORD
ConvertArgvToUnicode( LPWSTR * wargv, char ** argv, int argc )
{
DWORD dwErr = ERROR_SUCCESS;
int i = 0;
for ( i = 0; i < argc ; ++i )
if( ( dwErr = ConvertStringAToStringW( argv[i], wargv + i ) ) != ERROR_SUCCESS )
return dwErr;
return ERROR_SUCCESS;
}
/*
Sets Security Descriptor for pszObject
*/
DWORD
WriteObjectSecurity( IN LPWSTR pszObject,
IN SECURITY_INFORMATION si,
IN PSECURITY_DESCRIPTOR pSD )
{
DWORD dwErr;
SECURITY_DESCRIPTOR_CONTROL wSDControl = 0;
DWORD dwRevision;
PSID psidOwner = NULL;
PSID psidGroup = NULL;
PACL pDacl = NULL;
PACL pSacl = NULL;
BOOL bDefaulted;
BOOL bPresent;
LPWSTR pszLDAPObjectPath = NULL;
if( ( dwErr = BuildLdapPath( &pszLDAPObjectPath,
g_szServerName,
pszObject ) ) != ERROR_SUCCESS )
return dwErr;
//
// Get pointers to various security descriptor parts for
// calling SetNamedSecurityInfo
//
;
if( !GetSecurityDescriptorControl(pSD, &wSDControl, &dwRevision) )
{
return GetLastError();
}
if( !GetSecurityDescriptorOwner(pSD, &psidOwner, &bDefaulted) )
{
return GetLastError();
}
if( !GetSecurityDescriptorGroup(pSD, &psidGroup, &bDefaulted) )
{
return GetLastError();
}
if( !GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefaulted) )
{
return GetLastError();
}
if( !GetSecurityDescriptorSacl(pSD, &bPresent, &pSacl, &bDefaulted) )
{
return GetLastError();
}
if ((si & DACL_SECURITY_INFORMATION) && (wSDControl & SE_DACL_PROTECTED))
si |= PROTECTED_DACL_SECURITY_INFORMATION;
if ((si & SACL_SECURITY_INFORMATION) && (wSDControl & SE_SACL_PROTECTED))
si |= PROTECTED_SACL_SECURITY_INFORMATION;
return SetNamedSecurityInfo( (LPWSTR)pszLDAPObjectPath,
SE_DS_OBJECT_ALL,
si,
psidOwner,
psidGroup,
pDacl,
pSacl);
}
/*******************************************************************
NAME: DisplayAccessRights
SYNOPSIS: Displays Access Rights in Acess Mask
RETURNS: NONE
********************************************************************/
void DisplayAccessRights( UINT nSpace, ACCESS_MASK m_Mask )
{
for ( int j = 0; j < ( sizeof( DsAclsRights ) / sizeof( DSACLS_RIGHTS ) ); j++ )
{
if( FlagOn( m_Mask,DsAclsRights[j].Right ) )
{
DisplayStringWithNewLine( nSpace,DsAclsRights[j].StringEx );
}
}
}
/*******************************************************************
NAME: ConvertAccessMaskToGenericString
SYNOPSIS: Map access mask to FULL CONTROL or SPECIAL
RETURNS: NONE
********************************************************************/
void ConvertAccessMaskToGenericString( ACCESS_MASK m_Mask, LPWSTR szLoadBuffer, UINT nBuffer )
{
szLoadBuffer[0] = 0;
WCHAR szTemp[1024];
if( GENERIC_ALL_MAPPING == ( m_Mask & GENERIC_ALL_MAPPING ) )
{
LoadString( g_hInstance, MSG_TAG_GA_EX, szLoadBuffer, nBuffer );
}
else
{
LoadString( g_hInstance, MSG_DSACLS_SPECIAL, szLoadBuffer, nBuffer );
}
}
/*******************************************************************
NAME: MapGeneric
********************************************************************/
void MapGeneric( ACCESS_MASK * pMask )
{
GENERIC_MAPPING m = DS_GENERIC_MAPPING;
MapGenericMask( pMask, &m );
}
/*******************************************************************
NAME: BuildExplicitAccess
SYNOPSIS: Builds Explicit Access
RETURNS: ERROR_SUCCESS if success
ERROR_NOT_ENOUGH_MEMORY
********************************************************************/
DWORD BuildExplicitAccess( IN PSID pSid,
IN GUID* pGuidObject,
IN GUID* pGuidInherit,
IN ACCESS_MODE AccessMode,
IN ULONG Access,
IN ULONG Inheritance,
OUT PEXPLICIT_ACCESS pExplicitAccess )
{
DWORD dwErr = ERROR_SUCCESS;
PSID pSidLocal = NULL;
DWORD cbSid = 0;
POBJECTS_AND_SID pOAS = NULL;
cbSid = GetLengthSid( pSid );
pSidLocal = (PSID) LocalAlloc( LMEM_FIXED, cbSid );
CHECK_NULL( pSidLocal,FAILURE_RETURN );
CopySid( cbSid,pSidLocal, pSid );
if( pGuidObject || pGuidInherit )
{
pOAS = (POBJECTS_AND_SID)LocalAlloc( LMEM_FIXED, sizeof( OBJECTS_AND_SID ) );
CHECK_NULL( pOAS, FAILURE_RETURN );
BuildTrusteeWithObjectsAndSid( &pExplicitAccess->Trustee,
pOAS,
pGuidObject,
pGuidInherit,
pSidLocal );
}
else
BuildTrusteeWithSid( &pExplicitAccess->Trustee,
pSidLocal );
MapGeneric( &Access );
pExplicitAccess->grfAccessMode = AccessMode;
pExplicitAccess->grfAccessPermissions =Access;
pExplicitAccess->grfInheritance = Inheritance;
goto SUCCESS_RETURN;
FAILURE_RETURN:
if(pSidLocal)
LocalFree(pSidLocal);
if( pOAS )
LocalFree( pOAS );
SUCCESS_RETURN:
return dwErr;
}
/*******************************************************************
NAME: ParseUserAndPermissons
SYNOPSIS: Parses <GROUP\USER>:Access;[object\property];[inheritid]
********************************************************************/
DWORD ParseUserAndPermissons( IN LPWSTR pszArgument,
IN DSACLS_OP Op,
IN ULONG RightsListCount,
IN PDSACLS_RIGHTS RightsList,
OUT LPWSTR * ppszTrusteeName,
OUT PULONG pAccess,
OUT LPWSTR * ppszObjectId,
OUT LPWSTR * ppszInheritId )
{
LPWSTR pszTempString = NULL;
LPWSTR pszTempString2 = NULL;
DWORD dwErr = ERROR_SUCCESS;
ULONG j = 0;
*ppszTrusteeName = NULL;
*pAccess = 0;
*ppszObjectId = NULL;
*ppszInheritId = NULL;
if ( Op != REVOKE )
{
pszTempString = wcschr( pszArgument, L':' );
if ( !pszTempString )
{
dwErr = ERROR_INVALID_PARAMETER;
goto FAILURE_RETURN;
}
*pszTempString = L'\0';
}
dwErr = CopyUnicodeString( ppszTrusteeName, pszArgument );
if ( dwErr != ERROR_SUCCESS )
{
goto FAILURE_RETURN;
}
if ( Op != REVOKE )
{
*pszTempString = L':';
pszTempString++;
// Now, process all of the user rights
*pAccess = 0;
while ( pszTempString && !( *pszTempString == L';' || *pszTempString == L'\0' ) )
{
for ( j = 0; j < RightsListCount; j++ )
{
if ( !_wcsnicmp( pszTempString,
RightsList[ j ].String,
RightsList[ j ].Length ) )
{
*pAccess |= RightsList[ j ].Right;
pszTempString += RightsList[ j ].Length;
break;
}
}
if ( j == RightsListCount )
{
dwErr = ERROR_INVALID_PARAMETER;
goto FAILURE_RETURN;
}
}
if ( *pAccess == 0 )
{
dwErr = ERROR_INVALID_PARAMETER;
goto FAILURE_RETURN;
}
//
// Object id
//
if ( pszTempString && *pszTempString != L'\0' )
{
pszTempString++;
if ( pszTempString && *pszTempString != L';' && *pszTempString != L'\0' )
{
pszTempString2 = wcschr( pszTempString, L';' );
if ( pszTempString2 )
{
*pszTempString2 = L'\0';
}
dwErr = CopyUnicodeString( ppszObjectId,pszTempString );
if ( dwErr != ERROR_SUCCESS )
{
goto FAILURE_RETURN;
}
if ( pszTempString2 )
{
*pszTempString2 = L';';
}
pszTempString = pszTempString2;
}
}
else
*ppszObjectId = NULL;
//
// Inherit id
//
if ( pszTempString && *pszTempString != L'\0' )
{
pszTempString++;
if ( pszTempString && *pszTempString != L'\0' )
{
dwErr = CopyUnicodeString( ppszInheritId,
pszTempString );
if ( dwErr != ERROR_SUCCESS )
{
goto FAILURE_RETURN;
}
}
} else
*ppszInheritId = NULL;
}
FAILURE_RETURN:
if( dwErr != ERROR_SUCCESS )
{
if( *ppszTrusteeName )
{
LocalFree( *ppszTrusteeName );
*ppszTrusteeName = NULL;
}
if( *ppszObjectId )
{
LocalFree( *ppszObjectId );
*ppszObjectId = NULL;
}
if( *ppszInheritId )
{
LocalFree( *ppszInheritId );
*ppszInheritId = NULL;
}
*pAccess = 0;
}
return dwErr;
}