//--------------------------------------------------------------------------- // // 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; }