windows-nt/Source/XPSP1/NT/shell/lib/autosecurity.cpp
2020-09-26 16:20:57 +08:00

219 lines
7.5 KiB
C++

/*****************************************************************************\
FILE: autosecurity.cpp
DESCRIPTION:
Helpers functions to check if an Automation interface or ActiveX Control
is hosted or used by a safe caller.
BryanSt 8/20/1999
Copyright (C) Microsoft Corp 1999-1999. All rights reserved.
\*****************************************************************************/
#include "stock.h"
#pragma hdrstop
#include <autosecurity.h> // CAutomationSecurity
#include <ieguidp.h> // IID_IBrowserService
#include "ccstock.h" // LocalZoneCheck
/***************************************************************\
DESCRIPTION:
Some hosts are always safe. Visual Basic is one example.
PARAMETERS:
RETURN: This function will return TRUE if the host is
always safe.
HRESULT: This is a more descriptive error so the caller
can differenciate E_OUTOFMEMORY from E_INVALIDARG, etc.
\***************************************************************/
BOOL CAutomationSecurity::IsSafeHost(OUT OPTIONAL HRESULT * phr)
{
BOOL fAlwaysSafe;
// _dwSafetyOptions being zero means we are in a mode
// that needs to assume the caller or data is from
// an untrusted source.
if (0 == _dwSafetyOptions)
{
fAlwaysSafe = TRUE;
if (phr)
*phr = S_OK;
}
else
{
fAlwaysSafe = FALSE;
if (phr)
*phr = E_ACCESSDENIED;
}
return fAlwaysSafe;
}
/***************************************************************\
DESCRIPTION:
The class that implements this can check if the host is
from the Local zone. This way, we can prevent a host that
would try to call unsafe automation methods or misrepresent
the consequence of the ActiveX Control's UI.
PARAMETERS:
RETURN: TRUE if the security check passed. FALSE means
the host isn't trusted so don't care out unsafe
operations.
dwFlags: What behaviors does the caller want? Currently:
CAS_REG_VALIDATION: This means the caller needs the
host's HTML to be registered and the checksum to
be valid.
HRESULT: This is a more descriptive error so the caller
can differenciate E_OUTOFMEMORY from E_INVALIDARG, etc.
\***************************************************************/
BOOL CAutomationSecurity::IsHostLocalZone(IN DWORD dwFlags, OUT OPTIONAL HRESULT * phr)
{
HRESULT hr;
// See if the host is always safe.
if (!IsSafeHost(&hr))
{
// It isn't, so let's see if this content is safe.
// (Normally the immediate HTML FRAME)
// Is it from the local zone?
hr = LocalZoneCheck(_punkSite);
// Does the caller also want to verify it's checksum?
if ((S_OK == hr) && (CAS_REG_VALIDATION & dwFlags))
{
IBrowserService* pbs;
WCHAR wszPath[MAX_PATH];
wszPath[0] = 0;
hr = E_ACCESSDENIED;
// ask the browser, for example we are in a .HTM doc
if (SUCCEEDED(IUnknown_QueryService(_punkSite, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &pbs))))
{
LPITEMIDLIST pidl;
if (SUCCEEDED(pbs->GetPidl(&pidl)))
{
DWORD dwAttribs = SFGAO_FOLDER;
if (SUCCEEDED(SHGetNameAndFlagsW(pidl, SHGDN_FORPARSING, wszPath, ARRAYSIZE(wszPath), &dwAttribs))
&& (dwAttribs & SFGAO_FOLDER)) // This is a folder. So, wszPath should be the path for it's webview template
{
IOleCommandTarget *pct;
// find the template path from webview, for example a .HTT file
if (SUCCEEDED(IUnknown_QueryService(_punkSite, SID_DefView, IID_PPV_ARG(IOleCommandTarget, &pct))))
{
VARIANT vPath;
vPath.vt = VT_EMPTY;
if (pct->Exec(&CGID_DefView, DVCMDID_GETTEMPLATEDIRNAME, 0, NULL, &vPath) == S_OK)
{
if (vPath.vt == VT_BSTR && vPath.bstrVal)
{
DWORD cchPath = ARRAYSIZE(wszPath);
if (S_OK != PathCreateFromUrlW(vPath.bstrVal, wszPath, &cchPath, 0))
{
// it might not be an URL, in this case it is a file path
StrCpyNW(wszPath, vPath.bstrVal, ARRAYSIZE(wszPath));
}
}
VariantClear(&vPath);
}
pct->Release();
}
}
ILFree(pidl);
}
pbs->Release();
}
else
{
ASSERT(0); // no browser, where are we?
}
if (wszPath[0])
{
DWORD dwRVTFlags = (SHRVT_VALIDATE | SHRVT_REGISTERIFPROMPTOK);
if (CAS_PROMPT_USER & dwFlags)
dwRVTFlags |= SHRVT_PROMPTUSER;
hr = SHRegisterValidateTemplate(wszPath, dwRVTFlags);
}
}
}
if (S_FALSE == hr)
hr = E_ACCESSDENIED; // The caller needs to soften the hr to S_OK if it's concerned for script.
if (phr)
*phr = hr;
return ((S_OK == hr) ? TRUE : FALSE);
}
/***************************************************************\
DESCRIPTION:
The class that implements this can check if the host is
from the Local zone. This way, we can prevent a host that
would try to call unsafe automation methods or misrepresent
the consequence of the ActiveX Control's UI.
PARAMETERS:
RETURN: TRUE if the security check passed. FALSE means
the host isn't trusted so don't care out unsafe
operations.
dwFlags: What behaviors does the caller want? Currently:
CAS_REG_VALIDATION: This means the caller needs the
host's HTML to be registered and the checksum to
be valid.
HRESULT: This is a more descriptive error so the caller
can differenciate E_OUTOFMEMORY from E_INVALIDARG, etc.
\***************************************************************/
BOOL CAutomationSecurity::IsUrlActionAllowed(IN IInternetHostSecurityManager * pihsm, IN DWORD dwUrlAction, IN DWORD dwFlags, OUT OPTIONAL HRESULT * phr)
{
HRESULT hr;
IInternetHostSecurityManager * pihsmTemp = NULL;
if (!pihsm)
{
hr = IUnknown_QueryService(_punkSite, IID_IInternetHostSecurityManager, IID_PPV_ARG(IInternetHostSecurityManager, &pihsmTemp));
pihsm= pihsmTemp;
}
hr = ZoneCheckHost(pihsm, dwUrlAction, dwFlags);
if (S_FALSE == hr)
hr = E_ACCESSDENIED; // The caller needs to soften the hr to S_OK if it's concerned for script.
if (phr)
*phr = hr;
ATOMICRELEASE(pihsmTemp);
return ((S_OK == hr) ? TRUE : FALSE);
}
HRESULT CAutomationSecurity::MakeObjectSafe(IN IUnknown ** ppunk)
{
HRESULT hr;
// See if the host is always safe.
if (!IsSafeHost(&hr))
{
// It isn't, so let's ask the control if it's
// going to be safe.
hr = MakeSafeForScripting(ppunk);
}
return hr;
}