597 lines
14 KiB
C
597 lines
14 KiB
C
/*++
|
||
|
||
Copyright (c) 1992-1997 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
registry.c
|
||
|
||
Abstract:
|
||
|
||
Contains routines for manipulating registry parameters.
|
||
|
||
Environment:
|
||
|
||
User Mode - Win32
|
||
|
||
Revision History:
|
||
|
||
10-Feb-1997 DonRyan
|
||
Rewrote to implement SNMPv2 support.
|
||
|
||
--*/
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Include files //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
#include "globals.h"
|
||
#include "registry.h"
|
||
#include "contexts.h"
|
||
#include "regions.h"
|
||
#include "trapmgrs.h"
|
||
#include "snmpmgrs.h"
|
||
#include "snmpmgmt.h"
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Private procedures //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Public procedures //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
INT
|
||
InitRegistryNotifiers(
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Setup registry notifiers
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
Returns the number of events that have been registered successfully
|
||
|
||
--*/
|
||
{
|
||
DWORD nEvents = 0;
|
||
|
||
// on first call only create the default notifier
|
||
if (g_hDefaultRegNotifier == NULL)
|
||
g_hDefaultRegNotifier = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||
|
||
if (g_hDefaultKey == NULL)
|
||
{
|
||
RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
REG_KEY_SNMP_PARAMETERS,
|
||
0,
|
||
KEY_READ,
|
||
&g_hDefaultKey
|
||
);
|
||
}
|
||
|
||
// setup the default registry notifier
|
||
if (g_hDefaultRegNotifier &&
|
||
g_hDefaultKey &&
|
||
RegNotifyChangeKeyValue(
|
||
g_hDefaultKey,
|
||
TRUE,
|
||
REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
|
||
g_hDefaultRegNotifier,
|
||
TRUE
|
||
) == ERROR_SUCCESS)
|
||
{
|
||
SNMPDBG((SNMP_LOG_TRACE,
|
||
"SNMP: REG: Default reg notifier initialized successfully.\n"));
|
||
nEvents++;
|
||
}
|
||
|
||
#ifdef _POLICY
|
||
// on first call only create the policy notifier
|
||
if (g_hPolicyRegNotifier == NULL)
|
||
g_hPolicyRegNotifier = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||
|
||
if (g_hPolicyKey == NULL)
|
||
{
|
||
RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
REG_POLICY_ROOT,
|
||
0,
|
||
KEY_READ,
|
||
&g_hPolicyKey
|
||
);
|
||
}
|
||
|
||
// setup the policy registry notifier
|
||
if (g_hPolicyRegNotifier &&
|
||
g_hPolicyKey &&
|
||
RegNotifyChangeKeyValue(
|
||
g_hPolicyKey,
|
||
TRUE,
|
||
REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
|
||
g_hPolicyRegNotifier,
|
||
TRUE
|
||
) == ERROR_SUCCESS)
|
||
{
|
||
SNMPDBG((SNMP_LOG_TRACE,
|
||
"SNMP: REG: Policy reg notifier initialized successfully.\n"));
|
||
nEvents++;
|
||
}
|
||
|
||
SNMPDBG((SNMP_LOG_TRACE,
|
||
"SNMP: REG: Initialized notifiers ... %d.\n", nEvents));
|
||
#endif
|
||
|
||
return nEvents;
|
||
}
|
||
|
||
BOOL UnloadRegistryNotifiers();
|
||
|
||
INT
|
||
WaitOnRegNotification(
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Blocking call - waits for a notification that one of the registry parameters has change
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
Returns the notifyer index (0 for the termination event, !=0 for parameter change)
|
||
|
||
--*/
|
||
{
|
||
HANDLE hNotifiers[3]; // hack - we now (hardcoded) that we are not going to wait for more than three events.
|
||
DWORD dwNotifiers = 0;
|
||
DWORD retCode;
|
||
|
||
hNotifiers[dwNotifiers++] = g_hTerminationEvent;
|
||
|
||
if (g_hDefaultRegNotifier != NULL)
|
||
hNotifiers[dwNotifiers++] = g_hDefaultRegNotifier;
|
||
|
||
#ifdef _POLICY
|
||
if (g_hPolicyRegNotifier != NULL)
|
||
hNotifiers[dwNotifiers++] = g_hPolicyRegNotifier;
|
||
#endif
|
||
|
||
SNMPDBG((SNMP_LOG_WARNING,
|
||
"SNMP: REG: Will listen for params changes on %d notifiers.\n",
|
||
dwNotifiers));
|
||
|
||
retCode = WaitForMultipleObjects(
|
||
dwNotifiers,
|
||
hNotifiers,
|
||
FALSE,
|
||
INFINITE);
|
||
|
||
UnloadRegistryNotifiers();
|
||
|
||
return retCode;
|
||
}
|
||
|
||
/*++
|
||
Inplace parser for the string formatted OID.
|
||
It is done in O(n) where n is the length of the string formatted OID (two passes)
|
||
--*/
|
||
BOOL
|
||
ConvStringToOid(
|
||
LPTSTR pStr,
|
||
AsnObjectIdentifier *pOid)
|
||
{
|
||
LPTSTR pDup;
|
||
int iComp;
|
||
DWORD dwCompValue;
|
||
enum
|
||
{ DOT,
|
||
DIGIT
|
||
} state = DIGIT;
|
||
|
||
// no need to check for parameters consistency (internal call->correct call :o)
|
||
|
||
// check the consistency and determine the number of components
|
||
pOid->idLength = 0;
|
||
|
||
if (*pStr == _T('.')) // skip a possible leading '.'
|
||
pStr++;
|
||
|
||
for (pDup = pStr; *pDup != _T('\0'); pDup++)
|
||
{
|
||
switch(state)
|
||
{
|
||
case DOT:
|
||
// note: a trailing dot results in a trailing 0
|
||
if (*pDup == _T('.'))
|
||
{
|
||
pOid->idLength++;
|
||
state = DIGIT;
|
||
break;
|
||
}
|
||
// intentionally missing 'break'
|
||
case DIGIT:
|
||
if (*pDup < _T('0') || *pDup > _T('9'))
|
||
return FALSE;
|
||
state = DOT;
|
||
break;
|
||
}
|
||
}
|
||
// add one to the id length as a trailing dot might not be present
|
||
pOid->idLength++;
|
||
|
||
// accept oids with two components at least;
|
||
// alloc memory and check for success;
|
||
if (pOid->idLength < 2 ||
|
||
(pOid->ids = SnmpUtilMemAlloc(pOid->idLength * sizeof(UINT))) == NULL)
|
||
return FALSE;
|
||
|
||
// we have now enough buffer and a correct input string. Just convert it to OID
|
||
iComp = 0;
|
||
dwCompValue = 0;
|
||
for (pDup = pStr; *pDup != _T('\0'); pDup++)
|
||
{
|
||
if (*pDup == _T('.'))
|
||
{
|
||
pOid->ids[iComp++] = dwCompValue;
|
||
dwCompValue = 0;
|
||
}
|
||
else
|
||
{
|
||
dwCompValue = dwCompValue * 10 + (*pDup - _T('0'));
|
||
}
|
||
}
|
||
pOid->ids[iComp] = dwCompValue;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL
|
||
LoadScalarParameters(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Reads authentication trap flags key and manager timeout value.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY hKey;
|
||
LONG lStatus;
|
||
DWORD dwIndex;
|
||
DWORD dwNameSize;
|
||
DWORD dwValueSize;
|
||
DWORD dwValueType;
|
||
TCHAR szName[MAX_PATH];
|
||
TCHAR szValue[MAX_PATH];
|
||
LPTSTR pszKey = REG_KEY_SNMP_PARAMETERS;
|
||
BOOL bChangedSysID = FALSE;
|
||
|
||
// default value for the IsnmpNameResolutionRetries counter
|
||
// an address will resist to no more than MGRADDR_DYING (16 by default)
|
||
// consecutive name resolution failures.
|
||
snmpMgmtBase.AsnIntegerPool[IsnmpNameResolutionRetries].asnValue.number = MGRADDR_DYING;
|
||
|
||
// open registry subkey
|
||
lStatus = RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
pszKey,
|
||
0,
|
||
KEY_READ,
|
||
&hKey
|
||
);
|
||
|
||
// validate return code
|
||
if (lStatus == ERROR_SUCCESS)
|
||
{
|
||
// initialize
|
||
dwIndex = 0;
|
||
|
||
// loop until error or end of list
|
||
while (lStatus == ERROR_SUCCESS)
|
||
{
|
||
|
||
// initialize buffer sizes
|
||
dwNameSize = sizeof(szName) / sizeof(szName[0]); // size in number of TCHARs
|
||
dwValueSize = sizeof(szValue); // size in number of bytes
|
||
|
||
// read next value
|
||
lStatus = RegEnumValue(
|
||
hKey,
|
||
dwIndex,
|
||
szName,
|
||
&dwNameSize,
|
||
NULL,
|
||
&dwValueType,
|
||
(LPBYTE)szValue,
|
||
&dwValueSize
|
||
);
|
||
|
||
// validate return code
|
||
if (lStatus == ERROR_SUCCESS)
|
||
{
|
||
|
||
// validate name of value
|
||
if (!lstrcmpi(szName, REG_VALUE_AUTH_TRAPS))
|
||
{
|
||
// set the 'EnableAuthenTraps' in the internal management structure
|
||
mgmtISet(IsnmpEnableAuthenTraps, *((PDWORD)&szValue));
|
||
}
|
||
else if (!lstrcmpi(szName, REG_VALUE_MGRRES_COUNTER))
|
||
{
|
||
// set the 'NameResolutionRetries' in the internal management structure
|
||
mgmtISet(IsnmpNameResolutionRetries, *((PDWORD)&szValue));
|
||
}
|
||
|
||
// next
|
||
dwIndex++;
|
||
|
||
}
|
||
}
|
||
|
||
RegCloseKey(hKey);
|
||
}
|
||
|
||
// look into MIB2 subtree ..SNMP\Parameters\RFC1156Agent for sysObjectID parameter
|
||
lStatus = RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
REG_KEY_MIB2,
|
||
0,
|
||
KEY_READ,
|
||
&hKey
|
||
);
|
||
|
||
// validate return code
|
||
if (lStatus == ERROR_SUCCESS)
|
||
{
|
||
LPTSTR pszOid = szValue;
|
||
|
||
dwValueSize = sizeof(szValue); // size in number of bytes
|
||
|
||
// first, get the size of the buffer required for the sysObjectID parameter
|
||
lStatus = RegQueryValueEx(
|
||
hKey,
|
||
REG_VALUE_SYS_OBJECTID,
|
||
0,
|
||
&dwValueType,
|
||
(LPBYTE)pszOid,
|
||
&dwValueSize);
|
||
|
||
// the ERROR_MORE_DATA is the only error code we expect at this point
|
||
if (lStatus == ERROR_MORE_DATA)
|
||
{
|
||
pszOid = SnmpUtilMemAlloc(dwValueSize);
|
||
|
||
// if a buffer was set up correctly, go an read the oid value
|
||
if (pszOid != NULL)
|
||
{
|
||
lStatus = RegQueryValueEx(
|
||
hKey,
|
||
REG_VALUE_SYS_OBJECTID,
|
||
0,
|
||
&dwValueType,
|
||
(LPBYTE)pszOid,
|
||
&dwValueSize);
|
||
}
|
||
}
|
||
|
||
// at this point we should succeed
|
||
if (lStatus == ERROR_SUCCESS)
|
||
{
|
||
AsnObjectIdentifier sysObjectID;
|
||
// we have the string representation of the oid, convert it now to an AsnObjectIdentifier
|
||
|
||
// implement the convertion here, as I don't want to make this a public function in SNMPAPI.DLL
|
||
// otherwise I'll be forced to handle a lot of useless limit cases..
|
||
if (dwValueType == REG_SZ &&
|
||
ConvStringToOid(pszOid, &sysObjectID))
|
||
{
|
||
// don't free what has been alocated in ConvStringToOid as the buffer will be passed
|
||
// to the management variable below.
|
||
bChangedSysID = (mgmtOSet(OsnmpSysObjectID, &sysObjectID, FALSE) == ERROR_SUCCESS);
|
||
}
|
||
else
|
||
{
|
||
SNMPDBG((SNMP_LOG_WARNING,
|
||
"SNMP: SVC: LoadScalarParameters() - invalid type or value for sysObjectID param.\n"));
|
||
|
||
ReportSnmpEvent(
|
||
SNMP_EVENT_INVALID_ENTERPRISEOID,
|
||
0,
|
||
NULL,
|
||
0);
|
||
}
|
||
}
|
||
|
||
// cleanup the buffer if it was dynamically allocated
|
||
if (pszOid != szValue)
|
||
SnmpUtilMemFree(pszOid);
|
||
|
||
// cleanup the registry key
|
||
RegCloseKey(hKey);
|
||
}
|
||
|
||
if (!bChangedSysID)
|
||
{
|
||
mgmtOSet(OsnmpSysObjectID, SnmpSvcGetEnterpriseOID(), TRUE);
|
||
}
|
||
// all parameters here have default values, so there is no reason for this function to fail
|
||
// if a parameter could not be found into the registry, its default value will be considered.
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Public procedures //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
BOOL
|
||
LoadRegistryParameters(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Loads registry parameters.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
// first thing to do is to setup the registry notifiers. If we don't do this before reading
|
||
// the registry values we might not sense an initial change of the registry.
|
||
InitRegistryNotifiers();
|
||
|
||
// need to load first the scalar parameters especially to know how
|
||
// to handle further the name resolution
|
||
LoadScalarParameters();
|
||
|
||
// load managers
|
||
LoadPermittedManagers(TRUE);
|
||
|
||
// load trap destinations
|
||
LoadTrapDestinations(TRUE);
|
||
|
||
// load communities with dynamic update
|
||
LoadValidCommunities(TRUE);
|
||
|
||
// load subagents
|
||
LoadSubagents();
|
||
|
||
// determine regions
|
||
LoadSupportedRegions();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL
|
||
UnloadRegistryNotifiers(
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Unloads registry notifiers
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
Returns TRUE
|
||
|
||
--*/
|
||
{
|
||
if (g_hDefaultRegNotifier != NULL)
|
||
{
|
||
CloseHandle(g_hDefaultRegNotifier);
|
||
g_hDefaultRegNotifier = NULL;
|
||
}
|
||
#ifdef _POLICY
|
||
if (g_hPolicyRegNotifier != NULL)
|
||
{
|
||
CloseHandle(g_hPolicyRegNotifier);
|
||
g_hPolicyRegNotifier = NULL;
|
||
}
|
||
#endif
|
||
|
||
if (g_hDefaultKey != NULL)
|
||
{
|
||
RegCloseKey(g_hDefaultKey);
|
||
g_hDefaultKey = NULL;
|
||
}
|
||
#ifdef _POLICY
|
||
if (g_hPolicyKey != NULL)
|
||
{
|
||
RegCloseKey(g_hPolicyKey);
|
||
g_hPolicyKey = NULL;
|
||
}
|
||
#endif
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
UnloadRegistryParameters(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Unloads registry parameters.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
// unload the registry notifiers as the first thing to do
|
||
UnloadRegistryNotifiers();
|
||
|
||
// unload managers
|
||
UnloadPermittedManagers();
|
||
|
||
// unload trap destinations
|
||
UnloadTrapDestinations();
|
||
|
||
// unload communities
|
||
UnloadValidCommunities();
|
||
|
||
// unload subagents
|
||
UnloadSubagents();
|
||
|
||
// unload mib regions
|
||
UnloadSupportedRegions();
|
||
|
||
return TRUE;
|
||
}
|
||
|