summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pysnmp/hlapi/v3arch/auth.py8
-rw-r--r--pysnmp/proto/mpmod/rfc3412.py29
-rw-r--r--pysnmp/proto/secmod/rfc3414/service.py44
3 files changed, 49 insertions, 32 deletions
diff --git a/pysnmp/hlapi/v3arch/auth.py b/pysnmp/hlapi/v3arch/auth.py
index c4302d52..9392664f 100644
--- a/pysnmp/hlapi/v3arch/auth.py
+++ b/pysnmp/hlapi/v3arch/auth.py
@@ -294,7 +294,9 @@ class UsmUserData(object):
securityEngineId: :py:class:`~pysnmp.proto.rfc1902.OctetString`
The snmpEngineID of the authoritative SNMP engine to which a
dateRequest message is to be sent. Will be automatically
- discovered from peer if not given.
+ discovered from peer if not given, unless localized keys
+ are used. In the latter case *securityEngineId* must be
+ specified.
See :RFC:`3414#section-2.5.1` for technical explanation.
@@ -330,6 +332,10 @@ class UsmUserData(object):
* :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.
diff --git a/pysnmp/proto/mpmod/rfc3412.py b/pysnmp/proto/mpmod/rfc3412.py
index 20852db6..2062bf0e 100644
--- a/pysnmp/proto/mpmod/rfc3412.py
+++ b/pysnmp/proto/mpmod/rfc3412.py
@@ -234,33 +234,10 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
else:
if peerSnmpEngineData is None:
- # Force engineID discovery (rfc3414, 4)
- securityEngineId = securityName = self._emptyStr
- securityLevel = 1
-
- # Clear possible auth&priv flags
- headerData.setComponentByPosition(
- 2, self._msgFlags[msgFlags & 0xfc], verifyConstraints=False,
- matchTags=False, matchConstraints=False)
-
- # XXX
- scopedPDU = self._scopedPDU
- scopedPDU.setComponentByPosition(
- 0, self._emptyStr, verifyConstraints=False, matchTags=False,
- matchConstraints=False)
- scopedPDU.setComponentByPosition(1, contextName)
- scopedPDU.setComponentByPosition(2)
-
- # Use dead-empty PDU for engine-discovery report
- emptyPdu = pdu.clone()
- pMod.apiPDU.setDefaults(emptyPdu)
-
- scopedPDU.getComponentByPosition(2).setComponentByType(
- emptyPdu.tagSet, emptyPdu, verifyConstraints=False,
- matchTags=False, matchConstraints=False)
-
debug.logger & debug.FLAG_MP and debug.logger(
- 'prepareOutgoingMessage: force engineID discovery')
+ 'prepareOutgoingMessage: peer SNMP engine is not known')
+
+ securityEngineId = None
else:
securityEngineId = peerSnmpEngineData['securityEngineId']
diff --git a/pysnmp/proto/secmod/rfc3414/service.py b/pysnmp/proto/secmod/rfc3414/service.py
index 74bdaff9..9fdfe707 100644
--- a/pysnmp/proto/secmod/rfc3414/service.py
+++ b/pysnmp/proto/secmod/rfc3414/service.py
@@ -16,6 +16,7 @@ from pyasn1.type import namedtype
from pyasn1.type import univ
from pysnmp import debug
+from pysnmp.proto import api
from pysnmp.proto import errind
from pysnmp.proto import error
from pysnmp.proto import rfc1155
@@ -33,6 +34,9 @@ from pysnmp.proto.secmod.rfc3826.priv import aes
from pysnmp.proto.secmod.rfc7860.auth import hmacsha2
from pysnmp.smi.error import NoSuchInstanceError
+# API to rfc1905 protocol objects
+pMod = api.PROTOCOL_MODULES[api.SNMP_VERSION_2C]
+
# USM security params
@@ -304,6 +308,8 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
snmpEngineID = mibBuilder.importSymbols(
'__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax
+ msg = globalData
+
# 3.1.1
if securityStateReference is not None:
# 3.1.1a
@@ -361,7 +367,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
securityEngineID.prettyPrint(),
securityName, securityStateReference))
- elif securityName:
+ elif securityEngineID:
# 3.1.1b
try:
(usmUserName, usmUserSecurityName, usmUserAuthProtocol,
@@ -447,7 +453,35 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
raise error.StatusInformation(errorIndication=errind.invalidMsg)
else:
- # empty username used for engineID discovery
+ # 4. (start SNMP engine ID discovery)
+ securityEngineID = securityName = null
+ securityLevel = 1
+
+ scopedPDU.setComponentByPosition(
+ 0, null, verifyConstraints=False,
+ matchTags=False, matchConstraints=False)
+
+ headerData = msg.getComponentByPosition(1)
+
+ # Clear possible auth&priv flags
+ headerData.setComponentByPosition(
+ 2, univ.OctetString(hexValue='00'), verifyConstraints=False,
+ matchTags=False, matchConstraints=False
+ )
+
+ emptyPdu = scopedPDU.getComponentByPosition(2).getComponent()
+
+ # we edit the rest of the structures in-place because they
+ # are ours for as long as this stack lasts, however PDU
+ # is more persistent and should not be touched
+
+ emptyPdu = emptyPdu.clone()
+ pMod.apiPDU.setDefaults(emptyPdu)
+
+ scopedPDU.getComponentByPosition(2).setComponentByType(
+ emptyPdu.tagSet, emptyPdu, verifyConstraints=False,
+ matchTags=False, matchConstraints=False)
+
usmUserName = usmUserSecurityName = null
usmUserAuthProtocol = noauth.NoAuth.SERVICE_ID
usmUserPrivProtocol = nopriv.NoPriv.SERVICE_ID
@@ -456,6 +490,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
debug.logger & debug.FLAG_SM and debug.logger(
'__generateRequestOrResponseMsg: using blank USM info '
+ 'for peer SNMP engine ID discovery '
'usmUserName "%s" '
'usmUserSecurityName "%s" '
'usmUserAuthProtocol "%s" '
@@ -466,9 +501,8 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
usmUserName, usmUserSecurityName,
usmUserAuthProtocol, usmUserAuthKeyLocalized,
usmUserPrivProtocol, usmUserPrivKeyLocalized,
- securityEngineID.prettyPrint(), securityName))
-
- msg = globalData
+ securityEngineID and securityEngineID.prettyPrint(),
+ securityName))
# 3.1.2
if securityLevel == 3: