Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

809 lines
22 KiB

//
// ISecurityInformation interface implementation
//
#include <aclui.h>
#include "faxui.h"
class CFaxSecurity : public ISecurityInformation
{
protected:
ULONG m_cRef;
STDMETHOD(MakeSelfRelativeCopy)(PSECURITY_DESCRIPTOR psdOriginal,
PSECURITY_DESCRIPTOR* ppsdNew);
public:
CFaxSecurity() : m_cRef(1) {}
virtual ~CFaxSecurity() {}
// IUnknown methods
STDMETHOD(QueryInterface)(REFIID, LPVOID *);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
// ISecurityInformation methods
STDMETHOD(GetObjectInformation)(PSI_OBJECT_INFO pObjectInfo);
STDMETHOD(GetSecurity)(SECURITY_INFORMATION si,
PSECURITY_DESCRIPTOR *ppSD,
BOOL fDefault);
STDMETHOD(SetSecurity)(SECURITY_INFORMATION si,
PSECURITY_DESCRIPTOR pSD);
STDMETHOD(GetAccessRights)(const GUID* pguidObjectType,
DWORD dwFlags,
PSI_ACCESS *ppAccess,
ULONG *pcAccesses,
ULONG *piDefaultAccess);
STDMETHOD(MapGeneric)(const GUID *pguidObjectType,
UCHAR *pAceFlags,
ACCESS_MASK *pmask);
STDMETHOD(GetInheritTypes)(PSI_INHERIT_TYPE *ppInheritTypes,
ULONG *pcInheritTypes);
STDMETHOD(PropertySheetPageCallback)(HWND hwnd,
UINT uMsg,
SI_PAGE_TYPE uPage);
};
CFaxSecurity* g_pFaxSecurity = NULL;
///////////////////////////////////////////////////////////
//
// IUnknown methods
//
///////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG)
CFaxSecurity::AddRef()
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG)
CFaxSecurity::Release()
{
if (--m_cRef == 0)
{
delete this;
g_pFaxSecurity = NULL;
return 0;
}
return m_cRef;
}
STDMETHODIMP
CFaxSecurity::QueryInterface(REFIID riid, LPVOID FAR* ppv)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ISecurityInformation))
{
*ppv = (LPSECURITYINFO)this;
m_cRef++;
return S_OK;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
}
///////////////////////////////////////////////////////////
//
// ISecurityInformation methods
//
///////////////////////////////////////////////////////////
STDMETHODIMP
CFaxSecurity::GetObjectInformation(PSI_OBJECT_INFO pObjectInfo)
// *** ISecurityInformation methods implementation ***
/*
- CFaxSecurity::GetObjectInformation
-
* Purpose:
* Performs an access check against the fax service security descriptor
*
* Arguments:
* [in] pObjectInfo - pointer to object information structure.
*
* Return:
* OLE error code
*/
{
DWORD ec = ERROR_SUCCESS;
if(!Connect(NULL, FALSE))
{
return S_FALSE;
}
HANDLE hPrivBeforeSE_TAKE_OWNERSHIP = INVALID_HANDLE_VALUE;
HANDLE hPrivBeforeSE_SECURITY = INVALID_HANDLE_VALUE;
if( pObjectInfo == NULL )
{
Error(("Invalid parameter - pObjectInfo == NULL\n"));
Assert( pObjectInfo != NULL );
return E_POINTER;
}
//
// Set Flags
//
pObjectInfo->dwFlags = SI_EDIT_ALL |
SI_NO_TREE_APPLY |
SI_NO_ACL_PROTECT |
SI_ADVANCED |
SI_PAGE_TITLE;
//
// Check if to add SI_READONLY
//
if (!FaxAccessCheckEx(g_hFaxSvcHandle, WRITE_DAC, NULL))
{
ec = GetLastError();
if (ERROR_SUCCESS == ec)
{
pObjectInfo->dwFlags |= SI_READONLY;
}
else
{
Error(("FaxAccessCheckEx(WRITE_DAC) failed with %d \n", ec));
goto exit;
}
}
//
// Check if to add SI_OWNER_READONLY
//
hPrivBeforeSE_TAKE_OWNERSHIP = EnablePrivilege (SE_TAKE_OWNERSHIP_NAME);
//
// No error checking - If we failed we will get ERROR_ACCESS_DENIED in the access check
//
if (!FaxAccessCheckEx(g_hFaxSvcHandle,WRITE_OWNER, NULL))
{
ec = GetLastError();
if (ERROR_SUCCESS == ec)
{
pObjectInfo->dwFlags |= SI_OWNER_READONLY;
}
else
{
Error(("FaxAccessCheckEx(WRITE_OWNER) failed with %d \n", ec));
goto exit;
}
}
//
// Check if to remove SI_EDIT_AUDITS
//
hPrivBeforeSE_SECURITY = EnablePrivilege (SE_SECURITY_NAME);
//
// No error checking - If we failed we will get ERROR_ACCESS_DENIED in the access check
//
if (!FaxAccessCheckEx(g_hFaxSvcHandle, ACCESS_SYSTEM_SECURITY, NULL))
{
ec = GetLastError();
if (ERROR_SUCCESS == ec)
{
pObjectInfo->dwFlags &= ~SI_EDIT_AUDITS;
}
else
{
Error(("FaxAccessCheckEx(ACCESS_SYSTEM_SECURITY) failed with %d \n", ec));
goto exit;
}
}
//
// Set all other fields
//
static TCHAR tszPageTitle[MAX_PATH] = {0};
if(LoadString((HINSTANCE)g_hResource, IDS_SECURITY_TITLE, tszPageTitle, ARR_SIZE(tszPageTitle)))
{
pObjectInfo->pszPageTitle = tszPageTitle;
}
else
{
ec = GetLastError();
Error(("LoadString(IDS_SECURITY_TITLE) failed with %d \n", ec));
pObjectInfo->pszPageTitle = NULL;
}
static TCHAR tszPrinterName[MAX_PATH] = {0};
if(GetFirstLocalFaxPrinterName(tszPrinterName, ARR_SIZE(tszPrinterName)))
{
pObjectInfo->pszObjectName = tszPrinterName;
}
else
{
ec = GetLastError();
Error(("GetFirstLocalFaxPrinterName() failed with %d \n", ec));
pObjectInfo->pszObjectName = NULL;
}
pObjectInfo->hInstance = (HINSTANCE)g_hResource;
pObjectInfo->pszServerName = NULL;
exit:
ReleasePrivilege (hPrivBeforeSE_SECURITY);
ReleasePrivilege (hPrivBeforeSE_TAKE_OWNERSHIP);
return HRESULT_FROM_WIN32(ec);
} // CFaxSecurity::GetObjectInformation
STDMETHODIMP
CFaxSecurity::GetSecurity(SECURITY_INFORMATION si,
PSECURITY_DESCRIPTOR* ppSD,
BOOL fDefault)
/*
- CFaxSecurityInformation::GetSecurity
-
* Purpose:
* requests a security descriptor for the securable object whose
* security descriptor is being edited. The access control editor
* calls this method to retrieve the object's current or default security descriptor.
*
* Arguments:
* [in] RequestedInformation - security information.
* [out] ppSecurityDescriptor - pointer to security descriptor.
* [in] fDefault - not implemented
*
* Return:
* OLE error code
*/
{
HRESULT hRc = S_OK;
DWORD ec = ERROR_SUCCESS;
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
HANDLE hPrivBeforeSE_SECURITY = INVALID_HANDLE_VALUE;
Assert(ppSD);
if(!Connect(NULL, FALSE))
{
return S_FALSE;
}
if( fDefault == TRUE )
{
Error(("Non implemeted feature -> fDefault == TRUE\n"));
return E_NOTIMPL;
}
if (si & SACL_SECURITY_INFORMATION)
{
hPrivBeforeSE_SECURITY = EnablePrivilege (SE_SECURITY_NAME);
}
//
// Get the current relative descriptor from the fax server
//
if(!FaxGetSecurityEx(g_hFaxSvcHandle, si, &pSecurityDescriptor))
{
ec = GetLastError();
Error(("FaxGetSecurityEx() failed with %d\n", ec));
hRc = HRESULT_FROM_WIN32(ec);
goto exit;
}
//
// return a self relative descriptor copy allocated with LocalAlloc()
//
hRc = MakeSelfRelativeCopy( pSecurityDescriptor, ppSD );
if( FAILED( hRc ) )
{
Error(("MakeSelfRelativeCopy() failed with %08X\n", hRc));
goto exit;
}
Assert(S_OK == hRc);
exit:
if (pSecurityDescriptor)
{
FaxFreeBuffer(pSecurityDescriptor);
}
ReleasePrivilege (hPrivBeforeSE_SECURITY);
return hRc;
} // CFaxSecurity::GetSecurity
STDMETHODIMP
CFaxSecurity::SetSecurity(SECURITY_INFORMATION si,
PSECURITY_DESCRIPTOR pSD)
/*
- CFaxSecurityInformation::SetSecurity
-
* Purpose:
* Provides a security descriptor containing the security information
* the user wants to apply to the securable object. The access control
* editor calls this method when the user clicks the Okay or Apply buttons.
*
* Arguments:
* [in] SecurityInformation - security information structure.
* [in] pSecurityDescriptor - pointer to security descriptor.
*
* Return:
* OLE error code
*/
{
HRESULT hRc = S_OK;
DWORD ec = ERROR_SUCCESS;
PSECURITY_DESCRIPTOR psdSelfRelativeCopy = NULL;
HANDLE hPrivBeforeSE_TAKE_OWNERSHIP = INVALID_HANDLE_VALUE;
HANDLE hPrivBeforeSE_SECURITY = INVALID_HANDLE_VALUE;
Assert(pSD);
Assert( IsValidSecurityDescriptor( pSD ));
if(!Connect(NULL, FALSE))
{
return S_FALSE;
}
//
// Prepare self relative descriptor
//
hRc = MakeSelfRelativeCopy( pSD, &psdSelfRelativeCopy );
if( FAILED( hRc ) )
{
Error(("MakeSelfRelativeCopy() failed with %08X\n", hRc));
goto exit;
}
if (si & OWNER_SECURITY_INFORMATION)
{
hPrivBeforeSE_TAKE_OWNERSHIP = EnablePrivilege (SE_TAKE_OWNERSHIP_NAME);
}
if (si & SACL_SECURITY_INFORMATION)
{
hPrivBeforeSE_SECURITY = EnablePrivilege (SE_SECURITY_NAME);
}
//
// save the new relative descriptor to the fax server
//
if(!FaxSetSecurity(g_hFaxSvcHandle, si, psdSelfRelativeCopy))
{
ec = GetLastError();
Error(("FaxSetSecurity() failed with %d\n", ec));
hRc = HRESULT_FROM_WIN32(ec);
goto exit;
}
Assert( S_OK == hRc || E_ACCESSDENIED == hRc);
exit:
if (psdSelfRelativeCopy)
{
::LocalFree(psdSelfRelativeCopy);
}
ReleasePrivilege (hPrivBeforeSE_SECURITY);
ReleasePrivilege (hPrivBeforeSE_TAKE_OWNERSHIP);
return hRc;
} // CFaxSecurity::SetSecurity
STDMETHODIMP
CFaxSecurity::GetAccessRights(const GUID* pguidObjectType,
DWORD dwFlags,
PSI_ACCESS* ppAccess,
ULONG* pcAccesses,
ULONG* piDefaultAccess)
/*
- CFaxSecurityInformation::GetAccessRights
-
* Purpose:
* Requests information about the access rights that can be
* controlled for a securable object. The access control
* editor calls this method to retrieve display strings and
* other information used to initialize the property pages.
*
* Arguments:
* [in] pguidObjectType - Pointer to a GUID structure that
* identifies the type of object for which
* access rights are being requested.
* [in] dwFlags - A set of bit flags that indicate the property
* page being initialized
* [out] ppAccess - Pointer to a variable that you should
* set to a pointer to an array of SI_ACCESS
* structures.
* [out] pcAccesses - Pointer to a variable that you should set
* to indicate the number of entries in the ppAccess array.
* [out] piDefaultAccess - Pointer to a variable that you should set
* to indicate the zero-based index of the array entry that contains
* the default access rights.
* The access control editor uses this entry as the initial access rights in a new ACE.
*
* Return:
* OLE error code
*/
{
Assert( ppAccess );
Assert( pcAccesses );
Assert( piDefaultAccess );
//
// Access rights for the Basic security page
//
static SI_ACCESS siFaxBasicAccess[] =
{
// 0 Fax
{
&GUID_NULL,
FAX_ACCESS_SUBMIT_HIGH | FAX_ACCESS_SUBMIT_NORMAL | FAX_ACCESS_SUBMIT | FAX_ACCESS_QUERY_IN_ARCHIVE,
MAKEINTRESOURCE(IDS_RIGHT_FAX),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 1 Manage fax configuration
{
&GUID_NULL,
FAX_ACCESS_MANAGE_CONFIG | FAX_ACCESS_QUERY_CONFIG,
MAKEINTRESOURCE(IDS_RIGHT_MNG_CFG),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 2 Manage fax documents
{
&GUID_NULL,
FAX_ACCESS_MANAGE_JOBS | FAX_ACCESS_QUERY_JOBS |
FAX_ACCESS_MANAGE_IN_ARCHIVE | FAX_ACCESS_QUERY_IN_ARCHIVE |
FAX_ACCESS_MANAGE_OUT_ARCHIVE | FAX_ACCESS_QUERY_OUT_ARCHIVE,
MAKEINTRESOURCE(IDS_RIGHT_MNG_DOC),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
}
};
//
// Access rights for the Advanced security page
//
static SI_ACCESS siFaxAccess[] =
{
// 0 submit permission
{
&GUID_NULL,
FAX_ACCESS_SUBMIT ,
MAKEINTRESOURCE(IDS_FAXSEC_SUB_LOW),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 1 submit normal permission
{
&GUID_NULL,
FAX_ACCESS_SUBMIT_NORMAL ,
MAKEINTRESOURCE(IDS_FAXSEC_SUB_NORMAL),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 2 submit high permission
{
&GUID_NULL,
FAX_ACCESS_SUBMIT_HIGH ,
MAKEINTRESOURCE(IDS_FAXSEC_SUB_HIGH),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 3 query jobs
{
&GUID_NULL,
FAX_ACCESS_QUERY_JOBS,
MAKEINTRESOURCE(IDS_FAXSEC_JOB_QRY),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 4 Manage jobs
{
&GUID_NULL,
FAX_ACCESS_MANAGE_JOBS,
MAKEINTRESOURCE(IDS_FAXSEC_JOB_MNG),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 5 query configuration
{
&GUID_NULL,
FAX_ACCESS_QUERY_CONFIG,
MAKEINTRESOURCE(IDS_FAXSEC_CONFIG_QRY),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 6 Manage configuration
{
&GUID_NULL,
FAX_ACCESS_MANAGE_CONFIG,
MAKEINTRESOURCE(IDS_FAXSEC_CONFIG_SET),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 7 Query incoming faxes archive
{
&GUID_NULL,
FAX_ACCESS_QUERY_IN_ARCHIVE,
MAKEINTRESOURCE(IDS_FAXSEC_QRY_IN_ARCH),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 8 Manage incoming faxes archive
{
&GUID_NULL,
FAX_ACCESS_MANAGE_IN_ARCHIVE,
MAKEINTRESOURCE(IDS_FAXSEC_MNG_IN_ARCH),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 9 Query outgoing faxes archive
{
&GUID_NULL,
FAX_ACCESS_QUERY_OUT_ARCHIVE,
MAKEINTRESOURCE(IDS_FAXSEC_QRY_OUT_ARCH),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// 10 Manage outgoing faxes archive
{
&GUID_NULL,
FAX_ACCESS_MANAGE_OUT_ARCHIVE,
MAKEINTRESOURCE(IDS_FAXSEC_MNG_OUT_ARCH),
SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC
},
// specific permissions
// 11 Read permission
{
&GUID_NULL,
READ_CONTROL,
MAKEINTRESOURCE(IDS_FAXSEC_READ_PERM),
SI_ACCESS_SPECIFIC
},
// 12 Change Permissions
{
&GUID_NULL,
WRITE_DAC,
MAKEINTRESOURCE(IDS_FAXSEC_CHNG_PERM),
SI_ACCESS_SPECIFIC
},
// 13 Take ownership
{
&GUID_NULL,
WRITE_OWNER,
MAKEINTRESOURCE(IDS_FAXSEC_CHNG_OWNER),
SI_ACCESS_SPECIFIC
}
};
*ppAccess = (0 == dwFlags) ? siFaxBasicAccess : siFaxAccess;
*pcAccesses = ULONG((0 == dwFlags) ? ARR_SIZE(siFaxBasicAccess) : ARR_SIZE(siFaxAccess));
*piDefaultAccess = (0 == dwFlags) ? 0 : 1;
return S_OK;
} // CFaxSecurity::GetAccessRights
STDMETHODIMP
CFaxSecurity::MapGeneric(const GUID* pguidObjectType,
UCHAR* pAceFlags,
ACCESS_MASK* pmask)
/*
- CFaxSecurityInformation::MapGeneric
-
* Purpose:
* Requests that the generic access rights in an access mask
* be mapped to their corresponding standard and specific access rights.
*
* Arguments:
*
* Return:
* OLE error code
*/
{
static GENERIC_MAPPING genericMapping =
{
(STANDARD_RIGHTS_READ | FAX_GENERIC_READ), // GenericRead
(STANDARD_RIGHTS_WRITE | FAX_GENERIC_WRITE), // GenericWrite
(STANDARD_RIGHTS_EXECUTE | FAX_GENERIC_EXECUTE), // GenericExecute
(READ_CONTROL | WRITE_DAC | WRITE_OWNER | FAX_GENERIC_ALL) // GenericAll
};
MapGenericMask(pmask, &genericMapping);
return S_OK;
}
STDMETHODIMP
CFaxSecurity::GetInheritTypes(PSI_INHERIT_TYPE* ppInheritTypes,
ULONG* pcInheritTypes)
{
return E_NOTIMPL;
}
STDMETHODIMP
CFaxSecurity::PropertySheetPageCallback(HWND hwnd,
UINT uMsg,
SI_PAGE_TYPE uPage)
{
return S_OK;
}
HRESULT
CFaxSecurity::MakeSelfRelativeCopy(PSECURITY_DESCRIPTOR psdOriginal,
PSECURITY_DESCRIPTOR* ppsdNew)
/*
- CFaxSecurityInformation::MakeSelfRelativeCopy
-
* Purpose:
* This pravite method copies Security descriptors
*
* Arguments:
*
* Return:
* OLE error code
*/
{
Assert( NULL != psdOriginal );
//
// we have to find out whether the original is already self-relative
//
SECURITY_DESCRIPTOR_CONTROL sdc = 0;
PSECURITY_DESCRIPTOR psdSelfRelativeCopy = NULL;
DWORD dwRevision = 0;
DWORD cb = 0;
Assert(IsValidSecurityDescriptor( psdOriginal ) );
if( !::GetSecurityDescriptorControl( psdOriginal, &sdc, &dwRevision ) )
{
DWORD err = ::GetLastError();
Error(("GetSecurityDescriptorControl() failed with %d\n", err));
return HRESULT_FROM_WIN32( err );
}
if( sdc & SE_SELF_RELATIVE )
{
// the original is in self-relative format, just byte-copy it
// get size
cb = ::GetSecurityDescriptorLength( psdOriginal );
// alloc the memory
psdSelfRelativeCopy = (PSECURITY_DESCRIPTOR) ::LocalAlloc( LMEM_ZEROINIT, cb );
if(NULL == psdSelfRelativeCopy)
{
Error(("Out of memory.\n"));
return E_OUTOFMEMORY;
}
// make the copy
::memcpy( psdSelfRelativeCopy, psdOriginal, cb );
}
else
{
// the original is in absolute format, convert-copy it
// get new size - it will fail and set cb to the correct buffer size
::MakeSelfRelativeSD( psdOriginal, NULL, &cb );
// alloc the new amount of memory
psdSelfRelativeCopy = (PSECURITY_DESCRIPTOR) ::LocalAlloc( LMEM_ZEROINIT, cb );
if(!psdSelfRelativeCopy)
{
Error(("Out of memory.\n"));
return E_OUTOFMEMORY; // just in case the exception is ignored
}
if( !::MakeSelfRelativeSD( psdOriginal, psdSelfRelativeCopy, &cb ) )
{
DWORD err = ::GetLastError();
Error(("MakeSelfRelativeSD() failed with %d\n", err));
::LocalFree( psdSelfRelativeCopy );
return HRESULT_FROM_WIN32( err );
}
}
*ppsdNew = psdSelfRelativeCopy;
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
//
// This is the entry point function called from our code
//
///////////////////////////////////////////////////////////////////////////////
HMODULE g_hAclui = NULL;
extern "C"
HPROPSHEETPAGE
CreateFaxSecurityPage()
{
HPROPSHEETPAGE hPage = NULL;
HPROPSHEETPAGE (*pfCreateSecurityPage)(LPSECURITYINFO) = NULL;
if(!IsWinXPOS())
{
//
// The security page should bge added only to the local fax printer on XP OS.
//
Assert(FALSE);
return NULL;
}
//
// CreateSecurityPage() Requires Windows 2000 or later, so we connect to it dynamically
//
if(!g_hAclui)
{
g_hAclui = LoadLibrary(TEXT("aclui.dll"));
if(!g_hAclui)
{
Error(("LoadLibrary(aclui.dll) failed with %d\n", GetLastError()));
goto error;
}
}
(FARPROC&)pfCreateSecurityPage = GetProcAddress(g_hAclui, "CreateSecurityPage");
if(!pfCreateSecurityPage)
{
Error(("GetProcAddress(CreateSecurityPage) failed with %d\n", GetLastError()));
goto error;
}
if(!g_pFaxSecurity)
{
g_pFaxSecurity = new CFaxSecurity();
}
if(!g_pFaxSecurity)
{
Error(("Out of memory.\n"));
goto error;
}
hPage = pfCreateSecurityPage(g_pFaxSecurity);
if(!hPage)
{
Error(("CreateSecurityPage() failed with %d\n", ::GetLastError()));
goto error;
}
return hPage;
error:
if(g_hAclui)
{
FreeLibrary(g_hAclui);
g_hAclui = NULL;
}
return NULL;
}
extern "C"
void
ReleaseFaxSecurity()
{
if(g_pFaxSecurity)
{
g_pFaxSecurity->Release();
}
if(g_hAclui)
{
FreeLibrary(g_hAclui);
g_hAclui = NULL;
}
}