etingof / pysnmp

Python SNMP library
http://snmplabs.com/pysnmp/
BSD 2-Clause "Simplified" License
582 stars 200 forks source link

Unable to negotiate authoritative SNMP engine ID #308

Closed mvkraju4b1 closed 5 years ago

mvkraju4b1 commented 5 years ago

I was unable to get getcmd response from cisco router in gns3, where as i was able to get reply from a juniper olive device. "No SNMP response received before timeout" is the reply. When i tried to capture the packets in wire shark, i found the report pdu from juniper device contains the authoritative engine id, where as from cisco device, it was missing. Python code which i am running (taken from the examples), is below:

from pysnmp.hlapi import *

errorIndication, errorStatus, errorIndex, varBinds = next(
    getCmd(SnmpEngine(),
           UsmUserData('noauthuser'),
           UdpTransportTarget(('10.205.96.1', 161)),
           ContextData(),
           ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)))
)

if errorIndication:
    print(errorIndication)
elif errorStatus:
    print('%s at %s' % (errorStatus.prettyPrint(),
                        errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
else:
    for varBind in varBinds:
        print(' = '.join([x.prettyPrint() for x in varBind]))

So can anyone throw some light on why it happens so. When i tried to run the 'get' command on the said cisco device by using GetSnmp.exe from snmpsoft.com, i am getting the proper response. Only when using the above code, i was unable to get any response.

mvkraju4b1 commented 5 years ago

Infact, i have tried do run the above code on a physical cisco router, and it is not working. But as i have told, GetSnmp.exe works on it.

etingof commented 5 years ago

The code looks good. Try enabling pysnmp debugging to see the detailed exchange that happens with the router.

from pysnmp import debug

debug.setLogger(debug.Debug('all'))
pittsjl commented 5 years ago

I'm experiencing the same issue on a Cisco wireless controller running AireOS.

Python 3.7.3 PySNMP 4.4.11

#!/usr/bin/python3
from pysnmp.hlapi import *

from pysnmp import debug
# use specific flags or 'all' for full debugging
debug.setLogger(debug.Debug('all'))

username = 'username'
ipAddress = 'device'
authKey = 'authkey'
privKey = 'privkey'
communityName = 'community'

errorIndication, errorStatus, errorIndex, varBinds = next(
    getCmd(SnmpEngine(),
        #    CommunityData(communityName),
            UsmUserData(username, authKey, privKey,
                        authProtocol=usmHMACSHAAuthProtocol,
                        privProtocol=usmAesCfb128Protocol),
            UdpTransportTarget((ipAddress, 161)),
            ContextData(),
            ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
            ignoreNonIncreasingOid=True)
)

if errorIndication:
    print(errorIndication)
elif errorStatus:
    print('%s at %s' % (errorStatus.prettyPrint(),
                        errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
else:
    for varBind in varBinds:
        print(' = '.join([x.prettyPrint() for x in varBind]))

If I switch out UsmUserData() for CommunityData() to use SNMPv2c, it works correctly.

This the equivalent net-snmp command that works correctly against the same test device:

snmpwalk -Cc -v 3 -l authPriv -a SHA -x AES -A authkey -X privkey -u username device SNMPv2-MIB::sysDescr

Here is a snippet from the debug output:

2019-09-23 16:45:38,169 pysnmp: prepareDataElements: msg data msgVersion 3 msgID 10082918 securityModel 3
2019-09-23 16:45:38,170 pysnmp: processIncomingMsg: securityParameters
00000: 30 0E 04 00 02 01 00 02 01 00 04 00 04 00 04 00
2019-09-23 16:45:38,174 pysnmp: processIncomingMsg: UsmSecurityParameters:
 msgAuthoritativeEngineId=
 msgAuthoritativeEngineBoots=0
 msgAuthoritativeEngineTime=0
 msgUserName=
 msgAuthenticationParameters=
 msgPrivacyParameters=

2019-09-23 16:45:38,182 pysnmp: processIncomingMsg: cache write securityStateReference 5519077 by msgUserName
2019-09-23 16:45:38,183 pysnmp: processIncomingMsg: peer requested snmpEngineID discovery
2019-09-23 16:45:38,184 pysnmp: processIncomingMsg: null or malformed msgAuthoritativeEngineId
2019-09-23 16:45:38,187 pysnmp: processIncomingMsg: starting snmpEngineID discovery procedure
2019-09-23 16:45:38,198 pysnmp: StatusInformation: {'errorIndication': UnknownEngineID('Unknown SNMP engine ID encountered'),

(PySNMP) The SNMP "get-request" packet sent to the device for EngineID discovery (Reportable flag is unset):

Simple Network Management Protocol
    msgVersion: snmpv3 (3)
    msgGlobalData
        msgID: 14051419
        msgMaxSize: 65507
        msgFlags: 00
            .... .0.. = Reportable: Not set
            .... ..0. = Encrypted: Not set
            .... ...0 = Authenticated: Not set
        msgSecurityModel: USM (3)
    msgAuthoritativeEngineID: <MISSING>
    msgAuthoritativeEngineBoots: 0
    msgAuthoritativeEngineTime: 0
    msgUserName: 
    msgAuthenticationParameters: <MISSING>
    msgPrivacyParameters: <MISSING>
    msgData: plaintext (0)
        plaintext
            contextEngineID: <MISSING>
            contextName: 
            data: get-request (0)
                get-request
                    request-id: 13587404
                    error-status: noError (0)
                    error-index: 0
                    variable-bindings: 0 items

(PySNMP) SNMP "report" packet returned from device (msgAuthoritativeEngineID is missing):

Simple Network Management Protocol
    msgVersion: snmpv3 (3)
    msgGlobalData
        msgID: 14051419
        msgMaxSize: 4096
        msgFlags: 00
            .... .0.. = Reportable: Not set
            .... ..0. = Encrypted: Not set
            .... ...0 = Authenticated: Not set
        msgSecurityModel: USM (3)
    msgAuthoritativeEngineID: <MISSING>
    msgAuthoritativeEngineBoots: 0
    msgAuthoritativeEngineTime: 0
    msgUserName: 
    msgAuthenticationParameters: <MISSING>
    msgPrivacyParameters: <MISSING>
    msgData: plaintext (0)
        plaintext
            contextEngineID: 000037630000c997ab05010a
            contextName: 
            data: report (8)
                report
                    request-id: 13587404
                    error-status: noError (0)
                    error-index: 0
                    variable-bindings: 1 item

This repeats for a total of six tries before timing out with "No SNMP response received before timeout."

(Net-SNMP) The SNMP "get-request" packet sent to the device for EngineID discovery (Reportable flag is set):

Simple Network Management Protocol
    msgVersion: snmpv3 (3)
    msgGlobalData
        msgID: 422823601
        msgMaxSize: 65507
        msgFlags: 04
            .... .1.. = Reportable: Set
            .... ..0. = Encrypted: Not set
            .... ...0 = Authenticated: Not set
        msgSecurityModel: USM (3)
    msgAuthoritativeEngineID: <MISSING>
    msgAuthoritativeEngineBoots: 0
    msgAuthoritativeEngineTime: 0
    msgUserName: 
    msgAuthenticationParameters: <MISSING>
    msgPrivacyParameters: <MISSING>
    msgData: plaintext (0)
        plaintext
            contextEngineID: <MISSING>
            contextName: 
            data: get-request (0)
                get-request
                    request-id: 176323287
                    error-status: noError (0)
                    error-index: 0
                    variable-bindings: 0 items

(Net-SNMP) SNMP "report" packet returned from device (msgAuthoritativeEngineID is set):

Simple Network Management Protocol
    msgVersion: snmpv3 (3)
    msgGlobalData
        msgID: 422823601
        msgMaxSize: 4096
        msgFlags: 00
            .... .0.. = Reportable: Not set
            .... ..0. = Encrypted: Not set
            .... ...0 = Authenticated: Not set
        msgSecurityModel: USM (3)
    msgAuthoritativeEngineID: 000037630000c997ab05010a
    msgAuthoritativeEngineBoots: 1
    msgAuthoritativeEngineTime: 5968
    msgUserName: 
    msgAuthenticationParameters: <MISSING>
    msgPrivacyParameters: <MISSING>
    msgData: plaintext (0)
        plaintext
            contextEngineID: 000037630000c997ab05010a
            contextName: 
            data: report (8)
                report
                    request-id: 176323287
                    error-status: noError (0)
                    error-index: 0
                    variable-bindings: 1 item

The encrypted PDU packets follow this report packet showing a successful transaction.

mvkraju4b1 commented 5 years ago

Exactly...same is the case with my cisco IOS router as well. But interesting thing is, juniper device responds to the getcmd request(reportable flag not set) with a report pdu containing the authoritative engine id and subsequently with the required snmp object value. I don't know how this is happening. Please share the solution if the problem is solved with your cisco wireless controller.

etingof commented 5 years ago

Interesting! So pysnmp does not raise reportable flag on engine ID discovery it seems. Let me reproduce this locally...

etingof commented 5 years ago

I think commit c5cefab2cee5ae38d093743ef83a08641385b1cc should fix this issue. If you could test it before I release the entire thing - that would be helpful.

mvkraju4b1 commented 5 years ago

I think commit c5cefab should fix this issue. If you could test it before I release the entire thing - that would be helpful.

Yep.it is working now.Thanks.

pittsjl commented 5 years ago

Can confirm it's working. Thank heavens.

I wasn't sure at first if the reporting flag had anything to do with it, but it was the only thing different about the two SNMP packets I captured that stood out to me.

etingof commented 5 years ago

Awesomeness! And sorry for the regression!

I hope to push fixed version tonight.

pittsjl commented 5 years ago

Thank you. This is a great application and I appreciate all the work you put into it.

etingof commented 5 years ago

4.4.12 has been released on PyPI and GitHub.