1## This file is part of Scapy
2## See http://www.secdev.org/projects/scapy for more informations
3## Copyright (C) Philippe Biondi <phil@secdev.org>
4## This program is published under a GPLv2 license
5
6"""
7SNMP (Simple Network Management Protocol).
8"""
9
10from __future__ import print_function
11from scapy.packet import *
12from scapy.asn1packet import *
13from scapy.asn1fields import *
14from scapy.asn1.asn1 import *
15from scapy.asn1.ber import *
16from scapy.sendrecv import sr1
17from scapy.volatile import *
18from scapy.layers.inet import UDP, IP, ICMP
19
20##########
21## SNMP ##
22##########
23
24######[ ASN1 class ]######
25
26class ASN1_Class_SNMP(ASN1_Class_UNIVERSAL):
27    name="SNMP"
28    PDU_GET = 0xa0
29    PDU_NEXT = 0xa1
30    PDU_RESPONSE = 0xa2
31    PDU_SET = 0xa3
32    PDU_TRAPv1 = 0xa4
33    PDU_BULK = 0xa5
34    PDU_INFORM = 0xa6
35    PDU_TRAPv2 = 0xa7
36
37
38class ASN1_SNMP_PDU_GET(ASN1_SEQUENCE):
39    tag = ASN1_Class_SNMP.PDU_GET
40
41class ASN1_SNMP_PDU_NEXT(ASN1_SEQUENCE):
42    tag = ASN1_Class_SNMP.PDU_NEXT
43
44class ASN1_SNMP_PDU_RESPONSE(ASN1_SEQUENCE):
45    tag = ASN1_Class_SNMP.PDU_RESPONSE
46
47class ASN1_SNMP_PDU_SET(ASN1_SEQUENCE):
48    tag = ASN1_Class_SNMP.PDU_SET
49
50class ASN1_SNMP_PDU_TRAPv1(ASN1_SEQUENCE):
51    tag = ASN1_Class_SNMP.PDU_TRAPv1
52
53class ASN1_SNMP_PDU_BULK(ASN1_SEQUENCE):
54    tag = ASN1_Class_SNMP.PDU_BULK
55
56class ASN1_SNMP_PDU_INFORM(ASN1_SEQUENCE):
57    tag = ASN1_Class_SNMP.PDU_INFORM
58
59class ASN1_SNMP_PDU_TRAPv2(ASN1_SEQUENCE):
60    tag = ASN1_Class_SNMP.PDU_TRAPv2
61
62
63######[ BER codecs ]#######
64
65class BERcodec_SNMP_PDU_GET(BERcodec_SEQUENCE):
66    tag = ASN1_Class_SNMP.PDU_GET
67
68class BERcodec_SNMP_PDU_NEXT(BERcodec_SEQUENCE):
69    tag = ASN1_Class_SNMP.PDU_NEXT
70
71class BERcodec_SNMP_PDU_RESPONSE(BERcodec_SEQUENCE):
72    tag = ASN1_Class_SNMP.PDU_RESPONSE
73
74class BERcodec_SNMP_PDU_SET(BERcodec_SEQUENCE):
75    tag = ASN1_Class_SNMP.PDU_SET
76
77class BERcodec_SNMP_PDU_TRAPv1(BERcodec_SEQUENCE):
78    tag = ASN1_Class_SNMP.PDU_TRAPv1
79
80class BERcodec_SNMP_PDU_BULK(BERcodec_SEQUENCE):
81    tag = ASN1_Class_SNMP.PDU_BULK
82
83class BERcodec_SNMP_PDU_INFORM(BERcodec_SEQUENCE):
84    tag = ASN1_Class_SNMP.PDU_INFORM
85
86class BERcodec_SNMP_PDU_TRAPv2(BERcodec_SEQUENCE):
87    tag = ASN1_Class_SNMP.PDU_TRAPv2
88
89
90
91######[ ASN1 fields ]######
92
93class ASN1F_SNMP_PDU_GET(ASN1F_SEQUENCE):
94    ASN1_tag = ASN1_Class_SNMP.PDU_GET
95
96class ASN1F_SNMP_PDU_NEXT(ASN1F_SEQUENCE):
97    ASN1_tag = ASN1_Class_SNMP.PDU_NEXT
98
99class ASN1F_SNMP_PDU_RESPONSE(ASN1F_SEQUENCE):
100    ASN1_tag = ASN1_Class_SNMP.PDU_RESPONSE
101
102class ASN1F_SNMP_PDU_SET(ASN1F_SEQUENCE):
103    ASN1_tag = ASN1_Class_SNMP.PDU_SET
104
105class ASN1F_SNMP_PDU_TRAPv1(ASN1F_SEQUENCE):
106    ASN1_tag = ASN1_Class_SNMP.PDU_TRAPv1
107
108class ASN1F_SNMP_PDU_BULK(ASN1F_SEQUENCE):
109    ASN1_tag = ASN1_Class_SNMP.PDU_BULK
110
111class ASN1F_SNMP_PDU_INFORM(ASN1F_SEQUENCE):
112    ASN1_tag = ASN1_Class_SNMP.PDU_INFORM
113
114class ASN1F_SNMP_PDU_TRAPv2(ASN1F_SEQUENCE):
115    ASN1_tag = ASN1_Class_SNMP.PDU_TRAPv2
116
117
118
119######[ SNMP Packet ]######
120
121SNMP_error = { 0: "no_error",
122               1: "too_big",
123               2: "no_such_name",
124               3: "bad_value",
125               4: "read_only",
126               5: "generic_error",
127               6: "no_access",
128               7: "wrong_type",
129               8: "wrong_length",
130               9: "wrong_encoding",
131              10: "wrong_value",
132              11: "no_creation",
133              12: "inconsistent_value",
134              13: "resource_unavailable",
135              14: "commit_failed",
136              15: "undo_failed",
137              16: "authorization_error",
138              17: "not_writable",
139              18: "inconsistent_name",
140               }
141
142SNMP_trap_types = { 0: "cold_start",
143                    1: "warm_start",
144                    2: "link_down",
145                    3: "link_up",
146                    4: "auth_failure",
147                    5: "egp_neigh_loss",
148                    6: "enterprise_specific",
149                    }
150
151class SNMPvarbind(ASN1_Packet):
152    ASN1_codec = ASN1_Codecs.BER
153    ASN1_root = ASN1F_SEQUENCE( ASN1F_OID("oid","1.3"),
154                                ASN1F_field("value",ASN1_NULL(0))
155                                )
156
157
158class SNMPget(ASN1_Packet):
159    ASN1_codec = ASN1_Codecs.BER
160    ASN1_root = ASN1F_SNMP_PDU_GET( ASN1F_INTEGER("id",0),
161                                    ASN1F_enum_INTEGER("error",0, SNMP_error),
162                                    ASN1F_INTEGER("error_index",0),
163                                    ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
164                                    )
165
166class SNMPnext(ASN1_Packet):
167    ASN1_codec = ASN1_Codecs.BER
168    ASN1_root = ASN1F_SNMP_PDU_NEXT( ASN1F_INTEGER("id",0),
169                                     ASN1F_enum_INTEGER("error",0, SNMP_error),
170                                     ASN1F_INTEGER("error_index",0),
171                                     ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
172                                     )
173
174class SNMPresponse(ASN1_Packet):
175    ASN1_codec = ASN1_Codecs.BER
176    ASN1_root = ASN1F_SNMP_PDU_RESPONSE( ASN1F_INTEGER("id",0),
177                                         ASN1F_enum_INTEGER("error",0, SNMP_error),
178                                         ASN1F_INTEGER("error_index",0),
179                                         ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
180                                         )
181
182class SNMPset(ASN1_Packet):
183    ASN1_codec = ASN1_Codecs.BER
184    ASN1_root = ASN1F_SNMP_PDU_SET( ASN1F_INTEGER("id",0),
185                                    ASN1F_enum_INTEGER("error",0, SNMP_error),
186                                    ASN1F_INTEGER("error_index",0),
187                                    ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
188                                    )
189
190class SNMPtrapv1(ASN1_Packet):
191    ASN1_codec = ASN1_Codecs.BER
192    ASN1_root = ASN1F_SNMP_PDU_TRAPv1( ASN1F_OID("enterprise", "1.3"),
193                                       ASN1F_IPADDRESS("agent_addr","0.0.0.0"),
194                                       ASN1F_enum_INTEGER("generic_trap", 0, SNMP_trap_types),
195                                       ASN1F_INTEGER("specific_trap", 0),
196                                       ASN1F_TIME_TICKS("time_stamp", IntAutoTime()),
197                                       ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
198                                       )
199
200class SNMPbulk(ASN1_Packet):
201    ASN1_codec = ASN1_Codecs.BER
202    ASN1_root = ASN1F_SNMP_PDU_BULK( ASN1F_INTEGER("id",0),
203                                     ASN1F_INTEGER("non_repeaters",0),
204                                     ASN1F_INTEGER("max_repetitions",0),
205                                     ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
206                                     )
207
208class SNMPinform(ASN1_Packet):
209    ASN1_codec = ASN1_Codecs.BER
210    ASN1_root = ASN1F_SNMP_PDU_INFORM( ASN1F_INTEGER("id",0),
211                                       ASN1F_enum_INTEGER("error",0, SNMP_error),
212                                       ASN1F_INTEGER("error_index",0),
213                                       ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
214                                       )
215
216class SNMPtrapv2(ASN1_Packet):
217    ASN1_codec = ASN1_Codecs.BER
218    ASN1_root = ASN1F_SNMP_PDU_TRAPv2( ASN1F_INTEGER("id",0),
219                                       ASN1F_enum_INTEGER("error",0, SNMP_error),
220                                       ASN1F_INTEGER("error_index",0),
221                                       ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
222                                       )
223
224
225class SNMP(ASN1_Packet):
226    ASN1_codec = ASN1_Codecs.BER
227    ASN1_root = ASN1F_SEQUENCE(
228        ASN1F_enum_INTEGER("version", 1, {0:"v1", 1:"v2c", 2:"v2", 3:"v3"}),
229        ASN1F_STRING("community","public"),
230        ASN1F_CHOICE("PDU", SNMPget(),
231                     SNMPget, SNMPnext, SNMPresponse, SNMPset,
232                     SNMPtrapv1, SNMPbulk, SNMPinform, SNMPtrapv2)
233        )
234    def answers(self, other):
235        return ( isinstance(self.PDU, SNMPresponse)    and
236                 ( isinstance(other.PDU, SNMPget) or
237                   isinstance(other.PDU, SNMPnext) or
238                   isinstance(other.PDU, SNMPset)    ) and
239                 self.PDU.id == other.PDU.id )
240
241bind_layers( UDP,           SNMP,          sport=161)
242bind_layers( UDP,           SNMP,          dport=161)
243bind_layers( UDP,           SNMP,          sport=162)
244bind_layers( UDP,           SNMP,          dport=162)
245
246def snmpwalk(dst, oid="1", community="public"):
247    try:
248        while True:
249            r = sr1(IP(dst=dst)/UDP(sport=RandShort())/SNMP(community=community, PDU=SNMPnext(varbindlist=[SNMPvarbind(oid=oid)])),timeout=2, chainCC=1, verbose=0, retry=2)
250            if ICMP in r:
251                print(repr(r))
252                break
253            if r is None:
254                print("No answers")
255                break
256            print("%-40s: %r" % (r[SNMPvarbind].oid.val,r[SNMPvarbind].value))
257            oid = r[SNMPvarbind].oid
258
259    except KeyboardInterrupt:
260        pass
261
262