summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelie <elie>2013-05-25 15:05:14 +0000
committerelie <elie>2013-05-25 15:05:14 +0000
commita1436307bc73418e0a2796d541b10e8cee215cf2 (patch)
tree1bb4a74925f54a04457cf3beec4ff3eda1fc2370
parentb3b0746e1f9ecff315473fe6420f498f813bd44d (diff)
downloadpysnmp-a1436307bc73418e0a2796d541b10e8cee215cf2.tar.gz
the userName parameter is now fully separated from securityName at
usmUserTable.
-rw-r--r--CHANGES6
-rw-r--r--pysnmp/entity/config.py18
-rw-r--r--pysnmp/entity/rfc3413/oneliner/auth.py21
-rw-r--r--pysnmp/entity/rfc3413/oneliner/cmdgen.py13
-rw-r--r--pysnmp/proto/secmod/rfc3414/service.py144
5 files changed, 135 insertions, 67 deletions
diff --git a/CHANGES b/CHANGES
index a5bc574..6deca4f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -35,9 +35,9 @@ Revision 4.2.5rc2
methods now accept optional authData parameter to remove specific entries
from LCD. This can be useful for modifying security parameters for
specific securityName.
-- SNMP credentials management reworked to allow multiple securityNames's in
- snmpCommunityEntry and usmUserEntry tables. Changes made to addV1System(),
- addV3User() functions as well as to their oneliner's wrappers.
+- SNMP credentials management reworked to separate userName from securityName
+ in snmpCommunityEntry and usmUserEntry tables. Changes made to addV1System(),
+ addV3User() functions as well as to their oneliner's wrappers.
- The contextEngineId parameter of config.addV3User() and auth.UsmUserData()
renamed into securityEngineId as it's semantically correct
- Oneliner transport target classes now support the getTransportInfo()
diff --git a/pysnmp/entity/config.py b/pysnmp/entity/config.py
index f5652a9..d351ea6 100644
--- a/pysnmp/entity/config.py
+++ b/pysnmp/entity/config.py
@@ -110,17 +110,20 @@ def __cookV3UserInfo(snmpEngine, securityName, securityEngineId):
return snmpEngineID, usmUserEntry, tblIdx1, pysnmpUsmSecretEntry, tblIdx2
-def addV3User(snmpEngine, securityName,
+def addV3User(snmpEngine, userName,
authProtocol=usmNoAuthProtocol, authKey=None,
privProtocol=usmNoPrivProtocol, privKey=None,
securityEngineId=None,
+ securityName=None,
# deprecated parameters follow
contextEngineId=None):
+ if securityName is None:
+ securityName = userName
if securityEngineId is None: # backward compatibility
securityEngineId = contextEngineId
( snmpEngineID, usmUserEntry, tblIdx1,
pysnmpUsmSecretEntry, tblIdx2 ) = __cookV3UserInfo(
- snmpEngine, securityName, securityEngineId
+ snmpEngine, userName, securityEngineId
)
# Load augmenting table before creating new row in base one
@@ -134,7 +137,7 @@ def addV3User(snmpEngine, securityName,
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((usmUserEntry.name + (13,) + tblIdx1, 'createAndGo'),
- (usmUserEntry.name + (2,) + tblIdx1, securityName),
+ (usmUserEntry.name + (2,) + tblIdx1, userName),
(usmUserEntry.name + (3,) + tblIdx1, securityName),
(usmUserEntry.name + (4,) + tblIdx1, zeroDotZero.name),
(usmUserEntry.name + (5,) + tblIdx1, authProtocol),
@@ -184,15 +187,18 @@ def addV3User(snmpEngine, securityName,
)
def delV3User(snmpEngine,
- securityName,
+ userName,
securityEngineId=None,
+ securityName=None,
# deprecated parameters follow
contextEngineId=None):
+ if securityName is None:
+ securityName = userName
if securityEngineId is None: # backward compatibility
securityEngineId = contextEngineId
( snmpEngineID, usmUserEntry, tblIdx1,
pysnmpUsmSecretEntry, tblIdx2 ) = __cookV3UserInfo(
- snmpEngine, securityName, securityEngineId
+ snmpEngine, userName, securityEngineId
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((usmUserEntry.name + (13,) + tblIdx1, 'destroy'),)
@@ -204,7 +210,7 @@ def delV3User(snmpEngine,
# Drop all derived rows
varBinds = initialVarBinds = (
(usmUserEntry.name + (1,), None), # usmUserEngineID
- (usmUserEntry.name + (3,), None), # usmSecurityName
+ (usmUserEntry.name + (2,), None), # usmUserName
(usmUserEntry.name + (4,), None) # usmUserCloneFrom
)
while varBinds:
diff --git a/pysnmp/entity/rfc3413/oneliner/auth.py b/pysnmp/entity/rfc3413/oneliner/auth.py
index 56333d6..a2ab5f3 100644
--- a/pysnmp/entity/rfc3413/oneliner/auth.py
+++ b/pysnmp/entity/rfc3413/oneliner/auth.py
@@ -55,14 +55,20 @@ class UsmUserData:
contextName = null
# the contextEngineId/contextName values stored here should
# be used for USM configuration only, not for PDU contents
- def __init__(self, securityName,
+ def __init__(self, userName,
authKey=None, privKey=None,
authProtocol=None, privProtocol=None,
securityEngineId=None,
- # deprecated parameters follow
+ # deprecated parameters begin
contextName=None,
- contextEngineId=None):
- self.securityName = securityName
+ contextEngineId=None,
+ # deprecated parameters end
+ securityName=None):
+ self.userName = userName
+ if securityName is None:
+ self.securityName = userName
+ else:
+ self.securityName = securityName
if authKey is not None:
self.authKey = authKey
@@ -96,10 +102,11 @@ class UsmUserData:
raise TypeError('%s is not hashable' % self.__class__.__name__)
def __repr__(self):
- return '%s("%s", <AUTHKEY>, <PRIVKEY>, %r, %r, %r)' % (
+ return '%s("%s", <AUTHKEY>, <PRIVKEY>, %r, %r, %r, securityName=%r)'%(
self.__class__.__name__,
- self.securityName,
+ self.userName,
self.authProtocol,
self.privProtocol,
- self.securityEngineId
+ self.securityEngineId,
+ self.securityName
)
diff --git a/pysnmp/entity/rfc3413/oneliner/cmdgen.py b/pysnmp/entity/rfc3413/oneliner/cmdgen.py
index 7566896..56d5fdc 100644
--- a/pysnmp/entity/rfc3413/oneliner/cmdgen.py
+++ b/pysnmp/entity/rfc3413/oneliner/cmdgen.py
@@ -56,14 +56,15 @@ class AsynCommandGenerator:
)
self.__knownAuths[authData.communityIndex] = authData
elif isinstance(authData, UsmUserData):
- authDataKey = authData.securityName, authData.securityEngineId
+ authDataKey = authData.userName, authData.securityEngineId
if authDataKey not in self.__knownAuths:
config.addV3User(
self.snmpEngine,
- authData.securityName,
+ authData.userName,
authData.authProtocol, authData.authKey,
authData.privProtocol, authData.privKey,
- authData.securityEngineId
+ authData.securityEngineId,
+ securityName=authData.securityName
)
self.__knownAuths[authDataKey] = authData
else:
@@ -121,7 +122,7 @@ class AsynCommandGenerator:
if isinstance(authData, CommunityData):
authDataKey = authData.communityIndex
elif isinstance(authData, UsmUserData):
- authDataKey = authData.securityName, authData.securityEngineId
+ authDataKey = authData.userName, authData.securityEngineId
else:
raise error.PySnmpError('Unsupported authentication object')
if authDataKey in self.__knownAuths:
@@ -144,7 +145,7 @@ class AsynCommandGenerator:
elif isinstance(authDataX, UsmUserData):
config.delV3User(
self.snmpEngine,
- authDataX.securityName,
+ authDataX.userName,
authDataX.securityEngineId
)
else:
@@ -161,7 +162,7 @@ class AsynCommandGenerator:
)
paramsNames.add(paramsName)
else:
- raise error.PySnmpError('Unknown target %s/%s/%s' % paramsKey)
+ raise error.PySnmpError('Unknown target %s' % paramsKey)
addrKeys = [ x for x in self.__knownTransportAddrs if x[0] == paramsName ]
diff --git a/pysnmp/proto/secmod/rfc3414/service.py b/pysnmp/proto/secmod/rfc3414/service.py
index bc44b15..6284755 100644
--- a/pysnmp/proto/secmod/rfc3414/service.py
+++ b/pysnmp/proto/secmod/rfc3414/service.py
@@ -46,20 +46,67 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
self.__timeline = {}
self.__timelineExpQueue = {}
self.__expirationTimer = 0
+ self.__paramsBranchId = -1
+
+ def __sec2usr(self, snmpEngine, securityName, securityEngineID=None):
+ usmUserEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMP-USER-BASED-SM-MIB', 'usmUserEngineID')
+ if self.__paramsBranchId != usmUserEngineID.branchVersionId:
+ usmUserName, usmUserSecurityName = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMP-USER-BASED-SM-MIB', 'usmUserName', 'usmUserSecurityName')
+
+ self.__securityToUserMap = {}
+
+ nextMibNode = usmUserEngineID
+ while 1:
+ try:
+ nextMibNode = usmUserEngineID.getNextNode(
+ nextMibNode.name
+ )
+ except NoSuchInstanceError:
+ self.__paramsBranchId = usmUserEngineID.branchVersionId
+ debug.logger & debug.flagSM and debug.logger('_sec2usr: built snmpEngineId + securityName to userName map, version %s: %r' % (self.__paramsBranchId, self.__securityToUserMap))
+ break
+
+ instId = nextMibNode.name[len(usmUserSecurityName.name):]
+
+ __engineID = usmUserEngineID.getNode(usmUserEngineID.name + instId).syntax
+ __userName = usmUserName.getNode(usmUserName.name + instId).syntax
+ __securityName = usmUserSecurityName.getNode(usmUserSecurityName.name + instId).syntax
+
+ k = __engineID, __securityName
+
+ # first (lesser) securityName wins
+ if k not in self.__securityToUserMap:
+ self.__securityToUserMap[k] = __userName
+
+ if securityEngineID is None:
+ snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')
+ securityEngineID = snmpEngineID.syntax
+
+ userName = self.__securityToUserMap.get(
+ (securityEngineID, securityName), securityName
+ )
+
+ debug.logger & debug.flagSM and debug.logger('_sec2usr: using userName %r for snmpEngineId %r, securityName %r' % (userName, securityEngineID, securityName))
+
+ return userName
def __getUserInfo(
- self, mibInstrumController, securityEngineID, securityName
+ self, mibInstrumController, securityEngineID, userName
):
usmUserEntry, = mibInstrumController.mibBuilder.importSymbols(
'SNMP-USER-BASED-SM-MIB', 'usmUserEntry'
- )
+ )
tblIdx = usmUserEntry.getInstIdFromIndices(
- securityEngineID, securityName
- )
- # Get protocols
+ securityEngineID, userName
+ )
+ # Get userName & securityName
+ usmUserName = usmUserEntry.getNode(
+ usmUserEntry.name + (2,) + tblIdx
+ ).syntax
usmUserSecurityName = usmUserEntry.getNode(
usmUserEntry.name + (3,) + tblIdx
- ).syntax
+ ).syntax
+ # Get protocols
usmUserAuthProtocol = usmUserEntry.getNode(
usmUserEntry.name + (5,) + tblIdx
).syntax
@@ -77,65 +124,66 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
pysnmpUsmKeyEntry.name + (2,) + tblIdx
).syntax
return (
- usmUserSecurityName, # XXX function needed?
+ usmUserName,
+ usmUserSecurityName,
usmUserAuthProtocol,
pysnmpUsmKeyAuthLocalized,
usmUserPrivProtocol,
pysnmpUsmKeyPrivLocalized
- )
+ )
def __cloneUserInfo(
- self, mibInstrumController, securityEngineID, securityName
+ self, mibInstrumController, securityEngineID, userName
):
snmpEngineID, = mibInstrumController.mibBuilder.importSymbols(
'__SNMP-FRAMEWORK-MIB', 'snmpEngineID'
- )
+ )
# Proto entry
usmUserEntry, = mibInstrumController.mibBuilder.importSymbols(
'SNMP-USER-BASED-SM-MIB', 'usmUserEntry'
- )
+ )
tblIdx1 = usmUserEntry.getInstIdFromIndices(
- snmpEngineID.syntax, securityName
- )
+ snmpEngineID.syntax, userName
+ )
# Get proto protocols
usmUserName = usmUserEntry.getNode(
usmUserEntry.name + (2,) + tblIdx1
- )
+ )
usmUserSecurityName = usmUserEntry.getNode(
usmUserEntry.name + (3,) + tblIdx1
- )
+ )
usmUserCloneFrom = usmUserEntry.getNode(
usmUserEntry.name + (4,) + tblIdx1
- )
+ )
usmUserAuthProtocol = usmUserEntry.getNode(
usmUserEntry.name + (5,) + tblIdx1
- )
+ )
usmUserPrivProtocol = usmUserEntry.getNode(
usmUserEntry.name + (8,) + tblIdx1
- )
+ )
# Get proto keys
pysnmpUsmKeyEntry, = mibInstrumController.mibBuilder.importSymbols(
'PYSNMP-USM-MIB', 'pysnmpUsmKeyEntry'
- )
+ )
pysnmpUsmKeyAuth = pysnmpUsmKeyEntry.getNode(
pysnmpUsmKeyEntry.name + (3,) + tblIdx1
- )
+ )
pysnmpUsmKeyPriv = pysnmpUsmKeyEntry.getNode(
pysnmpUsmKeyEntry.name + (4,) + tblIdx1
- )
+ )
# Create new row from proto values
tblIdx2 = usmUserEntry.getInstIdFromIndices(
- securityEngineID, securityName
- )
+ securityEngineID, userName
+ )
# New row
mibInstrumController.writeVars(
((usmUserEntry.name + (13,) + tblIdx2, 4),)
- )
+ )
- # Set usernames
+ # Set user&securityNames
usmUserEntry.getNode(
usmUserEntry.name + (2,) + tblIdx2
).syntax = usmUserName.syntax
@@ -192,12 +240,13 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
if localPrivKey is not None:
pysnmpUsmKeyPrivLocalized.syntax = pysnmpUsmKeyPrivLocalized.syntax.clone(localPrivKey)
return (
- usmUserSecurityName.syntax, # XXX function needed?
+ usmUserName.syntax,
+ usmUserSecurityName.syntax,
usmUserAuthProtocol.syntax,
pysnmpUsmKeyAuthLocalized.syntax,
usmUserPrivProtocol.syntax,
pysnmpUsmKeyPrivLocalized.syntax
- )
+ )
def __generateRequestOrResponseMsg(
self,
@@ -240,13 +289,15 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
# 3.1.1b
try:
( usmUserName,
+ usmUserSecurityName,
usmUserAuthProtocol,
usmUserAuthKeyLocalized,
usmUserPrivProtocol,
usmUserPrivKeyLocalized ) = self.__getUserInfo(
snmpEngine.msgAndPduDsp.mibInstrumController,
- securityEngineID, securityName
- )
+ securityEngineID,
+ self.__sec2usr(snmpEngine, securityName, securityEngineID)
+ )
debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: read user info')
except NoSuchInstanceError:
pysnmpUsmDiscovery, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__PYSNMP-USM-MIB', 'pysnmpUsmDiscovery')
@@ -254,14 +305,15 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
if not __reportUnknownName:
try:
( usmUserName,
+ usmUserSecurityName,
usmUserAuthProtocol,
usmUserAuthKeyLocalized,
usmUserPrivProtocol,
usmUserPrivKeyLocalized ) = self.__cloneUserInfo(
snmpEngine.msgAndPduDsp.mibInstrumController,
securityEngineID,
- securityName
- )
+ self.__sec2usr(snmpEngine, securityName)
+ )
except NoSuchInstanceError:
__reportUnknownName = 1
@@ -278,7 +330,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
usmUserAuthKeyLocalized = usmUserPrivKeyLocalized = None
debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: use empty USM data')
- debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: local user usmUserName %r usmUserAuthProtocol %s usmUserPrivProtocol %s securityEngineID %r securityName %r' % (usmUserName, usmUserAuthProtocol, usmUserPrivProtocol, securityEngineID, securityName))
+ debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: local usmUserName %r usmUserSecurityName %r usmUserAuthProtocol %s usmUserPrivProtocol %s securityEngineID %r securityName %r' % (usmUserName, usmUserSecurityName, usmUserAuthProtocol, usmUserPrivProtocol, securityEngineID, securityName))
msg = globalData
@@ -360,14 +412,14 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
usmUserPrivKeyLocalized,
( snmpEngineBoots, snmpEngineTime, None ),
dataToEncrypt
- )
+ )
securityParameters.setComponentByPosition(
5, privParameters, verifyConstraints=False
- )
+ )
scopedPDUData.setComponentByPosition(
1, encryptedData, verifyConstraints=False
- )
+ )
debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: scopedPDU ciphered into %s' % debug.hexdump(encryptedData))
@@ -380,18 +432,18 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
# 3.1.5
securityParameters.setComponentByPosition(
0, securityEngineID, verifyConstraints=False
- )
+ )
securityParameters.setComponentByPosition(
1, snmpEngineBoots, verifyConstraints=False
- )
+ )
securityParameters.setComponentByPosition(
2, snmpEngineTime, verifyConstraints=False
- )
+ )
# 3.1.7
securityParameters.setComponentByPosition(
3, usmUserName, verifyConstraints=False
- )
+ )
# 3.1.8a
if securityLevel == 3 or securityLevel == 2:
@@ -615,7 +667,8 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
if msgUserName:
# 3.2.4
try:
- ( usmUserSecurityName,
+ ( usmUserName,
+ usmUserSecurityName,
usmUserAuthProtocol,
usmUserAuthKeyLocalized,
usmUserPrivProtocol,
@@ -623,14 +676,15 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
snmpEngine.msgAndPduDsp.mibInstrumController,
msgAuthoritativeEngineID,
msgUserName
- )
+ )
debug.logger & debug.flagSM and debug.logger('processIncomingMsg: read user info from LCD')
except NoSuchInstanceError:
pysnmpUsmDiscoverable, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__PYSNMP-USM-MIB', 'pysnmpUsmDiscoverable')
__reportUnknownName = not pysnmpUsmDiscoverable.syntax
if not __reportUnknownName:
try:
- ( usmUserSecurityName,
+ ( usmUserName,
+ usmUserSecurityName,
usmUserAuthProtocol,
usmUserAuthKeyLocalized,
usmUserPrivProtocol,
@@ -638,7 +692,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
snmpEngine.msgAndPduDsp.mibInstrumController,
msgAuthoritativeEngineID,
msgUserName
- )
+ )
debug.logger & debug.flagSM and debug.logger('processIncomingMsg: cloned user info')
except NoSuchInstanceError:
__reportUnknownName = 1
@@ -663,7 +717,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
usmUserPrivProtocol = nopriv.NoPriv.serviceID
usmUserAuthKeyLocalized = usmUserPrivKeyLocalized = None
- debug.logger & debug.flagSM and debug.logger('processIncomingMsg: now have usmUserSecurityName %s usmUserAuthProtocol %s usmUserPrivProtocol %s for msgUserName %s' % (usmUserSecurityName, usmUserAuthProtocol, usmUserPrivProtocol, msgUserName))
+ debug.logger & debug.flagSM and debug.logger('processIncomingMsg: now have usmUserName %r usmUserSecurityName %r usmUserAuthProtocol %r usmUserPrivProtocol %r for msgUserName %r' % (usmUserName, usmUserSecurityName, usmUserAuthProtocol, usmUserPrivProtocol, msgUserName))
# 3.2.11 (moved up here to let Reports be authenticated & encrypted)
self._cache.pop(securityStateReference)
@@ -673,7 +727,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
usmUserAuthKeyLocalized=usmUserAuthKeyLocalized,
usmUserPrivProtocol=usmUserPrivProtocol,
usmUserPrivKeyLocalized=usmUserPrivKeyLocalized
- )
+ )
# 3.2.5
if msgAuthoritativeEngineID == snmpEngineID: