windows-nt/Source/XPSP1/NT/termsrv/admtools/winutils/tscfg/security.c

1065 lines
32 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//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