|
|
// to be linked with:
// uuid.lib ole32.lib user32.lib kernel32.lib advapi32.lib wsock32.lib
// iis\svcs\infocomm\rdns\obj\i386\isrdns.lib iis\svcs\lib\i386\tsstr.lib iis\svcs\lib\i386\isdebug.lib
#include "stdafx.h"
#define _RDNS_STANDALONE
#include <winsock2.h>
#include <rdns.hxx>
#include <buffer.hxx>
#include <ole2.h>
#include <iadm.h>
#include <iiscnfg.h>
#include "mdkey.h"
#include "mdentry.h"
#include "helper.h"
#include <inetinfo.h>
extern int g_CheckIfMetabaseValueWasWritten;
#define TIMEOUT_VALUE 5000
//
// Global Data
//
//
// The registry parameter key names for the grant list and deny
// list. We use the kludgemultisz thing for Chicago
//
#define IPSEC_DENY_LIST L"Deny IP List"
#define IPSEC_GRANT_LIST L"Grant IP List"
//
// Private prototypes.
//
BOOL DottedDecimalToDword( CHAR * * ppszAddress, DWORD * pdwAddress );
CHAR * KludgeMultiSz( HKEY hkey, LPDWORD lpdwLength ) { LONG err; DWORD iValue; DWORD cchTotal; DWORD cchValue; CHAR szValue[MAX_PATH]; LPSTR lpMultiSz; LPSTR lpTmp; LPSTR lpEnd;
//
// Enumerate the values and total up the lengths.
//
iValue = 0; cchTotal = 0;
for( ; ; ) { cchValue = sizeof(szValue) / sizeof(szValue[0]);
err = RegEnumValueA( hkey, iValue, szValue, &cchValue, NULL, NULL, NULL, NULL );
if( err != NO_ERROR ) { break; }
//
// Add the length of the value's name, plus one
// for the terminator.
//
cchTotal += strlen( szValue ) + 1;
//
// Advance to next value.
//
iValue++; }
//
// Add one for the final terminating NULL.
//
cchTotal++; *lpdwLength = cchTotal;
//
// Allocate the MULTI_SZ buffer.
//
lpMultiSz = (CHAR *) LocalAlloc( LMEM_FIXED, cchTotal * sizeof(CHAR) );
if( lpMultiSz == NULL ) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); return NULL; }
memset( lpMultiSz, 0, cchTotal * sizeof(CHAR) );
//
// Enumerate the values and append to the buffer.
//
iValue = 0; lpTmp = lpMultiSz; lpEnd = lpMultiSz + cchTotal;
for( ; ; ) { cchValue = sizeof(szValue)/sizeof(CHAR);
err = RegEnumValueA( hkey, iValue, szValue, &cchValue, NULL, NULL, NULL, NULL );
if( err != NO_ERROR ) { break; }
//
// Compute the length of the value name (including
// the terminating NULL).
//
cchValue = strlen( szValue ) + 1;
//
// Determine if there is room in the array, taking into
// account the second NULL that terminates the string list.
//
if( ( lpTmp + cchValue + 1 ) > lpEnd ) { break; }
//
// Append the value name.
//
strcpy( lpTmp, szValue ); lpTmp += cchValue;
//
// Advance to next value.
//
iValue++; }
//
// Success!
//
return (LPSTR)lpMultiSz;
} // KludgeMultiSz
BOOL ReadIPList( LPWSTR pszRegKey, LPWSTR pszRegSubKey, INETA_IP_SEC_LIST** ppIpSec ) /*++
Description: This function reads the IP list from registry location specified in the pszRegKey + pszRegSubKey and stores the list in the internal list in memory.
If there are no entries in the registry then this returns a NULL IP Security list object. If there is a new list, this function also frees the old list present in *ppIPSecList
Arguments: pszRegKey - pointer to string containing the registry key where pszRegSubKey is located pszRegSubKey - pointer to string containing the registry key where IP list is stored relative to pszRegKey
Returns:
TRUE on success and FALSE on failure --*/ { HKEY hkey; DWORD dwError; BOOL fReturn = TRUE; LPWSTR pszK;
*ppIpSec = NULL;
if ( (pszK = (LPWSTR)LocalAlloc(LMEM_FIXED, (wcslen(pszRegKey)+wcslen(pszRegSubKey)+2)*sizeof(WCHAR))) == NULL ) { return FALSE; }
wcscpy( pszK, pszRegKey ); wcscat( pszK, L"\\" ); wcscat( pszK, pszRegSubKey );
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, pszK, 0, KEY_ALL_ACCESS, &hkey );
LocalFree( pszK );
if ( dwError != NO_ERROR) {
if ( dwError != ERROR_FILE_NOT_FOUND ) {
// maybe access denied or some other error.
SetLastError( dwError ); return (FALSE); }
//
// A non-existent key is the same as a blank key
//
} else {
CHAR * psz; CHAR * pszTmp; DWORD cb; DWORD cEntries = 0; INETA_IP_SEC_LIST * pIPSec = NULL;
psz = pszTmp = KludgeMultiSz( hkey, &cb );
RegCloseKey( hkey );
//
// Count the number of addresses and then add them to the list
//
if ( psz != NULL ) {
for( ; *pszTmp; cEntries++ ) {
pszTmp += strlen( pszTmp ) + 1; }
pszTmp = psz;
if ( cEntries > 0) {
pIPSec = ((INETA_IP_SEC_LIST *) LocalAlloc( LMEM_FIXED, sizeof(INETA_IP_SEC_LIST) + cEntries * sizeof(INETA_IP_SEC_ENTRY )) );
if ( pIPSec == NULL ) {
dwError = ERROR_NOT_ENOUGH_MEMORY; fReturn = FALSE; } else {
for( pIPSec->cEntries = 0; *pszTmp; pszTmp += strlen( pszTmp ) + 1 ) {
if (!DottedDecimalToDword( &pszTmp, &pIPSec->aIPSecEntry[pIPSec->cEntries].dwMask ) || !DottedDecimalToDword( &pszTmp, &pIPSec->aIPSecEntry[pIPSec->cEntries].dwNetwork ) ) { } else {
pIPSec->cEntries++; } } // for
dwError = NO_ERROR; } }
if ( dwError == NO_ERROR) { *ppIpSec = pIPSec; }
LocalFree( psz ); }
if ( !fReturn) {
SetLastError( dwError); } }
return ( fReturn); } // IPAccessList::ReadIPList()
BOOL DottedDecimalToDword( CHAR * * ppszAddress, DWORD * pdwAddress ) /*++
Routine Description:
Converts a dotted decimal IP string to it's network equivalent
Note: White space is eaten before *pszAddress and pszAddress is set to the character following the converted address
Arguments:
ppszAddress - Pointer to address to convert. White space before the address is OK. Will be changed to point to the first character after the address pdwAddress - DWORD equivalent address in network order
returns TRUE if successful, FALSE if the address is not correct
--*/ { CHAR * psz; USHORT i; ULONG value; int iSum =0; ULONG k = 0; UCHAR Chr; UCHAR pArray[4];
psz = *ppszAddress;
//
// Skip white space
//
while ( *psz && !isdigit( (UCHAR)(*psz) )) psz++;
//
// Convert the four segments
//
pArray[0] = 0; Chr = *psz;
while ( ( Chr != '\0' ) && (Chr != ' ') ) { if (Chr == '.') { // be sure not to overflow a byte.
if (iSum <= 0xFF) pArray[k] = (UCHAR)iSum; else return FALSE;
// check for too many periods in the address
if (++k > 3) return FALSE;
pArray[k] = 0; iSum = 0; } else { Chr = Chr - '0';
// be sure character is a number 0..9
if ((Chr < 0) || (Chr > 9)) return FALSE;
iSum = iSum*10 + Chr; }
psz++; Chr = *psz; }
// save the last sum in the byte and be sure there are 4 pieces to the
// address
if ((iSum <= 0xFF) && (k == 3)) pArray[k] = (UCHAR)iSum; else return FALSE;
// now convert to a ULONG, in network order...
value = 0;
// go through the array of bytes and concatenate into a ULONG
for (i=0; i < 4; i++ ) { value = (value << 8) + pArray[i]; } *pdwAddress = htonl( value );
*ppszAddress = psz;
return TRUE; }
BOOL FillAddrCheckFromIpList( BOOL fIsGrant, LPINET_INFO_IP_SEC_LIST pInfo, ADDRESS_CHECK *pCheck ) /*++
Routine Description:
Fill an access check object from an IP address list from
Arguments:
fIsGrant - TRUE to access grant list, FALSE to access deny list pInfo - ptr to IP address list pCheck - ptr to address check object to update
Return:
TRUE if success, otherwise FALSE
--*/ { UINT x;
if ( pInfo ) { for ( x = 0 ; x < pInfo->cEntries ; ++x ) { if ( ! pCheck->AddAddr( fIsGrant, AF_INET, (LPBYTE)&pInfo->aIPSecEntry[x].dwMask, (LPBYTE)&pInfo->aIPSecEntry[x].dwNetwork ) ) { return FALSE; } } }
return TRUE; }
DWORD MigrateServiceIpSec( LPWSTR pszSrvRegKey, LPWSTR pszSrvMetabasePath ) { INETA_IP_SEC_LIST* pGrant = NULL; INETA_IP_SEC_LIST* pDeny = NULL; ADDRESS_CHECK acCheck; DWORD err = 0;
if ( ReadIPList( pszSrvRegKey, IPSEC_GRANT_LIST, &pGrant ) && ReadIPList( pszSrvRegKey, IPSEC_DENY_LIST, &pDeny ) ) { if ( pGrant || pDeny ) { acCheck.BindCheckList( NULL, 0 );
if ( FillAddrCheckFromIpList( TRUE, pGrant, &acCheck ) && FillAddrCheckFromIpList( FALSE, pDeny, &acCheck ) ) { CMDKey cmdKey; cmdKey.OpenNode(pszSrvMetabasePath); if ( (METADATA_HANDLE)cmdKey ) { cmdKey.SetData( MD_IP_SEC, METADATA_INHERIT | METADATA_REFERENCE, IIS_MD_UT_FILE, BINARY_METADATA, acCheck.GetStorage()->GetUsed(), (acCheck.GetStorage()->GetAlloc() ? acCheck.GetStorage()->GetAlloc() : (LPBYTE)"") ); cmdKey.Close(); } } }
acCheck.UnbindCheckList(); } else { err = GetLastError(); }
if ( pGrant ) { LocalFree( pGrant ); }
if ( pDeny ) { LocalFree( pDeny ); }
return err; }
|