diff options
author | Ilya Etingof <etingof@gmail.com> | 2019-08-11 00:22:08 +0200 |
---|---|---|
committer | Ilya Etingof <etingof@gmail.com> | 2019-08-11 00:29:42 +0200 |
commit | 61cda3803e5f12d34dafd8359a9071353eac83b6 (patch) | |
tree | 920ce6fc41f794582282dc99071854dc18be5b8e | |
parent | e19c04d20befd6b7d12aecfa857e998219dd0881 (diff) | |
download | pysnmp-git-61cda3803e5f12d34dafd8359a9071353eac83b6.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/v3arch/auth.py | 20 | ||||
-rw-r--r-- | pysnmp/proto/secmod/rfc3414/service.py | 83 |
2 files changed, 74 insertions, 29 deletions
diff --git a/pysnmp/hlapi/v3arch/auth.py b/pysnmp/hlapi/v3arch/auth.py index 9392664f..d93e30af 100644 --- a/pysnmp/hlapi/v3arch/auth.py +++ b/pysnmp/hlapi/v3arch/auth.py @@ -331,11 +331,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. @@ -346,6 +341,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 9fdfe707..de0330c9 100644 --- a/pysnmp/proto/secmod/rfc3414/service.py +++ b/pysnmp/proto/secmod/rfc3414/service.py @@ -93,6 +93,11 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): nopriv.NoPriv.SERVICE_ID: 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 + WILDCARD_SECURITY_ENGINE_ID = pMod.OctetString(hexValue='0000000000') + def __init__(self): AbstractSecurityModel.__init__(self) self._securityParametersSpec = UsmSecurityParameters() @@ -370,13 +375,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.WILDCARD_SECURITY_ENGINE_ID, + self._sec2usr(snmpEngine, securityName, + self.WILDCARD_SECURITY_ENGINE_ID) + ) debug.logger & debug.FLAG_SM and debug.logger( '__generateRequestOrResponseMsg: found USM user entry ' @@ -881,29 +898,47 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): snmpEngine.msgAndPduDsp.mibInstrumController, msgAuthoritativeEngineId, msgUserName ) + debug.logger & debug.FLAG_SM and debug.logger( 'processIncomingMsg: read user info from LCD') except NoSuchInstanceError: - debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: unknown securityEngineID %r ' - 'msgUserName %r' % (msgAuthoritativeEngineId, msgUserName)) + try: + (usmUserName, + usmUserSecurityName, + usmUserAuthProtocol, + usmUserAuthKeyLocalized, + usmUserPrivProtocol, + usmUserPrivKeyLocalized) = self._getUserInfo( + snmpEngine.msgAndPduDsp.mibInstrumController, + self.WILDCARD_SECURITY_ENGINE_ID, msgUserName + ) - usmStatsUnknownUserNames, = mibBuilder.importSymbols( - '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames') - usmStatsUnknownUserNames.syntax += 1 + debug.logger & debug.FLAG_SM and debug.logger( + 'processIncomingMsg: read wildcard user info from LCD') - 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 NoSuchInstanceError: + + debug.logger & debug.FLAG_SM 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 as exc: debug.logger & debug.FLAG_SM and debug.logger( |