/*++ 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 :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; }