windows-nt/Source/XPSP1/NT/inetsrv/iis/admin/adsi/adsiis/cipsec.cxx
2020-09-26 16:20:57 +08:00

1033 lines
21 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: cipsec.cxx
//
// Contents: IPSecurity object
//
// History: 21-4-97 SophiaC Created.
//
//----------------------------------------------------------------------------
#include "iis.hxx"
#pragma hdrstop
#define _RDNS_STANDALONE
#define ILIST_DENY 0
#define ILIST_GRANT 1
#define ITYPE_DNS 0
#define ITYPE_IP 1
#define SENTINEL_ADDR "0.0.0.0, 255.255.255.255"
#define DEFAULT_MASK "255.255.255.255"
LPBYTE
GetIp(
LPSTR pArg
);
BOOL
FreeIp(
LPBYTE pIp
);
// Class CIPSecurity
DEFINE_Simple_IDispatch_Implementation(CIPSecurity)
CIPSecurity::CIPSecurity():
_pDispMgr(NULL)
{
ENLIST_TRACKING(CIPSecurity);
}
HRESULT
CIPSecurity::CreateIPSecurity(
REFIID riid,
void **ppvObj
)
{
CIPSecurity FAR * pIPSecurity = NULL;
HRESULT hr = S_OK;
hr = AllocateIPSecurityObject(&pIPSecurity);
BAIL_ON_FAILURE(hr);
hr = pIPSecurity->QueryInterface(riid, ppvObj);
BAIL_ON_FAILURE(hr);
pIPSecurity->Release();
RRETURN(hr);
error:
delete pIPSecurity;
RRETURN(hr);
}
CIPSecurity::~CIPSecurity( )
{
delete _pDispMgr;
_AddrChk.UnbindCheckList();
}
STDMETHODIMP
CIPSecurity::QueryInterface(
REFIID iid,
LPVOID FAR* ppv
)
{
if (IsEqualIID(iid, IID_IUnknown))
{
*ppv = (IISIPSecurity FAR *) this;
}
else if (IsEqualIID(iid, IID_IISIPSecurity))
{
*ppv = (IISIPSecurity FAR *) this;
}
else if (IsEqualIID(iid, IID_IDispatch))
{
*ppv = (IISIPSecurity FAR *) this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
HRESULT
CIPSecurity::InitFromBinaryBlob(
LPBYTE pByte,
DWORD dwLength
)
{
DWORD dwDenyEntries, dwGrantEntries;
LPBYTE pBuffer = NULL;
if (pByte && dwLength) {
pBuffer = (LPBYTE) AllocADsMem(dwLength);
if (!pBuffer) {
return(E_OUTOFMEMORY);
}
memcpy(pBuffer, pByte, dwLength);
}
//
// Length of 0 is the default value for empty blob
//
if ((pByte == NULL) || (dwLength == 0)) {
_AddrChk.BindCheckList(NULL, 0);
} else {
_AddrChk.BindCheckList(pBuffer, dwLength);
}
dwDenyEntries = _AddrChk.GetNbAddr(FALSE) +
_AddrChk.GetNbName(FALSE);
dwGrantEntries = _AddrChk.GetNbAddr(TRUE) +
_AddrChk.GetNbName(TRUE);
if (dwGrantEntries > dwDenyEntries) {
_bGrantByDefault = FALSE;
//
// check if entry is a sentinel address
//
if (dwGrantEntries == 1 && _AddrChk.GetNbAddr(TRUE) == 1) {
DWORD dwFlags;
LPBYTE pM;
LPBYTE pA;
CHAR achE[80];
if (_AddrChk.GetAddr(TRUE, 0, &dwFlags, &pM, &pA) == TRUE) {
wsprintfA( (LPSTR)achE, "%d.%d.%d.%d, %d.%d.%d.%d",
pA[3], pA[2], pA[1], pA[0],
pM[3], pM[2], pM[1], pM[0] );
}
if (strcmp(achE, SENTINEL_ADDR) == 0) {
_AddrChk.DeleteAllAddr(TRUE);
}
}
}
else {
_bGrantByDefault = TRUE;
}
return S_OK;
}
HRESULT
CIPSecurity::CopyIPSecurity(
LPBYTE *ppByte,
PDWORD pdwLength
)
{
//
// Remove the other list if default by grant
//
_AddrChk.DeleteAllAddr(_bGrantByDefault);
_AddrChk.DeleteAllName(_bGrantByDefault);
//
// List is empty. If deny by default is on, create
// a dummy sentinel entry to grant access to single
// address 0.0.0.0, otherwise we're ok.
//
if (!_bGrantByDefault &&
!_AddrChk.GetNbAddr(TRUE) &&
!_AddrChk.GetNbName(TRUE)) {
BYTE bMask[4] = { 0xff, 0xff, 0xff, 0xff };
BYTE bIp[4] = { 0, 0, 0, 0 };
_AddrChk.AddAddr(
ILIST_GRANT,
AF_INET,
bMask,
bIp
);
}
*ppByte = _AddrChk.QueryCheckListPtr();
*pdwLength = _AddrChk.QueryCheckListSize();
return S_OK;
}
HRESULT
CIPSecurity::AllocateIPSecurityObject(
CIPSecurity ** ppIPSecurity
)
{
CIPSecurity FAR * pIPSecurity = NULL;
CAggregatorDispMgr FAR * pDispMgr = NULL;
HRESULT hr = S_OK;
pIPSecurity = new CIPSecurity();
if (pIPSecurity == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
pDispMgr = new CAggregatorDispMgr;
if (pDispMgr == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_IISOle,
IID_IISIPSecurity,
(IISIPSecurity *)pIPSecurity,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
pIPSecurity->_pDispMgr = pDispMgr;
*ppIPSecurity = pIPSecurity;
RRETURN(hr);
error:
delete pDispMgr;
RRETURN(hr);
}
STDMETHODIMP
CIPSecurity::get_IPDeny(THIS_ VARIANT FAR * retval)
{
long i = 0;
HRESULT hr = S_OK;
DWORD dwNumEntries = _AddrChk.GetNbAddr(FALSE);
VariantInit(retval);
SAFEARRAY *aList = NULL;
SAFEARRAYBOUND aBound;
aBound.lLbound = 0;
aBound.cElements = dwNumEntries; // number of entries
aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
if ( aList == NULL )
{
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
for ( i = 0; i < (long) dwNumEntries; i++ )
{
VARIANT v;
LPBYTE pByte = NULL;
DWORD dwStatus;
VariantInit(&v);
v.vt = VT_BSTR;
GetEntry(ITYPE_IP, ILIST_DENY, &pByte, i);
hr = ADsAllocString((LPWSTR)pByte, &(v.bstrVal));
if (pByte) {
FreeADsMem(pByte);
}
BAIL_ON_FAILURE(hr);
hr = SafeArrayPutElement( aList, &i, &v );
VariantClear(&v);
BAIL_ON_FAILURE(hr);
}
V_VT(retval) = VT_ARRAY | VT_VARIANT;
V_ARRAY(retval) = aList;
RRETURN(S_OK);
error:
if ( aList )
SafeArrayDestroy( aList );
RRETURN(hr);
}
STDMETHODIMP
CIPSecurity::put_IPDeny(THIS_ VARIANT pVarIPDeny)
{
VARIANT * pVarArray = NULL;
VARIANT * pvProp = NULL;
VARIANT vVar;
DWORD dwNumValues;
DWORD dwStatus;
DWORD i;
LPSTR pszAnsiName = NULL;
HRESULT hr = S_OK;
VariantInit(&vVar);
VariantCopyInd(&vVar, &pVarIPDeny);
if ((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar)) {
hr = ConvertArrayToVariantArray(
vVar,
&pVarArray,
&dwNumValues
);
BAIL_ON_FAILURE(hr);
pvProp = pVarArray;
}
else {
dwNumValues = 1;
pvProp = &pVarIPDeny;
}
_AddrChk.DeleteAllAddr(FALSE);
for (i = 0; i < dwNumValues; i++ ) {
dwStatus = AllocAnsi(
(LPWSTR)pvProp->bstrVal,
&pszAnsiName
);
if (dwStatus) {
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwStatus));
}
if (pszAnsiName) {
if (!AddToList(ITYPE_IP, ILIST_DENY, pszAnsiName)) {
hr = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
FreeAnsi(pszAnsiName);
pszAnsiName = NULL;
BAIL_ON_FAILURE(hr);
}
pvProp++;
}
error:
if (pVarArray) {
for (i = 0; i < dwNumValues; i++) {
VariantClear(pVarArray + i);
}
FreeADsMem(pVarArray);
}
VariantClear(&vVar);
RRETURN(hr);
}
STDMETHODIMP
CIPSecurity::get_IPGrant(THIS_ VARIANT FAR * retval)
{
long i = 0;
HRESULT hr = S_OK;
DWORD dwNumEntries = _AddrChk.GetNbAddr(TRUE);
VariantInit(retval);
SAFEARRAY *aList = NULL;
SAFEARRAYBOUND aBound;
aBound.lLbound = 0;
aBound.cElements = dwNumEntries; // number of entries
aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
if ( aList == NULL )
{
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
for ( i = 0; i < (long) dwNumEntries; i++ )
{
VARIANT v;
LPBYTE pByte = NULL;
DWORD dwStatus;
LPWSTR pszUnicode;
VariantInit(&v);
v.vt = VT_BSTR;
GetEntry(ITYPE_IP, ILIST_GRANT, &pByte, i);
hr = ADsAllocString((LPWSTR)pByte, &(v.bstrVal));
if (pByte) {
FreeADsMem(pByte);
}
BAIL_ON_FAILURE(hr);
hr = SafeArrayPutElement( aList, &i, &v );
VariantClear(&v);
BAIL_ON_FAILURE(hr);
}
V_VT(retval) = VT_ARRAY | VT_VARIANT;
V_ARRAY(retval) = aList;
RRETURN(S_OK);
error:
if ( aList )
SafeArrayDestroy( aList );
RRETURN(hr);
}
STDMETHODIMP
CIPSecurity::put_IPGrant(THIS_ VARIANT pVarIPGrant)
{
HRESULT hr = S_OK;
VARIANT * pVarArray = NULL;
VARIANT * pvProp = NULL;
VARIANT vVar;
DWORD dwNumValues;
DWORD dwStatus;
DWORD i;
LPSTR pszAnsiName = NULL;
VariantInit(&vVar);
VariantCopyInd(&vVar, &pVarIPGrant);
if ((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar)) {
hr = ConvertArrayToVariantArray(
vVar,
&pVarArray,
&dwNumValues
);
BAIL_ON_FAILURE(hr);
pvProp = pVarArray;
}
else {
dwNumValues = 1;
pvProp = &pVarIPGrant;
}
_AddrChk.DeleteAllAddr(TRUE);
for (i = 0; i < dwNumValues; i++ ) {
dwStatus = AllocAnsi(
(LPWSTR)pvProp->bstrVal,
&pszAnsiName
);
if (dwStatus) {
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwStatus));
}
if (pszAnsiName) {
if (!AddToList(ITYPE_IP, ILIST_GRANT, pszAnsiName) ) {
hr = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
FreeAnsi(pszAnsiName);
pszAnsiName = NULL;
BAIL_ON_FAILURE(hr);
}
pvProp++;
}
error:
if (pVarArray) {
for (i = 0; i < dwNumValues; i++) {
VariantClear(pVarArray + i);
}
FreeADsMem(pVarArray);
}
VariantClear(&vVar);
RRETURN(hr);
}
STDMETHODIMP
CIPSecurity::get_DomainDeny(THIS_ VARIANT FAR * retval)
{
long i = 0;
HRESULT hr = S_OK;
DWORD dwNumEntries = _AddrChk.GetNbName(FALSE);
VariantInit(retval);
SAFEARRAY *aList = NULL;
SAFEARRAYBOUND aBound;
aBound.lLbound = 0;
aBound.cElements = dwNumEntries; // number of entries
aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
if ( aList == NULL )
{
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
for ( i = 0; i < (long) dwNumEntries; i++ )
{
VARIANT v;
LPBYTE pByte = NULL;
DWORD dwStatus;
VariantInit(&v);
v.vt = VT_BSTR;
GetEntry(ITYPE_DNS, ILIST_DENY, &pByte, i);
hr = ADsAllocString((LPWSTR)pByte, &(v.bstrVal));
if (pByte) {
FreeADsMem(pByte);
}
BAIL_ON_FAILURE(hr);
hr = SafeArrayPutElement( aList, &i, &v );
VariantClear(&v);
BAIL_ON_FAILURE(hr);
}
V_VT(retval) = VT_ARRAY | VT_VARIANT;
V_ARRAY(retval) = aList;
RRETURN(S_OK);
error:
if ( aList )
SafeArrayDestroy( aList );
RRETURN(hr);
}
STDMETHODIMP
CIPSecurity::put_DomainDeny(THIS_ VARIANT pVarDomainDeny)
{
HRESULT hr = S_OK;
VARIANT * pVarArray = NULL;
VARIANT * pvProp = NULL;
VARIANT vVar;
DWORD dwNumValues;
DWORD dwStatus;
DWORD i;
LPSTR pszAnsiName = NULL;
VariantInit(&vVar);
VariantCopyInd(&vVar, &pVarDomainDeny);
if ((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar)) {
hr = ConvertArrayToVariantArray(
vVar,
&pVarArray,
&dwNumValues
);
BAIL_ON_FAILURE(hr);
pvProp = pVarArray;
}
else {
dwNumValues = 1;
pvProp = &pVarDomainDeny;
}
_AddrChk.DeleteAllName(FALSE);
for (i = 0; i < dwNumValues; i++ ) {
dwStatus = AllocAnsi(
(LPWSTR)pvProp->bstrVal,
&pszAnsiName
);
if (dwStatus) {
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwStatus));
}
if (pszAnsiName) {
if (!AddToList(ITYPE_DNS, ILIST_DENY, pszAnsiName)) {
hr = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
FreeAnsi(pszAnsiName);
pszAnsiName = NULL;
BAIL_ON_FAILURE(hr);
}
pvProp++;
}
error:
if (pVarArray) {
for (i = 0; i < dwNumValues; i++) {
VariantClear(pVarArray + i);
}
FreeADsMem(pVarArray);
}
VariantClear(&vVar);
RRETURN(hr);
}
STDMETHODIMP
CIPSecurity::get_DomainGrant(THIS_ VARIANT FAR * retval)
{
long i = 0;
HRESULT hr = S_OK;
DWORD dwNumEntries = _AddrChk.GetNbName(TRUE);
VariantInit(retval);
SAFEARRAY *aList = NULL;
SAFEARRAYBOUND aBound;
aBound.lLbound = 0;
aBound.cElements = dwNumEntries; // number of entries
aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
if ( aList == NULL )
{
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
for ( i = 0; i < (long) dwNumEntries; i++ )
{
VARIANT v;
LPBYTE pByte = NULL;
DWORD dwStatus;
VariantInit(&v);
v.vt = VT_BSTR;
GetEntry(ITYPE_DNS, ILIST_GRANT, &pByte, i);
hr = ADsAllocString((LPWSTR)pByte, &(v.bstrVal));
if (pByte) {
FreeADsMem(pByte);
}
BAIL_ON_FAILURE(hr);
hr = SafeArrayPutElement( aList, &i, &v );
VariantClear(&v);
BAIL_ON_FAILURE(hr);
}
V_VT(retval) = VT_ARRAY | VT_VARIANT;
V_ARRAY(retval) = aList;
RRETURN(S_OK);
error:
if ( aList )
SafeArrayDestroy( aList );
RRETURN(hr);
}
STDMETHODIMP
CIPSecurity::put_DomainGrant(THIS_ VARIANT pVarDomainGrant)
{
HRESULT hr = S_OK;
VARIANT * pVarArray = NULL;
VARIANT * pvProp = NULL;
VARIANT vVar;
DWORD dwNumValues;
DWORD dwStatus;
DWORD i;
LPSTR pszAnsiName = NULL;
VariantInit(&vVar);
VariantCopyInd(&vVar, &pVarDomainGrant);
if ((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar)) {
hr = ConvertArrayToVariantArray(
vVar,
&pVarArray,
&dwNumValues
);
BAIL_ON_FAILURE(hr);
pvProp = pVarArray;
}
else {
dwNumValues = 1;
pvProp = &pVarDomainGrant;
}
_AddrChk.DeleteAllName(TRUE);
for (i = 0; i < dwNumValues; i++ ) {
dwStatus = AllocAnsi(
(LPWSTR)pvProp->bstrVal,
&pszAnsiName
);
if (dwStatus) {
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwStatus));
}
if (pszAnsiName) {
if (!AddToList(ITYPE_DNS, ILIST_GRANT, pszAnsiName)) {
hr = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
}
FreeAnsi(pszAnsiName);
pszAnsiName = NULL;
BAIL_ON_FAILURE(hr);
}
pvProp++;
}
error:
if (pVarArray) {
for (i = 0; i < dwNumValues; i++) {
VariantClear(pVarArray + i);
}
FreeADsMem(pVarArray);
}
VariantClear(&vVar);
RRETURN(hr);
}
STDMETHODIMP
CIPSecurity::get_GrantByDefault(THIS_ VARIANT_BOOL FAR * retval)
{
*retval = _bGrantByDefault ? VARIANT_TRUE : VARIANT_FALSE;
RRETURN(S_OK);
}
STDMETHODIMP
CIPSecurity::put_GrantByDefault(THIS_ VARIANT_BOOL bGrantByDefault)
{
_bGrantByDefault = bGrantByDefault ? TRUE : FALSE;
RRETURN(S_OK);
}
/* INTRINSA suppress=null_pointers */
BOOL
CIPSecurity::AddToList(
int iType,
int iList,
LPSTR pArg
)
{
BOOL fSt;
LPBYTE pMask = NULL;
LPBYTE pAddr = NULL;
DWORD dwFlags = 0;
int * piArg;
switch ( iType )
{
case ITYPE_IP:
if (pAddr = GetIp( strtok(pArg,",") ))
{
pMask = GetIp( pArg+strlen(pArg)+1 );
if (!pMask) {
pMask = GetIp(DEFAULT_MASK);
}
fSt = _AddrChk.AddAddr( iList, AF_INET, pMask, pAddr );
}
else
{
fSt = FALSE;
}
FreeIp( pMask );
FreeIp( pAddr );
return fSt;
case ITYPE_DNS:
if ( !strncmp( pArg, "*.", 2 ) )
{
pArg += 2;
}
else
{
dwFlags |= DNSLIST_FLAG_NOSUBDOMAIN;
}
return _AddrChk.AddName( iList, pArg, dwFlags );
break;
}
return FALSE;
}
BOOL
CIPSecurity::GetEntry(
int iType,
int iList,
LPBYTE * ppbyte,
int dwEntry
)
{
UINT i;
UINT x;
DWORD dwF;
DWORD dwStatus;
BOOL fSt = FALSE;
LPWSTR pszStr = NULL;
*ppbyte = NULL;
switch ( iType )
{
case ITYPE_IP:
LPBYTE pM;
LPBYTE pA;
CHAR achE[80];
fSt = _AddrChk.GetAddr( iList, dwEntry, &dwF, &pM, &pA );
if (fSt) {
wsprintfA( (LPSTR)achE, "%d.%d.%d.%d, %d.%d.%d.%d",
pA[0], pA[1], pA[2], pA[3],
pM[0], pM[1], pM[2], pM[3] );
dwStatus = AllocUnicode(
(LPSTR)achE,
&pszStr
);
if (dwStatus == ERROR_SUCCESS) {
*ppbyte = (LPBYTE) pszStr;
}
else {
fSt = FALSE;
}
}
break;
case ITYPE_DNS:
LPSTR pN;
DWORD dwLen;
UINT err;
// Use break to exit on error condition
fSt = _AddrChk.GetName( iList, dwEntry, &pN, &dwF );
if( !fSt )
{
break;
}
dwLen = strlen(pN) + 1;
// pszStr is the working copy of our memory
// *ppbyte is the data to be returned
if ( dwF & DNSLIST_FLAG_NOSUBDOMAIN )
{
pszStr = (LPWSTR) AllocADsMem(dwLen*sizeof(WCHAR));
if( !pszStr )
{
fSt = FALSE;
break;
}
*ppbyte = (LPBYTE)pszStr;
}
else
{
// In this case we have a subdomain restriction, so
// we want to pre-pend "*." to the string.
pszStr = (LPWSTR) AllocADsMem((dwLen+2)*sizeof(WCHAR));
if( !pszStr )
{
fSt = FALSE;
break;
}
// Save the address to return
*ppbyte = (LPBYTE)pszStr;
wcscpy((LPWSTR)pszStr, L"*.");
pszStr += wcslen(pszStr);
}
err = (UINT) !MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
pN,
dwLen,
pszStr,
dwLen);
if (err)
{
FreeADsMem( *ppbyte );
*ppbyte = NULL;
fSt = FALSE;
break;
}
// Final break
break;
}
return fSt;
}
LPBYTE
GetIp(
LPSTR pArg
)
{
if (pArg)
{
LPBYTE p;
if ( p = (LPBYTE)LocalAlloc( LMEM_FIXED, 4 ) )
{
int p0, p1, p2, p3;
if ( sscanf( pArg, "%d.%d.%d.%d", &p0, &p1, &p2, &p3 ) == 4 )
{
//
// network byte order
//
p[3] = (BYTE)(p3 & 0xFF);
p[2] = (BYTE)(p2 & 0xFF);
p[1] = (BYTE)(p1 & 0xFF);
p[0] = (BYTE)(p0 & 0xFF);
return p;
}
LocalFree( p );
return NULL;
}
}
return NULL;
}
BOOL
FreeIp(
LPBYTE pIp
)
{
if ( pIp )
{
LocalFree( pIp );
}
return TRUE;
}
typedef
VOID
(* PFN_SCHED_CALLBACK)(
VOID * pContext
);
dllexp
DWORD
ScheduleWorkItem(
PFN_SCHED_CALLBACK pfnCallback,
PVOID pContext,
DWORD msecTimeInterval,
BOOL fPeriodic = FALSE
)
{
return 0;
}
dllexp
BOOL
RemoveWorkItem(
DWORD pdwCookie
)
{
return FALSE;
}