summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Etingof <etingof@gmail.com>2019-08-11 00:22:08 +0200
committerGitHub <noreply@github.com>2019-08-11 00:22:08 +0200
commit3488150a26636a7d0395769bdedd8c1b183f1f62 (patch)
tree44275f95990d37e047e664f50448a0a04807c69f
parent6049b0cfc4b34ded72da44a8c97c56799c00127c (diff)
downloadpysnmp-git-3488150a26636a7d0395769bdedd8c1b183f1f62.tar.gz
Introduce "wildcard" SNMP engine ID (#297)
This change introduces "wildcard" SNMP engine ID (0x00000000). Right before deciding on firing up SNMP engine ID discovery and key localization procedure, originating SNMP engine will check for the presence of this magical engine ID (5 zeros), if it is present in LCD along with the user name being used, localized keys from that entry will be used. Does this have security implications?
-rw-r--r--pysnmp/hlapi/auth.py20
-rw-r--r--pysnmp/proto/secmod/rfc3414/service.py83
2 files changed, 73 insertions, 30 deletions
diff --git a/pysnmp/hlapi/auth.py b/pysnmp/hlapi/auth.py
index e784eec8..735d85df 100644
--- a/pysnmp/hlapi/auth.py
+++ b/pysnmp/hlapi/auth.py
@@ -305,11 +305,6 @@ class UsmUserData(object):
* :py:class:`~pysnmp.hlapi.usmKeyTypeMaster`
* :py:class:`~pysnmp.hlapi.usmKeyTypeLocalized`
-
- If `~pysnmp.hlapi.usmKeyTypeLocalized` is used, peer SNMP engine ID
- discovery mechanism can't be leveraged for key localization, so
- *securityEngineId* must be given by local configuration.
-
privKeyType: :py:class:`int`
Type of `privKey` material. See :RFC:`3414#section-2.6` for
technical explanation.
@@ -320,6 +315,21 @@ class UsmUserData(object):
* :py:class:`~pysnmp.hlapi.usmKeyTypeMaster`
* :py:class:`~pysnmp.hlapi.usmKeyTypeLocalized`
+ Notes
+ -----
+ If `~pysnmp.hlapi.usmKeyTypeLocalized` is used when running a
+ non-authoritative SNMP engine, USM key localization mechanism
+ is not invoked. As a consequence, local SNMP engine configuration
+ won't get automatically populated with remote SNMP engine's
+ *securityEngineId*.
+
+ Therefore peer SNMP engine's *securityEngineId* must be added
+ to local configuration and associated with its localized keys.
+
+ Alternatively, the magic *securityEngineId* value of five zeros
+ (*0x0000000000*) can be used to refer to the localized keys that
+ should be used with any unknown remote SNMP engine. This feature
+ is specific to pysnmp.
Examples
--------
diff --git a/pysnmp/proto/secmod/rfc3414/service.py b/pysnmp/proto/secmod/rfc3414/service.py
index 244e9324..be2515ec 100644
--- a/pysnmp/proto/secmod/rfc3414/service.py
+++ b/pysnmp/proto/secmod/rfc3414/service.py
@@ -59,6 +59,11 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
aes256.Aes256.serviceID: aes256.Aes256(), # non-standard
nopriv.NoPriv.serviceID: nopriv.NoPriv()}
+ # If this, normally impossible, SNMP engine ID is present in LCD, we will use
+ # its master/localized keys when preparing SNMP message towards any unknown peer
+ # SNMP engine
+ wildcardSecurityEngineId = pMod.OctetString(hexValue='0000000000')
+
def __init__(self):
AbstractSecurityModel.__init__(self)
self.__securityParametersSpec = UsmSecurityParameters()
@@ -278,13 +283,25 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
elif securityEngineID:
# 3.1.1b
try:
- (usmUserName, usmUserSecurityName, usmUserAuthProtocol,
- usmUserAuthKeyLocalized, usmUserPrivProtocol,
- usmUserPrivKeyLocalized) = self.__getUserInfo(
- snmpEngine.msgAndPduDsp.mibInstrumController,
- securityEngineID,
- self.__sec2usr(snmpEngine, securityName, securityEngineID)
- )
+ try:
+ (usmUserName, usmUserSecurityName, usmUserAuthProtocol,
+ usmUserAuthKeyLocalized, usmUserPrivProtocol,
+ usmUserPrivKeyLocalized) = self.__getUserInfo(
+ snmpEngine.msgAndPduDsp.mibInstrumController,
+ securityEngineID,
+ self.__sec2usr(snmpEngine, securityName,
+ securityEngineID)
+ )
+
+ except NoSuchInstanceError:
+ (usmUserName, usmUserSecurityName, usmUserAuthProtocol,
+ usmUserAuthKeyLocalized, usmUserPrivProtocol,
+ usmUserPrivKeyLocalized) = self.__getUserInfo(
+ snmpEngine.msgAndPduDsp.mibInstrumController,
+ self.wildcardSecurityEngineId,
+ self.__sec2usr(snmpEngine, securityName,
+ self.wildcardSecurityEngineId)
+ )
debug.logger & debug.flagSM and debug.logger(
'__generateRequestOrResponseMsg: found USM user entry '
@@ -743,28 +760,44 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
snmpEngine.msgAndPduDsp.mibInstrumController,
msgAuthoritativeEngineId, msgUserName
)
- debug.logger & debug.flagSM and debug.logger('processIncomingMsg: read user info from LCD')
+ debug.logger & debug.flagSM and debug.logger(
+ 'processIncomingMsg: read user info from LCD')
except NoSuchInstanceError:
- debug.logger & debug.flagSM and debug.logger(
- 'processIncomingMsg: unknown securityEngineID %r msgUserName %r' % (
- msgAuthoritativeEngineId, msgUserName))
+ try:
+ (usmUserName,
+ usmUserSecurityName,
+ usmUserAuthProtocol,
+ usmUserAuthKeyLocalized,
+ usmUserPrivProtocol,
+ usmUserPrivKeyLocalized) = self.__getUserInfo(
+ snmpEngine.msgAndPduDsp.mibInstrumController,
+ self.wildcardSecurityEngineId, msgUserName
+ )
+ debug.logger & debug.flagSM and debug.logger(
+ 'processIncomingMsg: read wildcard user info from LCD')
- usmStatsUnknownUserNames, = mibBuilder.importSymbols(
- '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames')
- usmStatsUnknownUserNames.syntax += 1
+ except NoSuchInstanceError:
- raise error.StatusInformation(
- errorIndication=errind.unknownSecurityName,
- oid=usmStatsUnknownUserNames.name,
- val=usmStatsUnknownUserNames.syntax,
- securityStateReference=securityStateReference,
- securityLevel=securityLevel,
- contextEngineId=contextEngineId,
- contextName=contextName,
- msgUserName=msgUserName,
- maxSizeResponseScopedPDU=maxSizeResponseScopedPDU
- )
+ debug.logger & debug.flagSM and debug.logger(
+ 'processIncomingMsg: unknown securityEngineID %r msgUserName %r' % (
+ msgAuthoritativeEngineId, msgUserName))
+
+ usmStatsUnknownUserNames, = mibBuilder.importSymbols(
+ '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames')
+ usmStatsUnknownUserNames.syntax += 1
+
+ raise error.StatusInformation(
+ errorIndication=errind.unknownSecurityName,
+ oid=usmStatsUnknownUserNames.name,
+ val=usmStatsUnknownUserNames.syntax,
+ securityStateReference=securityStateReference,
+ securityLevel=securityLevel,
+ contextEngineId=contextEngineId,
+ contextName=contextName,
+ msgUserName=msgUserName,
+ maxSizeResponseScopedPDU=maxSizeResponseScopedPDU
+ )
except PyAsn1Error:
debug.logger & debug.flagSM and debug.logger('processIncomingMsg: %s' % (sys.exc_info()[1],))