534 lines
12 KiB
C++
534 lines
12 KiB
C++
// 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;
|
|
}
|
|
|