|
|
//Copyright (c) 1998 - 1999 Microsoft Corporation
/*******************************************************************************
* * security.c * * WinStation ACL editing functions (based on code from NT PRINTMAN security.c) * * copyright notice: Copyright 1995, Citrix Systems Inc. * * $Author: donm $ Butch Davis * * $Log: N:\nt\private\utils\citrix\winutils\tscfg\VCS\security.c $ * * Rev 1.12 19 Mar 1998 16:38:40 donm * was looking for old help file * * Rev 1.11 20 Sep 1996 20:37:18 butchd * update * * Rev 1.10 19 Sep 1996 15:58:44 butchd * update * * Rev 1.9 12 Sep 1996 16:16:38 butchd * update * *******************************************************************************/
/*
* We must compile for UNICODE because of ACL edit structures & interface, which * is UNICODE-only. */ #ifndef UNICODE
#define UNICODE 1
#endif
#ifndef _UNICODE
#define _UNICODE 1
#endif
/*
* include files */ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tchar.h>
#include <wchar.h>
#include <sedapi.h>
#include <winsta.h>
#include "defines.h"
#include "resource.h"
#include "security.h"
#include "common.h"
#include <utildll.h>
/*
* Global variables for WINUTILS Common functions. */ LPCTSTR WinUtilsAppName; HWND WinUtilsAppWindow; HINSTANCE WinUtilsAppInstance;
////////////////////////////////////////////////////////////////////////////////
// typedefs, defines, persistant storage, and private function prototypes
/*
* Indexes into the APPLICATION_ACCESSES structure: */ #define PERMS_SPECIAL_QUERY 0 /* query information access */
#define PERMS_SPECIAL_SET 1 /* set information access */
#define PERMS_SPECIAL_RESET 2 /* reset access */
#define PERMS_SPECIAL_SHADOW 3 /* shadow access */
#define PERMS_SPECIAL_LOGON 4 /* logon access */
#define PERMS_SPECIAL_LOGOFF 5 /* logoff access */
#define PERMS_SPECIAL_MSG 6 /* message access */
#define PERMS_SPECIAL_CONNECT 7 /* connect access */
#define PERMS_SPECIAL_DISCONNECT 8 /* disconnect access */
#define PERMS_SPECIAL_DELETE 9 /* delete access */
#define PERMS_RESOURCE_NOACCESS 10 /* no access grouping */
#define PERMS_RESOURCE_GUEST 11 /* guest access grouping */
#define PERMS_RESOURCE_USER 12 /* user access grouping */
#define PERMS_RESOURCE_ADMIN 13 /* all (admin) access grouping */
#define PERMS_COUNT 14 /* Total number of permissions */
/*
* Typedefs and static storage. */ typedef struct _SECURITY_CONTEXT { PWINSTATIONNAME pWSName; } SECURITY_CONTEXT, *PSECURITY_CONTEXT;
/*
* We need this structure even though we're not doing generic access mapping. */ GENERIC_MAPPING GenericMapping = { /* GenericMapping: */ GENERIC_READ, /* GenericRead */ GENERIC_WRITE, /* GenericWrite */ GENERIC_EXECUTE, /* GenericExecute */ GENERIC_ALL /* GenericAll */ };
WCHAR szLWinCfgHlp[] = L"TSCFG.HLP"; TCHAR szAclEdit[] = TEXT("ACLEDIT"); /* DLL containing ACL Edit Dialog */ char szSedDiscretionaryAclEditor[] = "SedDiscretionaryAclEditor";
LPWSTR pwstrWinStation = NULL; LPWSTR pwstrSpecial = NULL;
#define IDD_BASE 0x20000 // makehelp.bat uses this base offset to form HIDD_ symbol
SED_HELP_INFO PermissionsHelpInfo = { /* HelpInfo */ szLWinCfgHlp, IDD_HELP_PERMISSIONS_MAIN+IDD_BASE, IDD_HELP_PERMISSIONS_SPECIAL_ACCESS+IDD_BASE, 0, IDD_HELP_PERMISSIONS_ADD_USER+IDD_BASE, IDD_HELP_PERMISSIONS_LOCAL_GROUP+IDD_BASE, IDD_HELP_PERMISSIONS_GLOBAL_GROUP+IDD_BASE, IDD_HELP_PERMISSIONS_FIND_ACCOUNT+IDD_BASE };
SED_OBJECT_TYPE_DESCRIPTOR ObjectTypeDescriptor = { SED_REVISION1, /* Revision */ FALSE, /* IsContainer */ FALSE, /* AllowNewObjectPerms */ FALSE, /* MapSpecificPermsToGeneric */ &GenericMapping, /* GenericMapping */ NULL, /* GenericMappingNewObjects */ NULL, /* ObjectTypeName */ NULL, /* HelpInfo */ NULL, /* ApplyToSubContainerTitle */ NULL, /* ApplyToObjectsTitle */ NULL, /* ApplyToSubContainerConfirmation */ NULL, /* SpecialObjectAccessTitle */ NULL /* SpecialNewObjectAccessTitle */ };
/*
* Application accesses passed to the discretionary ACL editor. */ SED_APPLICATION_ACCESS pDiscretionaryAccessGroup[PERMS_COUNT] = { /* query (Special...)
*/ { SED_DESC_TYPE_RESOURCE_SPECIAL, /* Type */ WINSTATION_QUERY, /* AccessMask1 */ 0, /* AccessMask2 */ NULL /* PermissionTitle */ },
/* set (Special...)
*/ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_SET, 0, NULL },
/* reset (Special...)
*/ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_RESET, 0, NULL },
/* shadow (Special...)
*/ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_SHADOW, 0, NULL },
/* logon (Special...)
*/ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_LOGON, 0, NULL },
/* logoff (Special...)
*/ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_LOGOFF, 0, NULL },
/* message (Special...)
*/ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_MSG, 0, NULL },
/* connect (Special...)
*/ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_CONNECT, 0, NULL },
/* disconnect (Special...)
*/ { SED_DESC_TYPE_RESOURCE_SPECIAL, WINSTATION_DISCONNECT, 0, NULL },
/* delete (Special...)
*/ { SED_DESC_TYPE_RESOURCE_SPECIAL, DELETE, 0, NULL },
/* no access (grouping):
*/ { SED_DESC_TYPE_RESOURCE, 0, 0, NULL },
/* guest access (grouping)
*/ { SED_DESC_TYPE_RESOURCE, WINSTATION_GUEST_ACCESS, 0, NULL },
/* user access (grouping)
*/ { SED_DESC_TYPE_RESOURCE, WINSTATION_USER_ACCESS, 0, NULL },
/* administrator access (grouping)
*/ { SED_DESC_TYPE_RESOURCE, GENERIC_ALL, // maps to WINSTATION_ALL_ACCESS on WinStationOpen()
0, NULL } };
#define PRIV_SECURITY 0
#define PRIV_COUNT 1
LUID SecurityValue;
/*
* Definitions from SEDAPI.H: * (unfortunately we have to do this if we want to link dynamically) */ typedef DWORD (WINAPI *SED_DISCRETIONARY_ACL_EDITOR)( HWND Owner, HANDLE Instance, LPWSTR Server, PSED_OBJECT_TYPE_DESCRIPTOR ObjectType, PSED_APPLICATION_ACCESSES ApplicationAccesses, LPWSTR ObjectName, PSED_FUNC_APPLY_SEC_CALLBACK ApplySecurityCallbackRoutine, ULONG CallbackContext, PSECURITY_DESCRIPTOR SecurityDescriptor, BOOLEAN CouldntReadDacl, BOOLEAN CantWriteDacl, LPDWORD SEDStatusReturn, DWORD Flags );
SED_DISCRETIONARY_ACL_EDITOR lpfnSedDiscretionaryAclEditor = NULL;
/*
* Private function prototypes (public prototypes are in security.h). */ DWORD SetWinStationSecurity( PWINSTATIONNAME pWSName, PSECURITY_DESCRIPTOR pSecurityDescriptor ); DWORD ValidateSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor); FARPROC LoadLibraryGetProcAddress( HWND hwnd, LPTSTR LibraryName, LPCSTR ProcName, PHANDLE phLibrary ); void InitializeSecurityStrings( ); VOID ReportSecurityFailure(HWND hwnd, DWORD ErrorResource, LPCTSTR String, DWORD Error); LPVOID AllocSplMem( DWORD cb ); BOOL FreeSplMem( LPVOID pMem ); LPWSTR GetUnicodeString( int id ); DWORD WINAPI SedCallback( HWND hwndParent, HANDLE hInstance, ULONG CallBackContext, PSECURITY_DESCRIPTOR pNewSecurityDescriptor, PSECURITY_DESCRIPTOR pSecDescNewObjects, BOOLEAN ApplyToSubContainers, BOOLEAN ApplyToSubObjects, LPDWORD StatusReturn );
////////////////////////////////////////////////////////////////////////////////
// public functions
/*******************************************************************************
* * CallPermissionsDialog (public function) * * Call the SedDiscretionaryAclEditor() function in ACLEDIT dll. * * ENTRY: * hwnd (input) * window handle of parent for ACL edit dialog. * bAdmin (input) * TRUE if user is an Administrator (can write to WinStation registry) * FALSE otherwise (permissions will be read-only). * pWSName (input) * Name of WinStation to edit security for. * EXIT: * (BOOL) TRUE if any winstations were modified; FALSE otherwise. * ******************************************************************************/
BOOL CallPermissionsDialog( HWND hwnd, BOOL bAdmin, PWINSTATIONNAME pWSName ) { SECURITY_CONTEXT SecurityContext; BOOLEAN CantWriteDacl; SED_APPLICATION_ACCESSES ApplicationAccesses; HANDLE hLibrary; PSECURITY_DESCRIPTOR pSecurityDescriptor; DWORD Status = SED_STATUS_NOT_MODIFIED; DWORD Error; HCURSOR hOldCursor;
hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
/*
* Get the current WinStation security */ if ( (Error = GetWinStationSecurity(pWSName, &pSecurityDescriptor)) != ERROR_SUCCESS ) {
ReportSecurityFailure( hwnd, IDP_ERROR_GET_SECURITY_WINSTATION, pWSName, Error );
SetCursor(hOldCursor); return(FALSE); }
/*
* If we're not allowed access to write to WinStation registry, flag such. */ CantWriteDacl = !(BOOL)bAdmin;
if( !lpfnSedDiscretionaryAclEditor ) lpfnSedDiscretionaryAclEditor = (SED_DISCRETIONARY_ACL_EDITOR)LoadLibraryGetProcAddress( hwnd, szAclEdit, szSedDiscretionaryAclEditor, &hLibrary);
if( lpfnSedDiscretionaryAclEditor ) { InitializeSecurityStrings( );
ObjectTypeDescriptor.ObjectTypeName = pwstrWinStation;
/*
* Pass all the permissions to the ACL editor, * and set up the type required: */ ApplicationAccesses.Count = PERMS_COUNT; ApplicationAccesses.AccessGroup = pDiscretionaryAccessGroup; ApplicationAccesses.DefaultPermName = pDiscretionaryAccessGroup[PERMS_RESOURCE_USER].PermissionTitle;
ObjectTypeDescriptor.HelpInfo = &PermissionsHelpInfo; ObjectTypeDescriptor.SpecialObjectAccessTitle = pwstrSpecial;
SecurityContext.pWSName = pWSName; Error = (*lpfnSedDiscretionaryAclEditor ) (hwnd, NULL, NULL, &ObjectTypeDescriptor, &ApplicationAccesses, pWSName, (PSED_FUNC_APPLY_SEC_CALLBACK)SedCallback, (ULONG)&SecurityContext, pSecurityDescriptor, FALSE, CantWriteDacl, &Status, 0);
if( Error != ERROR_SUCCESS ) ReportSecurityFailure(hwnd, IDP_ERROR_PERMISSIONS_EDITOR_FAILED, NULL, Error); }
SetCursor(hOldCursor); LocalFree(pSecurityDescriptor);
return( ((Status == SED_STATUS_NOT_MODIFIED) || (Status == SED_STATUS_NOT_ALL_MODIFIED)) ? FALSE : TRUE );
} // end CallPermissionsDialog
/*******************************************************************************
* * GetWinStationSecurityA (public function - ANSI stub) * * (see GetWinStationSecurityW) * * ENTRY: * (see GetWinStationSecurityW) * EXIT: * (see GetWinStationSecurityW) * ******************************************************************************/
DWORD GetWinStationSecurityA( PWINSTATIONNAMEA pWSName, PSECURITY_DESCRIPTOR *ppSecurityDescriptor ) { WINSTATIONNAMEW WSNameW;
/*
* Copy ANSI WinStation name to UNICODE and call GetWinStationNameW(). */ mbstowcs(WSNameW, pWSName, sizeof(WSNameW));
return( GetWinStationSecurityW(WSNameW, ppSecurityDescriptor) );
} // GetWinStationSecurityA
/*******************************************************************************
* * GetWinStationSecurityW (public function - UNICODE) * * Obtain the security descriptor for the specified WinStation. If the * WinStation does not have a security descriptor associated with it, * will quietly call GetDefaultWinStationSecurity() to get the default * security descriptor for it. * * ENTRY: * pWSName (input) * UNICODE name of WinStation to get security descriptor for. * ppSecurityDescriptor (output) * on success, set to pointer to allocated memory containing the * WinStation's security descriptor. * EXIT: * ERROR_SUCCESS if all is OK; error code and *pSecurityDescriptor set to * NULL if error. * * NOTE: on success, the memory pointed to by *ppSecurityDescriptor should be * LocalFree()'d by the caller when the security descriptor is no longer * needed. * ******************************************************************************/
DWORD GetWinStationSecurityW( PWINSTATIONNAMEW pWSName, PSECURITY_DESCRIPTOR *ppSecurityDescriptor ) { DWORD Error, SDLength, SDLengthRequired;
*ppSecurityDescriptor = NULL; if ( (Error = RegWinStationQuerySecurity( SERVERNAME_CURRENT, pWSName, NULL, 0, &SDLengthRequired )) == ERROR_INSUFFICIENT_BUFFER ) {
if ( !(*ppSecurityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc( 0, SDLength = SDLengthRequired)) ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
} else {
Error = RegWinStationQuerySecurity( SERVERNAME_CURRENT, pWSName, *ppSecurityDescriptor, SDLength, &SDLengthRequired ); }
} else {
/*
* Unexpected error. If 'not found', fetch the default WinStation SD. */ if ( Error == ERROR_FILE_NOT_FOUND ) return( GetDefaultWinStationSecurity(ppSecurityDescriptor) ); }
/*
* Check for a valid SD before returning. */ if ( Error == ERROR_SUCCESS ) {
Error = ValidateSecurityDescriptor(*ppSecurityDescriptor);
} else if ( *ppSecurityDescriptor ) {
LocalFree(*ppSecurityDescriptor); *ppSecurityDescriptor = NULL; }
return(Error);
} // GetWinStationSecurityW
/*******************************************************************************
* * GetDefaultWinStationSecurity (public function) * * Obtain the default WinStation security descriptor. * * ENTRY: * ppSecurityDescriptor (output) * on success, set to pointer to allocated memory containing the * default WinStation security descriptor. * EXIT: * ERROR_SUCCESS if all is OK; error code and *pSecurityDescriptor set to * NULL if error. * * NOTE: on success, the memory pointed to by *ppSecurityDescriptor should be * LocalFree()'d by the caller when the security descriptor is no longer * needed. * ******************************************************************************/
DWORD GetDefaultWinStationSecurity( PSECURITY_DESCRIPTOR *ppSecurityDescriptor ) { DWORD Error, SDLength, SDLengthRequired;
*ppSecurityDescriptor = NULL; if ( (Error = RegWinStationQueryDefaultSecurity( SERVERNAME_CURRENT, NULL, 0, &SDLengthRequired )) == ERROR_INSUFFICIENT_BUFFER ) {
if ( !(*ppSecurityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc( 0, SDLength = SDLengthRequired)) ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
} else {
Error = RegWinStationQueryDefaultSecurity( SERVERNAME_CURRENT, *ppSecurityDescriptor, SDLength, &SDLengthRequired ); } }
/*
* Check for a valid SD before returning. */ if ( Error == ERROR_SUCCESS ) {
Error = ValidateSecurityDescriptor(*ppSecurityDescriptor);
} else if ( *ppSecurityDescriptor ) {
LocalFree(*ppSecurityDescriptor); *ppSecurityDescriptor = NULL; }
return(Error);
} // GetDefaultWinStationSecurity
/*******************************************************************************
* * FreeSecurityStrings (public function) * * Free allocated memory for ACL edit string resources. This function * should be called when the application exits. * * ENTRY: * EXIT: * ******************************************************************************/
void FreeSecurityStrings( ) { /*
* Only perform free if the strings have been allocated and loaded. */ if( pwstrWinStation ) { FreeSplMem(pwstrWinStation); FreeSplMem(pwstrSpecial);
FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_QUERY].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_SET].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_RESET].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_SHADOW].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGON].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGOFF].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_MSG].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_CONNECT].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_DISCONNECT].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_DELETE].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_NOACCESS].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_GUEST].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_USER].PermissionTitle); FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_ADMIN].PermissionTitle); }
} // end FreeSecurityStrings
////////////////////////////////////////////////////////////////////////////////
// private functions
/*******************************************************************************
* * InitializeSecurityStrings (private function) * * Allocate and load ACL editing string resources if not done already. * The application should call the public FreeSecurityStrings() function * to free allocated memory when the application exits. * * ENTRY: * EXIT: * ******************************************************************************/
void InitializeSecurityStrings() { if( !pwstrWinStation ) { pwstrWinStation = GetUnicodeString(IDS_WINSTATION); pwstrSpecial = GetUnicodeString(IDS_SPECIALACCESS);
pDiscretionaryAccessGroup[PERMS_SPECIAL_QUERY].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_QUERY);
pDiscretionaryAccessGroup[PERMS_SPECIAL_SET].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_SET);
pDiscretionaryAccessGroup[PERMS_SPECIAL_RESET].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_RESET);
pDiscretionaryAccessGroup[PERMS_SPECIAL_SHADOW].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_SHADOW);
pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGON].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_LOGON);
pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGOFF].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_LOGOFF);
pDiscretionaryAccessGroup[PERMS_SPECIAL_MSG].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_MSG);
pDiscretionaryAccessGroup[PERMS_SPECIAL_CONNECT].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_CONNECT);
pDiscretionaryAccessGroup[PERMS_SPECIAL_DISCONNECT].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_DISCONNECT);
pDiscretionaryAccessGroup[PERMS_SPECIAL_DELETE].PermissionTitle = GetUnicodeString(IDS_PERMS_SPECIAL_DELETE);
pDiscretionaryAccessGroup[PERMS_RESOURCE_NOACCESS].PermissionTitle = GetUnicodeString(IDS_PERMS_RESOURCE_NOACCESS);
pDiscretionaryAccessGroup[PERMS_RESOURCE_GUEST].PermissionTitle = GetUnicodeString(IDS_PERMS_RESORUCE_GUEST);
pDiscretionaryAccessGroup[PERMS_RESOURCE_USER].PermissionTitle = GetUnicodeString(IDS_PERMS_RESORUCE_USER);
pDiscretionaryAccessGroup[PERMS_RESOURCE_ADMIN].PermissionTitle = GetUnicodeString(IDS_PERMS_RESOURCE_ADMIN); }
} // end InitializeSecurityStrings
/*******************************************************************************
* * ReportSecurityFailure (private function) * * Output an appropriate error message for security failure. * * ENTRY: * hwnd (input) * window handle of parent for message box. * ErrorResource (input) * resource ID of error format string. * String (input) * If not NULL, points to string to output as part of message. * Error (input) * Error code * EXIT: * * NOTE: all ErrorResource format strings should specify a %d for Error code * and %S for system error message string as the last two substitution * arguments. The %S is optional, and must be present in the format * string if the String argument is non-NULL. * ******************************************************************************/
VOID ReportSecurityFailure(HWND hwnd, DWORD ErrorResource, LPCTSTR String, DWORD Error) { HWND hwndSave = WinUtilsAppWindow;
/*
* Set parent window in WinUtilsAppWindow global for use * by STANDARD_ERROR_MESSAGE macro (StandardErrorMessage function). */ WinUtilsAppWindow = hwnd;
if ( String ) STANDARD_ERROR_MESSAGE((WINAPPSTUFF, LOGONID_NONE, Error, ErrorResource, String)) else STANDARD_ERROR_MESSAGE((WINAPPSTUFF, LOGONID_NONE, Error, ErrorResource))
/*
* Restore original WinUtilsAppWindow to global. */ WinUtilsAppWindow = hwndSave;
} // end ReportSecurityFailure
/*******************************************************************************
* * SedCallback (private function) * * Callback function from ACL edit dialog DLL * * ENTRY: * (see sedapi.h) * EXIT: * (see sedapi.h) * ******************************************************************************/
DWORD WINAPI SedCallback( HWND hwndParent, HANDLE hInstance, ULONG CallBackContext, PSECURITY_DESCRIPTOR pUpdatedSecurityDescriptor, PSECURITY_DESCRIPTOR pSecDescNewObjects, BOOLEAN ApplyToSubContainers, BOOLEAN ApplyToSubObjects, LPDWORD StatusReturn ) { WINSTATIONNAME WSName; PSECURITY_CONTEXT pSecurityContext; DWORD Error; BOOL OK = TRUE;
pSecurityContext = (PSECURITY_CONTEXT)CallBackContext;
/*
* Apply security to the WinStation. */ lstrcpy(WSName, pSecurityContext->pWSName); if ( (Error = SetWinStationSecurity( WSName, pUpdatedSecurityDescriptor)) != ERROR_SUCCESS ) {
ReportSecurityFailure( hwndParent, IDP_ERROR_SET_SECURITY_WINSTATION, WSName, Error ); OK = FALSE; *StatusReturn = SED_STATUS_NOT_ALL_MODIFIED; }
if ( OK == TRUE ) *StatusReturn = SED_STATUS_MODIFIED;
return( OK ? 0 : 1 );
} // end SedCallback
/*******************************************************************************
* * LoadLibraryGetProcAddress (private function) * * Load the specified library and retrieve FARPROC pointer to specified * procedure's entry point. * * ENTRY: * hwnd (input) * window handle of owner for error message display * LibraryName (input) * name of library dll to load * ProcName (input) * name of library procedure to reference * phLibrary (output) * set to handle of loaded library on return * EXIT: * FARPROC pointer to library procedure's entry point. * ******************************************************************************/
FARPROC LoadLibraryGetProcAddress( HWND hwnd, LPTSTR LibraryName, LPCSTR ProcName, PHANDLE phLibrary ) { HANDLE hLibrary; FARPROC lpfn = NULL;
hLibrary = LoadLibrary(LibraryName);
if ( hLibrary ) {
lpfn = GetProcAddress(hLibrary, ProcName);
if(!lpfn) {
ERROR_MESSAGE(( IDP_ERROR_COULDNOTFINDPROCEDURE, ProcName, LibraryName )) FreeLibrary(hLibrary); }
} else ERROR_MESSAGE((IDP_ERROR_COULDNOTLOADLIBRARY, LibraryName))
*phLibrary = hLibrary;
return(lpfn);
} // end LoadLibraryGetProcAddress
/*******************************************************************************
* * AllocSplMem (private function) * * Allocate and zero-fill specified amount of memory. * * ENTRY: * cb (input) * number of bytes to allocate * EXIT: * LPVOID pointer to allocated memory; NULL if error. * ******************************************************************************/
LPVOID AllocSplMem( DWORD cb ) { return(LocalAlloc(LPTR, cb));
} // end AllocSplMem
/*******************************************************************************
* * FreeSplMem (private function) * * Free the specified memory block. * * ENTRY: * pMem (input) * memory to free * EXIT: * TRUE if sucess; FALSE if error. * ******************************************************************************/
BOOL FreeSplMem( LPVOID pMem ) { return( LocalFree((HLOCAL)pMem) == NULL );
} // end FreeSplMem
/*******************************************************************************
* * GetUnicodeString (private function) * * Load a resource string and allocate/save in memory block. * * ENTRY: * id (input) * resource id of string to get * EXIT: * pointer to allocated and loaded UNICODE string * ******************************************************************************/
LPWSTR GetUnicodeString(int id) { WCHAR ResString[256]; DWORD length = 0; LPWSTR pUnicode; DWORD cbUnicode;
length = LoadStringW(NULL, id, ResString, 256);
cbUnicode = (length * sizeof(WCHAR)) + sizeof(WCHAR); pUnicode = AllocSplMem(cbUnicode);
if( pUnicode ) memcpy(pUnicode, ResString, cbUnicode);
return(pUnicode);
} // end GetUnicodeString
/*******************************************************************************
* * ValidateSecurityDescriptor (private function) * * Check the specified security descriptor for valid structure as well as * valid ACLs and SIDs. * * ENTRY: * pSecurityDescriptor (input) * Security descriptor to validate. * EXIT: * ERROR_SUCCESS if valid; error otherwise. * ******************************************************************************/
DWORD ValidateSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor) { DWORD Error = ERROR_SUCCESS;
if ( !IsValidSecurityDescriptor(pSecurityDescriptor) ) {
Error = GetLastError();
} else {
BOOL bAclPresent, bDefaulted; PACL pACL; PSID pSID;
for ( ; ; ) {
if ( !GetSecurityDescriptorDacl( pSecurityDescriptor, &bAclPresent, &pACL, &bDefaulted ) ) { Error = GetLastError(); break; } if ( bAclPresent && pACL ) if ( !IsValidAcl(pACL) ) { Error = GetLastError(); break; }
if ( !GetSecurityDescriptorSacl( pSecurityDescriptor, &bAclPresent, &pACL, &bDefaulted ) ) { Error = GetLastError(); break; } if ( bAclPresent && pACL ) if ( !IsValidAcl(pACL) ) { Error = GetLastError(); break; }
if ( !GetSecurityDescriptorOwner( pSecurityDescriptor, &pSID, &bDefaulted ) ) { Error = GetLastError(); break; } if ( pSID ) if ( !IsValidSid(pSID) ) { Error = GetLastError(); break; }
if ( !GetSecurityDescriptorGroup( pSecurityDescriptor, &pSID, &bDefaulted ) ) { Error = GetLastError(); break; } if ( pSID ) if ( !IsValidSid(pSID) ) { Error = GetLastError(); break; }
break; } }
return(Error);
} // end ValidateSecurityDescriptor
/*******************************************************************************
* * SetWinStationSecurity (private function) * * Set the specified WinStation's registry and kernel object security. * * ENTRY: * pWSName (input) * Name of WinStation to set security for. * pSecurityDescriptor (input) * Security descriptor to set for winstation. * EXIT: * ERROR_SUCCESS if valid; error otherwise. * ******************************************************************************/
DWORD SetWinStationSecurity( PWINSTATIONNAME pWSName, PSECURITY_DESCRIPTOR pSecurityDescriptor ) { DWORD Error = ERROR_SUCCESS;
Error = RegWinStationSetSecurity( SERVERNAME_CURRENT, pWSName, pSecurityDescriptor, GetSecurityDescriptorLength(pSecurityDescriptor) );
return(Error);
} // SetWinStationSecurity
|