summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pysnmp/hlapi/auth.py8
-rw-r--r--pysnmp/proto/mpmod/rfc3412.py25
-rw-r--r--pysnmp/proto/secmod/rfc3414/service.py46
3 files changed, 50 insertions, 29 deletions
diff --git a/pysnmp/hlapi/auth.py b/pysnmp/hlapi/auth.py
index 13120a6d..e784eec8 100644
--- a/pysnmp/hlapi/auth.py
+++ b/pysnmp/hlapi/auth.py
@@ -268,7 +268,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.
@@ -304,6 +306,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 58f3acc0..bfee07f9 100644
--- a/pysnmp/proto/mpmod/rfc3412.py
+++ b/pysnmp/proto/mpmod/rfc3412.py
@@ -203,31 +203,14 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
# 7.1.9.a
if pdu.tagSet in rfc3411.unconfirmedClassPDUs:
securityEngineId = snmpEngineID
+
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)
+ debug.logger & debug.flagMP and debug.logger(
+ 'prepareOutgoingMessage: peer SNMP engine is not known')
- # Use dead-empty PDU for engine-discovery report
- emptyPdu = pdu.clone()
- pMod.apiPDU.setDefaults(emptyPdu)
+ securityEngineId = None
- scopedPDU.getComponentByPosition(2).setComponentByType(
- emptyPdu.tagSet, emptyPdu, verifyConstraints=False, matchTags=False, matchConstraints=False
- )
- debug.logger & debug.flagMP and debug.logger('prepareOutgoingMessage: force engineID discovery')
else:
securityEngineId = peerSnmpEngineData['securityEngineId']
diff --git a/pysnmp/proto/secmod/rfc3414/service.py b/pysnmp/proto/secmod/rfc3414/service.py
index ab125aa7..244e9324 100644
--- a/pysnmp/proto/secmod/rfc3414/service.py
+++ b/pysnmp/proto/secmod/rfc3414/service.py
@@ -13,13 +13,16 @@ from pysnmp.proto.secmod.rfc3826.priv import aes
from pysnmp.proto.secmod.rfc7860.auth import hmacsha2
from pysnmp.proto.secmod.eso.priv import des3, aes192, aes256
from pysnmp.smi.error import NoSuchInstanceError
-from pysnmp.proto import rfc1155, errind, error
+from pysnmp.proto import api, rfc1155, errind, error
from pysnmp import debug
from pyasn1.type import univ, namedtype, constraint
from pyasn1.codec.ber import encoder, decoder, eoo
from pyasn1.error import PyAsn1Error
from pyasn1.compat.octets import null
+# API to rfc1905 protocol objects
+pMod = api.protoModules[api.protoVersion2c]
+
# USM security params
@@ -224,6 +227,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
scopedPDU, securityStateReference):
mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder
snmpEngineID = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax
+ msg = globalData
# 3.1.1
if securityStateReference is not None:
@@ -271,7 +275,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
securityEngineID.prettyPrint(),
securityName, securityStateReference))
- elif securityName:
+ elif securityEngineID:
# 3.1.1b
try:
(usmUserName, usmUserSecurityName, usmUserAuthProtocol,
@@ -352,14 +356,43 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
)
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.serviceID
usmUserPrivProtocol = nopriv.NoPriv.serviceID
usmUserAuthKeyLocalized = usmUserPrivKeyLocalized = None
debug.logger & debug.flagSM and debug.logger(
- '__generateRequestOrResponseMsg: using blank USM info '
+ '__generateRequestOrResponseMsg: using blank USM info for peer '
+ 'SNMP engine ID discovery '
'usmUserName "%s" '
'usmUserSecurityName "%s" '
'usmUserAuthProtocol "%s" '
@@ -370,9 +403,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: