1220 lines
29 KiB
C++
1220 lines
29 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (C) Microsoft Corporation, 1995 - 1997
|
||
|
All rights reserved.
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
prtsec.cxx
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Print queue administration.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Albert Ting (AlbertT) 28-Aug-1995
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
28-Aug-1995 AlbertT Munged from prtq32.c.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.hxx"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "time.hxx"
|
||
|
#include "psetup.hxx"
|
||
|
#include "drvsetup.hxx"
|
||
|
#include "instarch.hxx"
|
||
|
#include "portslv.hxx"
|
||
|
#include "dsinterf.hxx"
|
||
|
#include "prtprop.hxx"
|
||
|
|
||
|
#ifdef SECURITY
|
||
|
#ifndef UNICODE
|
||
|
#error "Acledit entrypoints are Unicode only."
|
||
|
#endif
|
||
|
|
||
|
LPCTSTR gpszAclEdit = TEXT( "acledit.dll" );
|
||
|
|
||
|
LPCSTR gpszSedDiscretionaryAclEditor = "SedDiscretionaryAclEditor";
|
||
|
LPCSTR gpszSedSystemAclEditor = "SedSystemAclEditor";
|
||
|
LPCSTR gpszSedTakeOwnership = "SedTakeOwnership";
|
||
|
|
||
|
|
||
|
HINSTANCE TPrinterSecurity::ghLibraryAcledit;
|
||
|
|
||
|
TPrinterSecurity::PFNSED_DISCRETIONARY_ACL_EDITOR
|
||
|
TPrinterSecurity::gpfnSedDiscretionaryAclEditor;
|
||
|
|
||
|
TPrinterSecurity::PFNSED_SYSTEM_ACL_EDITOR
|
||
|
TPrinterSecurity::gpfnSedSystemAclEditor;
|
||
|
|
||
|
TPrinterSecurity::PFNSED_TAKE_OWNERSHIP
|
||
|
TPrinterSecurity::gpfnSedTakeOwnership;
|
||
|
|
||
|
BOOL TPrinterSecurity::gbStringsLoaded = FALSE;
|
||
|
|
||
|
GENERIC_MAPPING
|
||
|
TPrinterSecurity::gGenericMappingPrinters = {
|
||
|
PRINTER_READ,
|
||
|
PRINTER_WRITE,
|
||
|
PRINTER_EXECUTE,
|
||
|
PRINTER_ALL_ACCESS
|
||
|
};
|
||
|
|
||
|
GENERIC_MAPPING
|
||
|
TPrinterSecurity::gGenericMappingDocuments = {
|
||
|
JOB_READ,
|
||
|
JOB_WRITE,
|
||
|
JOB_EXECUTE,
|
||
|
JOB_ALL_ACCESS
|
||
|
};
|
||
|
|
||
|
SED_HELP_INFO
|
||
|
TPrinterSecurity::gHelpInfoPermissions = {
|
||
|
NULL,
|
||
|
{
|
||
|
ID_HELP_PERMISSIONS_MAIN_DLG,
|
||
|
0,
|
||
|
0,
|
||
|
ID_HELP_PERMISSIONS_ADD_USER_DLG,
|
||
|
ID_HELP_PERMISSIONS_LOCAL_GROUP,
|
||
|
ID_HELP_PERMISSIONS_GLOBAL_GROUP,
|
||
|
ID_HELP_PERMISSIONS_FIND_ACCOUNT
|
||
|
}
|
||
|
};
|
||
|
|
||
|
SED_HELP_INFO
|
||
|
TPrinterSecurity::gHelpInfoAuditing = {
|
||
|
NULL,
|
||
|
{
|
||
|
ID_HELP_AUDITING_MAIN_DLG,
|
||
|
0,
|
||
|
0,
|
||
|
ID_HELP_AUDITING_ADD_USER_DLG,
|
||
|
ID_HELP_AUDITING_LOCAL_GROUP,
|
||
|
ID_HELP_AUDITING_GLOBAL_GROUP,
|
||
|
ID_HELP_AUDITING_FIND_ACCOUNT
|
||
|
}
|
||
|
};
|
||
|
|
||
|
SED_HELP_INFO
|
||
|
TPrinterSecurity::gHelpInfoTakeOwnership = {
|
||
|
NULL,
|
||
|
{
|
||
|
ID_HELP_TAKE_OWNERSHIP
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
SED_OBJECT_TYPE_DESCRIPTOR
|
||
|
TPrinterSecurity::gObjectTypeDescriptor = {
|
||
|
SED_REVISION1, // Revision
|
||
|
TRUE, // IsContainer
|
||
|
TRUE, // AllowNewObjectPerms
|
||
|
TRUE, // MapSpecificPermsToGeneric
|
||
|
&TPrinterSecurity::gGenericMappingPrinters, // GenericMapping
|
||
|
&TPrinterSecurity::gGenericMappingDocuments, // GenericMappingNewObjects
|
||
|
NULL, // ObjectTypeName
|
||
|
NULL, // HelpInfo
|
||
|
NULL, // ApplyToSubContainerTitle
|
||
|
NULL, // ApplyToObjectsTitle
|
||
|
NULL, // ApplyToSubContainerConfirmation
|
||
|
NULL, // SpecialObjectAccessTitle
|
||
|
NULL // SpecialNewObjectAccessTitle
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Application accesses passed to the discretionary ACL editor
|
||
|
// as well as the Take Ownership dialog.
|
||
|
//
|
||
|
SED_APPLICATION_ACCESS
|
||
|
TPrinterSecurity::gpDiscretionaryAccessGroup[TPrinterSecurity::PERMS_COUNT] = {
|
||
|
|
||
|
//
|
||
|
// No Access:
|
||
|
//
|
||
|
{
|
||
|
SED_DESC_TYPE_CONT_AND_NEW_OBJECT, // Type
|
||
|
0, // AccessMask1
|
||
|
0, // AccessMask2
|
||
|
NULL // PermissionTitle
|
||
|
},
|
||
|
|
||
|
//
|
||
|
// Print permission:
|
||
|
//
|
||
|
{
|
||
|
SED_DESC_TYPE_CONT_AND_NEW_OBJECT,
|
||
|
GENERIC_EXECUTE | GENERIC_READ | GENERIC_WRITE,
|
||
|
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
|
||
|
NULL
|
||
|
},
|
||
|
|
||
|
//
|
||
|
// Document Administer permission:
|
||
|
//
|
||
|
{
|
||
|
SED_DESC_TYPE_CONT_AND_NEW_OBJECT,
|
||
|
STANDARD_RIGHTS_READ,
|
||
|
GENERIC_ALL,
|
||
|
NULL
|
||
|
},
|
||
|
|
||
|
//
|
||
|
// Administer permission:
|
||
|
//
|
||
|
{
|
||
|
SED_DESC_TYPE_CONT_AND_NEW_OBJECT,
|
||
|
GENERIC_ALL,
|
||
|
GENERIC_ALL,
|
||
|
NULL
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Application accesses passed to the system ACL editor:
|
||
|
//
|
||
|
SED_APPLICATION_ACCESS
|
||
|
TPrinterSecurity::gpSystemAccessGroup[TPrinterSecurity::PERMS_AUDIT_COUNT] = {
|
||
|
|
||
|
//
|
||
|
// Print permission:
|
||
|
//
|
||
|
{
|
||
|
SED_DESC_TYPE_AUDIT,
|
||
|
PRINTER_ACCESS_USE,
|
||
|
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
|
||
|
NULL
|
||
|
},
|
||
|
|
||
|
{
|
||
|
SED_DESC_TYPE_AUDIT,
|
||
|
PRINTER_ACCESS_ADMINISTER | ACCESS_SYSTEM_SECURITY,
|
||
|
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
|
||
|
NULL
|
||
|
},
|
||
|
|
||
|
{
|
||
|
SED_DESC_TYPE_AUDIT,
|
||
|
DELETE,
|
||
|
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
|
||
|
NULL
|
||
|
},
|
||
|
|
||
|
{
|
||
|
SED_DESC_TYPE_AUDIT,
|
||
|
WRITE_DAC,
|
||
|
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
|
||
|
NULL
|
||
|
},
|
||
|
|
||
|
{
|
||
|
SED_DESC_TYPE_AUDIT,
|
||
|
WRITE_OWNER,
|
||
|
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
|
||
|
NULL
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/********************************************************************
|
||
|
|
||
|
Acquire a single privilege. This routine needs to be rewritten
|
||
|
if multiple privleges are required at once.
|
||
|
|
||
|
********************************************************************/
|
||
|
|
||
|
class TAcquirePrivilege {
|
||
|
|
||
|
SIGNATURE( 'acpr' )
|
||
|
|
||
|
public:
|
||
|
|
||
|
TAcquirePrivilege( LPTSTR pszPrivilegeName );
|
||
|
~TAcquirePrivilege();
|
||
|
|
||
|
BOOL
|
||
|
bValid(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
return _pPrivilegesOld ? TRUE : FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
private:
|
||
|
|
||
|
enum _CONSTANTS {
|
||
|
kPrivilegeSizeHint = 256,
|
||
|
kPrivCount = 1
|
||
|
};
|
||
|
|
||
|
HANDLE _hToken;
|
||
|
PTOKEN_PRIVILEGES _pPrivilegesOld;
|
||
|
};
|
||
|
|
||
|
/********************************************************************
|
||
|
|
||
|
TAcquirePrivilege
|
||
|
|
||
|
********************************************************************/
|
||
|
|
||
|
TAcquirePrivilege::
|
||
|
TAcquirePrivilege(
|
||
|
LPTSTR pszPrivilegeName
|
||
|
) : _hToken( NULL ), _pPrivilegesOld( NULL )
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This adjusts the token to acquire one privilege.
|
||
|
|
||
|
Note: This is efficient only for acquiring a single privilege.
|
||
|
For multiple privileges, this routine should be rewritten
|
||
|
so that the _hToken is reused.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pszPrivilegeName - Privilege string to acquire.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
if( !OpenThreadToken( GetCurrentThread( ),
|
||
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
||
|
TRUE,
|
||
|
&_hToken )){
|
||
|
|
||
|
SPLASSERT( !_hToken );
|
||
|
|
||
|
if( GetLastError() == ERROR_NO_TOKEN ){
|
||
|
|
||
|
//
|
||
|
// This means we are not impersonating anybody.
|
||
|
// Get the token out of the process.
|
||
|
//
|
||
|
if( !OpenProcessToken( GetCurrentProcess( ),
|
||
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
||
|
&_hToken )){
|
||
|
|
||
|
SPLASSERT( !_hToken );
|
||
|
return;
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
SPLASSERT( !_hToken );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We have a valid _hToken at this point.
|
||
|
//
|
||
|
BYTE abyPrivileges[sizeof( TOKEN_PRIVILEGES ) +
|
||
|
(( kPrivCount - 1 ) *
|
||
|
sizeof( LUID_AND_ATTRIBUTES ))];
|
||
|
|
||
|
PTOKEN_PRIVILEGES pPrivilegesNew;
|
||
|
|
||
|
pPrivilegesNew = (PTOKEN_PRIVILEGES)abyPrivileges;
|
||
|
ZeroMemory( abyPrivileges, sizeof( abyPrivileges ));
|
||
|
|
||
|
if( !LookupPrivilegeValue( NULL,
|
||
|
pszPrivilegeName,
|
||
|
&pPrivilegesNew->Privileges[0].Luid )){
|
||
|
|
||
|
DBGMSG( DBG_WARN,
|
||
|
( "AcquirePrivilege.ctr: LookupPrivilegeValue failed: %d\n",
|
||
|
GetLastError( )));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Save previous privileges.
|
||
|
//
|
||
|
DWORD cbPrivilegesOld = kPrivilegeSizeHint;
|
||
|
TStatusB bStatus;
|
||
|
|
||
|
Retry:
|
||
|
|
||
|
_pPrivilegesOld = (PTOKEN_PRIVILEGES)AllocMem( cbPrivilegesOld );
|
||
|
|
||
|
if( !_pPrivilegesOld ){
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set up the privilege set we will need.
|
||
|
//
|
||
|
pPrivilegesNew->PrivilegeCount = kPrivCount;
|
||
|
//
|
||
|
// Luid set above.
|
||
|
//
|
||
|
pPrivilegesNew->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||
|
|
||
|
bStatus DBGCHK = AdjustTokenPrivileges( _hToken,
|
||
|
FALSE,
|
||
|
pPrivilegesNew,
|
||
|
cbPrivilegesOld,
|
||
|
_pPrivilegesOld,
|
||
|
&cbPrivilegesOld );
|
||
|
|
||
|
if( !bStatus ){
|
||
|
|
||
|
FreeMem( _pPrivilegesOld );
|
||
|
_pPrivilegesOld = NULL;
|
||
|
|
||
|
if( GetLastError() == ERROR_INSUFFICIENT_BUFFER ){
|
||
|
goto Retry;
|
||
|
}
|
||
|
|
||
|
DBGMSG( DBG_WARN,
|
||
|
( "AcquirePrivilege.ctr: AdjustTokenPrivileges failed: Error %d\n",
|
||
|
GetLastError( )));
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// _pPrivilegesOld is our valid check.
|
||
|
//
|
||
|
}
|
||
|
|
||
|
TAcquirePrivilege::
|
||
|
~TAcquirePrivilege(
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Restore privileges and free buffer.
|
||
|
|
||
|
_hToken needs to be close if it is non-NULL. _pPrivilegeOld
|
||
|
is our valid check.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
if( _pPrivilegesOld ){
|
||
|
|
||
|
TStatusB bStatus;
|
||
|
|
||
|
bStatus DBGCHK = AdjustTokenPrivileges( _hToken,
|
||
|
FALSE,
|
||
|
_pPrivilegesOld,
|
||
|
0,
|
||
|
NULL,
|
||
|
NULL );
|
||
|
FreeMem( _pPrivilegesOld );
|
||
|
}
|
||
|
|
||
|
if( _hToken ){
|
||
|
CloseHandle( _hToken );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/********************************************************************
|
||
|
|
||
|
Security.
|
||
|
|
||
|
********************************************************************/
|
||
|
|
||
|
BOOL
|
||
|
TPrinterSecurity::
|
||
|
bInitStrings(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// Check whether the strings have been loaded.
|
||
|
//
|
||
|
if( gbStringsLoaded == TRUE ){
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gbStringsLoaded = TRUE;
|
||
|
|
||
|
gHelpInfoPermissions.pszHelpFileName = (LPTSTR)gszWindowsHlp;
|
||
|
gHelpInfoAuditing.pszHelpFileName = (LPTSTR)gszWindowsHlp;
|
||
|
gHelpInfoTakeOwnership.pszHelpFileName = (LPTSTR)gszWindowsHlp;
|
||
|
|
||
|
gObjectTypeDescriptor.ObjectTypeName =
|
||
|
pszLoadString( ghInst, IDS_PRINTER );
|
||
|
|
||
|
gpDiscretionaryAccessGroup[PERMS_NOACC].PermissionTitle =
|
||
|
pszLoadString( ghInst, IDS_SEC_NOACCESS );
|
||
|
|
||
|
gpDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle =
|
||
|
pszLoadString( ghInst, IDS_SEC_PRINT );
|
||
|
|
||
|
gpDiscretionaryAccessGroup[PERMS_DOCAD].PermissionTitle =
|
||
|
pszLoadString( ghInst, IDS_SEC_ADMINISTERDOCUMENTS );
|
||
|
|
||
|
gpDiscretionaryAccessGroup[PERMS_ADMIN].PermissionTitle =
|
||
|
pszLoadString( ghInst, IDS_SEC_ADMINISTER );
|
||
|
|
||
|
gpSystemAccessGroup[PERMS_AUDIT_PRINT].PermissionTitle =
|
||
|
pszLoadString( ghInst, IDS_SEC_AUDIT_PRINT );
|
||
|
|
||
|
gpSystemAccessGroup[PERMS_AUDIT_ADMINISTER].PermissionTitle =
|
||
|
pszLoadString( ghInst, IDS_SEC_AUDIT_ADMINISTER );
|
||
|
|
||
|
gpSystemAccessGroup[PERMS_AUDIT_DELETE].PermissionTitle =
|
||
|
pszLoadString( ghInst, IDS_SEC_AUDIT_DELETE );
|
||
|
|
||
|
gpSystemAccessGroup[PERMS_AUDIT_CHANGE_PERMISSIONS].PermissionTitle =
|
||
|
pszLoadString( ghInst, IDS_SEC_CHANGE_PERMISSIONS );
|
||
|
|
||
|
gpSystemAccessGroup[PERMS_AUDIT_TAKE_OWNERSHIP].PermissionTitle =
|
||
|
pszLoadString( ghInst, IDS_SEC_TAKE_OWNERSHIP );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
TPrinterSecurity::
|
||
|
bHandleMessage(
|
||
|
UINT uMsg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
switch( uMsg ){
|
||
|
case WM_INITDIALOG:
|
||
|
|
||
|
if( !bInitStrings( )){
|
||
|
DBGMSG( DBG_ERROR,
|
||
|
( "PrinterSecurity.bHandlMessage: InitStrings failed %d\n",
|
||
|
GetLastError( )));
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_HELP:
|
||
|
case WM_CONTEXTMENU:
|
||
|
return PrintUIHelp( uMsg, _hDlg, wParam, lParam );
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
|
||
|
switch( GET_WM_COMMAND_ID( wParam, lParam )){
|
||
|
case IDC_SEC_PERMS:
|
||
|
|
||
|
vCallDiscretionaryAclEditor();
|
||
|
break;
|
||
|
|
||
|
case IDC_SEC_AUDIT:
|
||
|
|
||
|
vCallSystemAclEditor();
|
||
|
break;
|
||
|
|
||
|
case IDC_SEC_OWNER:
|
||
|
|
||
|
vCallTakeOwnershipDialog();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/********************************************************************
|
||
|
|
||
|
Load the dll.
|
||
|
|
||
|
********************************************************************/
|
||
|
|
||
|
BOOL
|
||
|
TPrinterSecurity::
|
||
|
bLoadAcledit(
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Loads acledit and sets pfns.
|
||
|
|
||
|
Note: Not multithread safe, no unloading done.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE = success, FALSE = error.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
if( ghLibraryAcledit ){
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
ghLibraryAcledit = LoadLibrary( gpszAclEdit );
|
||
|
|
||
|
if( !ghLibraryAcledit ){
|
||
|
goto Fail;
|
||
|
}
|
||
|
|
||
|
gpfnSedDiscretionaryAclEditor =
|
||
|
(PFNSED_DISCRETIONARY_ACL_EDITOR)GetProcAddress(
|
||
|
ghLibraryAcledit,
|
||
|
gpszSedDiscretionaryAclEditor );
|
||
|
|
||
|
gpfnSedSystemAclEditor =
|
||
|
(PFNSED_SYSTEM_ACL_EDITOR)GetProcAddress(
|
||
|
ghLibraryAcledit,
|
||
|
gpszSedSystemAclEditor );
|
||
|
|
||
|
gpfnSedTakeOwnership =
|
||
|
(PFNSED_TAKE_OWNERSHIP)GetProcAddress(
|
||
|
ghLibraryAcledit,
|
||
|
gpszSedTakeOwnership );
|
||
|
|
||
|
if( !gpfnSedDiscretionaryAclEditor ||
|
||
|
!gpfnSedSystemAclEditor ||
|
||
|
!gpfnSedTakeOwnership ){
|
||
|
|
||
|
FreeLibrary( ghLibraryAcledit );
|
||
|
ghLibraryAcledit = NULL;
|
||
|
goto Fail;
|
||
|
}
|
||
|
return TRUE;
|
||
|
|
||
|
Fail:
|
||
|
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/********************************************************************
|
||
|
|
||
|
Bring up each of the dialogs.
|
||
|
|
||
|
********************************************************************/
|
||
|
|
||
|
VOID
|
||
|
TPrinterSecurity::
|
||
|
vCallDiscretionaryAclEditor(
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Edit access privileges of print queue.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
HANDLE hPrinterWriteDac = NULL;;
|
||
|
DWORD dwAccess = WRITE_DAC;
|
||
|
SED_APPLICATION_ACCESSES ApplicationAccesses;
|
||
|
DWORD SedStatus;
|
||
|
TStatusB bStatus;
|
||
|
TStatus Status;
|
||
|
|
||
|
Status DBGNOCHK = 0;
|
||
|
|
||
|
PPRINTER_INFO_3 pInfo3 = NULL;
|
||
|
DWORD cbInfo3 = 0;
|
||
|
|
||
|
if( !bLoadAcledit( )){
|
||
|
goto Fail;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the security descriptor.
|
||
|
//
|
||
|
if( !_pPrinterData->hPrinter( )){
|
||
|
|
||
|
Status DBGCHK = ERROR_ACCESS_DENIED;
|
||
|
goto Fail;
|
||
|
}
|
||
|
|
||
|
bStatus DBGCHK = VDataRefresh::bGetPrinter( _pPrinterData->hPrinter(),
|
||
|
3,
|
||
|
(PVOID*)&pInfo3,
|
||
|
&cbInfo3 );
|
||
|
if( !bStatus ){
|
||
|
|
||
|
SPLASSERT( !pInfo3 );
|
||
|
|
||
|
Status DBGCHK = GetLastError();
|
||
|
goto Fail;
|
||
|
}
|
||
|
|
||
|
SECURITY_CONTEXT SecurityContext;
|
||
|
|
||
|
Status DBGCHK = TPrinter::sOpenPrinter( _pPrinterData->strPrinterName(),
|
||
|
&dwAccess,
|
||
|
&hPrinterWriteDac );
|
||
|
if( Status == ERROR_SUCCESS){
|
||
|
SPLASSERT( hPrinterWriteDac );
|
||
|
SecurityContext.hPrinter = hPrinterWriteDac;
|
||
|
} else {
|
||
|
SPLASSERT( !hPrinterWriteDac );
|
||
|
SecurityContext.hPrinter = _pPrinterData->hPrinter();
|
||
|
}
|
||
|
|
||
|
SecurityContext.SecurityInformation = DACL_SECURITY_INFORMATION;
|
||
|
SecurityContext.pPrinterSecurity = this;
|
||
|
|
||
|
//
|
||
|
// Pass all the permissions to the ACL editor,
|
||
|
// and set up the type required:
|
||
|
//
|
||
|
ApplicationAccesses.Count = PERMS_COUNT;
|
||
|
ApplicationAccesses.AccessGroup = gpDiscretionaryAccessGroup;
|
||
|
ApplicationAccesses.DefaultPermName =
|
||
|
gpDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle;
|
||
|
|
||
|
COUNT i;
|
||
|
for( i = 0; i < PERMS_COUNT; ++i ){
|
||
|
ApplicationAccesses.AccessGroup[i].Type =
|
||
|
SED_DESC_TYPE_CONT_AND_NEW_OBJECT;
|
||
|
}
|
||
|
|
||
|
SED_OBJECT_TYPE_DESCRIPTOR Descriptor = gObjectTypeDescriptor;
|
||
|
|
||
|
Descriptor.AllowNewObjectPerms = TRUE;
|
||
|
Descriptor.HelpInfo = &gHelpInfoPermissions;
|
||
|
|
||
|
Status DBGCHK = (*gpfnSedDiscretionaryAclEditor)(
|
||
|
_hDlg,
|
||
|
ghInst,
|
||
|
(LPTSTR)(LPCTSTR)_pPrinterData->strServerName(),
|
||
|
&Descriptor,
|
||
|
&ApplicationAccesses,
|
||
|
(LPTSTR)(LPCTSTR)_pPrinterData->strPrinterName(),
|
||
|
SedCallback2,
|
||
|
(DWORD)&SecurityContext,
|
||
|
pInfo3->pSecurityDescriptor,
|
||
|
FALSE,
|
||
|
(BOOLEAN)!hPrinterWriteDac,
|
||
|
&SedStatus,
|
||
|
0 );
|
||
|
|
||
|
Fail:
|
||
|
|
||
|
if( Status ){
|
||
|
SetLastError( Status );
|
||
|
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Close the printer use to write the Dac.
|
||
|
//
|
||
|
if( hPrinterWriteDac ){
|
||
|
ClosePrinter( hPrinterWriteDac );
|
||
|
}
|
||
|
|
||
|
FreeMem( pInfo3 );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
TPrinterSecurity::
|
||
|
vCallSystemAclEditor(
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Edit auditing properties of print queue.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
HANDLE hPrinterSystemAccess = NULL;
|
||
|
SED_APPLICATION_ACCESSES ApplicationAccesses;
|
||
|
DWORD SedStatus;
|
||
|
TStatusB bStatus;
|
||
|
TStatus Status;
|
||
|
|
||
|
Status DBGNOCHK = 0;
|
||
|
|
||
|
if( !bLoadAcledit( )){
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
TAcquirePrivilege AcquirePrivilege( SE_SECURITY_NAME );
|
||
|
|
||
|
if( !VALID_OBJ( AcquirePrivilege )){
|
||
|
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DWORD dwAccess = ACCESS_SYSTEM_SECURITY;
|
||
|
Status DBGCHK = TPrinter::sOpenPrinter(
|
||
|
_pPrinterData->strPrinterName(),
|
||
|
&dwAccess,
|
||
|
&hPrinterSystemAccess );
|
||
|
|
||
|
if( Status != ERROR_SUCCESS ){
|
||
|
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the security descriptor.
|
||
|
//
|
||
|
PPRINTER_INFO_3 pInfo3 = NULL;
|
||
|
DWORD cbInfo3 = 0;
|
||
|
|
||
|
bStatus DBGCHK = VDataRefresh::bGetPrinter( hPrinterSystemAccess,
|
||
|
3,
|
||
|
(PVOID*)&pInfo3,
|
||
|
&cbInfo3 );
|
||
|
if( !bStatus ){
|
||
|
Status DBGCHK = GetLastError();
|
||
|
goto Fail;
|
||
|
}
|
||
|
|
||
|
SECURITY_CONTEXT SecurityContext;
|
||
|
|
||
|
SecurityContext.SecurityInformation = SACL_SECURITY_INFORMATION;
|
||
|
SecurityContext.pPrinterSecurity = this;
|
||
|
|
||
|
SPLASSERT( hPrinterSystemAccess );
|
||
|
SecurityContext.hPrinter = hPrinterSystemAccess;
|
||
|
|
||
|
//
|
||
|
// Pass only the Print and Administer permissions to the ACL editor,
|
||
|
// and set up the type required:
|
||
|
//
|
||
|
ApplicationAccesses.Count = PERMS_AUDIT_COUNT;
|
||
|
ApplicationAccesses.AccessGroup = gpSystemAccessGroup;
|
||
|
ApplicationAccesses.DefaultPermName =
|
||
|
gpDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle;
|
||
|
|
||
|
SED_OBJECT_TYPE_DESCRIPTOR Descriptor = gObjectTypeDescriptor;
|
||
|
|
||
|
Descriptor.AllowNewObjectPerms = FALSE;
|
||
|
Descriptor.HelpInfo = &gHelpInfoAuditing;
|
||
|
|
||
|
Status DBGCHK = (*gpfnSedSystemAclEditor)(
|
||
|
_hDlg,
|
||
|
ghInst,
|
||
|
(LPTSTR)(LPCTSTR)_pPrinterData->strServerName(),
|
||
|
&Descriptor,
|
||
|
&ApplicationAccesses,
|
||
|
(LPTSTR)(LPCTSTR)_pPrinterData->strPrinterName(),
|
||
|
SedCallback2,
|
||
|
(DWORD)&SecurityContext,
|
||
|
pInfo3->pSecurityDescriptor,
|
||
|
FALSE,
|
||
|
&SedStatus,
|
||
|
0 );
|
||
|
|
||
|
Fail:
|
||
|
|
||
|
if( Status ){
|
||
|
SetLastError( Status );
|
||
|
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
|
||
|
}
|
||
|
|
||
|
FreeMem( pInfo3 );
|
||
|
|
||
|
if( hPrinterSystemAccess ){
|
||
|
ClosePrinter( hPrinterSystemAccess );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
TPrinterSecurity::
|
||
|
vCallTakeOwnershipDialog(
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Edit ownership of print queue.
|
||
|
|
||
|
How does a user get to this dialog if they can't get properties
|
||
|
on a printer?
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
SED_APPLICATION_ACCESSES ApplicationAccesses;
|
||
|
DWORD SedStatus;
|
||
|
TStatusB bStatus;
|
||
|
TStatus Status;
|
||
|
HANDLE hPrinterWriteOwner = NULL;
|
||
|
|
||
|
Status DBGNOCHK = 0;
|
||
|
|
||
|
if( !bLoadAcledit( )){
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the security descriptor.
|
||
|
//
|
||
|
PPRINTER_INFO_3 pInfo3 = NULL;
|
||
|
DWORD cbInfo3 = 0;
|
||
|
|
||
|
//
|
||
|
// Attempt to retrieve the previous owner.
|
||
|
//
|
||
|
if( _pPrinterData->hPrinter( )){
|
||
|
|
||
|
bStatus DBGCHK = VDataRefresh::bGetPrinter( _pPrinterData->hPrinter(),
|
||
|
3,
|
||
|
(PVOID*)&pInfo3,
|
||
|
&cbInfo3 );
|
||
|
}
|
||
|
|
||
|
{
|
||
|
TAcquirePrivilege AcquirePrivilege( SE_TAKE_OWNERSHIP_NAME );
|
||
|
SECURITY_CONTEXT SecurityContext;
|
||
|
DWORD dwAccess = WRITE_OWNER;
|
||
|
|
||
|
Status DBGCHK = TPrinter::sOpenPrinter( _pPrinterData->strPrinterName(),
|
||
|
&dwAccess,
|
||
|
&hPrinterWriteOwner );
|
||
|
if( Status == ERROR_SUCCESS){
|
||
|
SPLASSERT( hPrinterWriteOwner );
|
||
|
SecurityContext.hPrinter = hPrinterWriteOwner;
|
||
|
} else {
|
||
|
SPLASSERT( !hPrinterWriteOwner );
|
||
|
SecurityContext.hPrinter = _pPrinterData->hPrinter();
|
||
|
}
|
||
|
|
||
|
SecurityContext.SecurityInformation = OWNER_SECURITY_INFORMATION;
|
||
|
SecurityContext.pPrinterSecurity = this;
|
||
|
|
||
|
ApplicationAccesses.Count = PERMS_COUNT;
|
||
|
ApplicationAccesses.AccessGroup = gpDiscretionaryAccessGroup;
|
||
|
ApplicationAccesses.DefaultPermName =
|
||
|
gpDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle;
|
||
|
|
||
|
COUNT i;
|
||
|
for( i = 0; i < PERMS_COUNT; ++i ){
|
||
|
ApplicationAccesses.AccessGroup[i].Type = SED_DESC_TYPE_AUDIT;
|
||
|
}
|
||
|
|
||
|
BOOL bCantReadOwner;
|
||
|
PSECURITY_DESCRIPTOR pSecurityDescriptor;
|
||
|
|
||
|
bCantReadOwner = pInfo3 ? FALSE : TRUE;
|
||
|
pSecurityDescriptor = pInfo3 ?
|
||
|
pInfo3->pSecurityDescriptor :
|
||
|
NULL;
|
||
|
TString strPrinter;
|
||
|
bStatus DBGCHK = strPrinter.bLoadString( ghInst, IDS_PRINTER );
|
||
|
|
||
|
Status DBGCHK = (*gpfnSedTakeOwnership)(
|
||
|
_hDlg,
|
||
|
ghInst,
|
||
|
(LPTSTR)(LPCTSTR)_pPrinterData->strServerName(),
|
||
|
(LPTSTR)(LPCTSTR)strPrinter,
|
||
|
(LPTSTR)(LPCTSTR)_pPrinterData->strPrinterName(),
|
||
|
1,
|
||
|
SedCallback2,
|
||
|
(DWORD)&SecurityContext,
|
||
|
pSecurityDescriptor,
|
||
|
(BOOLEAN)bCantReadOwner,
|
||
|
(BOOLEAN)!hPrinterWriteOwner,
|
||
|
&SedStatus,
|
||
|
&gHelpInfoTakeOwnership,
|
||
|
0 );
|
||
|
}
|
||
|
|
||
|
if( hPrinterWriteOwner ){
|
||
|
ClosePrinter( hPrinterWriteOwner );
|
||
|
}
|
||
|
|
||
|
FreeMem( pInfo3 );
|
||
|
}
|
||
|
|
||
|
|
||
|
/********************************************************************
|
||
|
|
||
|
Security callback routine.
|
||
|
|
||
|
********************************************************************/
|
||
|
|
||
|
DWORD
|
||
|
TPrinterSecurity::
|
||
|
SedCallback2(
|
||
|
HWND hwndParent,
|
||
|
HANDLE hInstance,
|
||
|
DWORD dwCallBackContext,
|
||
|
PSECURITY_DESCRIPTOR psdUpdated,
|
||
|
PSECURITY_DESCRIPTOR pSecDescNewObjects,
|
||
|
BOOLEAN bApplyToSubContainers,
|
||
|
BOOLEAN bApplyToSubObjects,
|
||
|
LPDWORD pdwStatusReturn
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Called by acledit to process writes.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
<insert>.
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
<insert>.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER( pdwStatusReturn );
|
||
|
UNREFERENCED_PARAMETER( bApplyToSubObjects );
|
||
|
UNREFERENCED_PARAMETER( bApplyToSubContainers );
|
||
|
UNREFERENCED_PARAMETER( pSecDescNewObjects );
|
||
|
UNREFERENCED_PARAMETER( hInstance );
|
||
|
UNREFERENCED_PARAMETER( hwndParent );
|
||
|
|
||
|
PSECURITY_CONTEXT pSecurityContext;
|
||
|
SECURITY_DESCRIPTOR SecurityDescriptorNew;
|
||
|
PSECURITY_DESCRIPTOR pSelfRelativeSD = NULL;
|
||
|
DWORD cbSelfRelativeSD;
|
||
|
|
||
|
TStatusB bStatus;
|
||
|
|
||
|
pSecurityContext = (PSECURITY_CONTEXT)dwCallBackContext;
|
||
|
SPLASSERT( pSecurityContext->hPrinter );
|
||
|
|
||
|
if( InitializeSecurityDescriptor( &SecurityDescriptorNew,
|
||
|
SECURITY_DESCRIPTOR_REVISION1 ) &&
|
||
|
BuildNewSecurityDescriptor( &SecurityDescriptorNew,
|
||
|
pSecurityContext->SecurityInformation,
|
||
|
psdUpdated )){
|
||
|
|
||
|
pSelfRelativeSD = AllocCopySecurityDescriptor( &SecurityDescriptorNew,
|
||
|
&cbSelfRelativeSD );
|
||
|
} else {
|
||
|
|
||
|
DBGMSG( DBG_ERROR, ( "PrinterSecurity.SedCallback2: InitializeSD failedt %d\n",
|
||
|
GetLastError( )));
|
||
|
}
|
||
|
|
||
|
if( !pSelfRelativeSD ){
|
||
|
|
||
|
DBGMSG( DBG_WARN,
|
||
|
( "PrinterSecurity.SedCallback2: Alloc copy sd failed %d\n",
|
||
|
GetLastError( )));
|
||
|
|
||
|
SPLASSERT( GetLastError( ));
|
||
|
|
||
|
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
|
||
|
return GetLastError();
|
||
|
}
|
||
|
|
||
|
PRINTER_INFO_3 PrinterInfo3;
|
||
|
|
||
|
PrinterInfo3.pSecurityDescriptor = pSelfRelativeSD;
|
||
|
|
||
|
bStatus DBGCHK = SetPrinter( pSecurityContext->hPrinter,
|
||
|
3,
|
||
|
(PBYTE)&PrinterInfo3,
|
||
|
0 );
|
||
|
//
|
||
|
// Free the newly created sd.
|
||
|
//
|
||
|
FreeMem( pSelfRelativeSD );
|
||
|
|
||
|
if( !bStatus ){
|
||
|
|
||
|
SPLASSERT( GetLastError( ));
|
||
|
|
||
|
iMessage( NULL,
|
||
|
IDS_ERR_PRINTER_PROP_TITLE,
|
||
|
IDS_ERR_SAVE_PRINTER,
|
||
|
MB_OK|MB_ICONHAND,
|
||
|
kMsgGetLastError,
|
||
|
NULL );
|
||
|
|
||
|
return GetLastError();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Refresh the property page set.
|
||
|
//
|
||
|
pSecurityContext->pPrinterSecurity->vReloadPages();
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
/********************************************************************
|
||
|
|
||
|
Helpers.
|
||
|
|
||
|
********************************************************************/
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
TPrinterSecurity::
|
||
|
BuildNewSecurityDescriptor(
|
||
|
PSECURITY_DESCRIPTOR psdNew,
|
||
|
SECURITY_INFORMATION SecurityInformation,
|
||
|
PSECURITY_DESCRIPTOR psdUpdated
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Builds new security desriptor.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
BOOL bDefaulted = FALSE;
|
||
|
PSID pOwnerSid = NULL;
|
||
|
PSID pGroupSid = NULL;
|
||
|
BOOL bDaclPresent = FALSE;
|
||
|
PACL pDacl = NULL;
|
||
|
BOOL bSaclPresent = FALSE;
|
||
|
PACL pSacl = NULL;
|
||
|
TStatusB bStatus;
|
||
|
|
||
|
switch( SecurityInformation ){
|
||
|
case OWNER_SECURITY_INFORMATION:
|
||
|
|
||
|
if( GetSecurityDescriptorOwner( psdUpdated,
|
||
|
&pOwnerSid,
|
||
|
&bDefaulted )){
|
||
|
|
||
|
bStatus DBGCHK = SetSecurityDescriptorOwner( psdNew,
|
||
|
pOwnerSid,
|
||
|
bDefaulted );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DACL_SECURITY_INFORMATION:
|
||
|
|
||
|
if( GetSecurityDescriptorDacl( psdUpdated,
|
||
|
&bDaclPresent,
|
||
|
&pDacl,
|
||
|
&bDefaulted )) {
|
||
|
|
||
|
bStatus DBGCHK = SetSecurityDescriptorDacl( psdNew,
|
||
|
bDaclPresent,
|
||
|
pDacl,
|
||
|
bDefaulted );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case SACL_SECURITY_INFORMATION:
|
||
|
|
||
|
if( GetSecurityDescriptorSacl( psdUpdated,
|
||
|
&bSaclPresent,
|
||
|
&pSacl,
|
||
|
&bDefaulted )) {
|
||
|
|
||
|
bStatus DBGCHK = SetSecurityDescriptorSacl( psdNew,
|
||
|
bSaclPresent,
|
||
|
pSacl,
|
||
|
bDefaulted );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
|
||
|
DBGMSG( DBG_ERROR, ( "PrinterSecurity.BuildSD: Unknown type %d\n",
|
||
|
SecurityInformation ));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return bStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
PSECURITY_DESCRIPTOR
|
||
|
TPrinterSecurity::
|
||
|
AllocCopySecurityDescriptor(
|
||
|
IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
||
|
OUT PDWORD pdwLength
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Alloc copy of security descriptor.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pSecurityDescriptor - sd to copy.
|
||
|
|
||
|
pdwLength - Output length.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Newly allocated sd. NULL if failed.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PSECURITY_DESCRIPTOR psdCopy;
|
||
|
DWORD dwLength;
|
||
|
|
||
|
dwLength = GetSecurityDescriptorLength(pSecurityDescriptor);
|
||
|
|
||
|
psdCopy = AllocMem( dwLength );
|
||
|
|
||
|
if( psdCopy ){
|
||
|
|
||
|
MakeSelfRelativeSD( pSecurityDescriptor,
|
||
|
psdCopy,
|
||
|
&dwLength);
|
||
|
|
||
|
*pdwLength = dwLength;
|
||
|
}
|
||
|
|
||
|
return psdCopy;
|
||
|
}
|
||
|
|
||
|
#endif // def SECURITY
|