Coverage for /root/GitHubProjects/impacket/impacket/cdp.py : 47%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved.
2#
3# This software is provided under under a slightly modified version
4# of the Apache Software License. See the accompanying LICENSE file
5# for more information.
6#
7# Description:
8# Cisco Discovery Protocol packet codecs.
9#
10# Author:
11# Martin Candurra
12# martincad at corest.com
14from struct import unpack
15import socket
17from impacket.ImpactPacket import Header, array_tobytes
18from impacket import LOG
20IP_ADDRESS_LENGTH = 4
22class CDPTypes:
24 DeviceID_Type = 1
25 Address_Type = 2
26 PortID_Type = 3
27 Capabilities_Type = 4
28 SoftVersion_Type = 5
29 Platform_Type = 6
30 IPPrefix_Type = 7
31 ProtocolHello_Type = 8
32 MTU_Type = 17
33 SystemName_Type = 20
34 SystemObjectId_Type = 21
35 SnmpLocation = 23
37class CDP(Header):
39 Type = 0x2000
40 OUI = 0x00000c
42 def __init__(self, aBuffer = None):
43 Header.__init__(self, 8)
44 if aBuffer:
45 self.load_header(aBuffer)
46 self._elements = self._getElements(aBuffer)
48 def _getElements(self, aBuffer):
49 # Remove version (1 byte), TTL (1 byte), and checksum (2 bytes)
50 buff = aBuffer[4:]
51 l = []
52 while buff:
53 elem = CDPElementFactory.create(buff)
54 l.append( elem )
55 buff = buff[ elem.get_length() : ]
56 return l
58 def get_header_size(self):
59 return 8
61 def get_version(self):
62 return self.get_byte(0)
64 def get_ttl(self):
65 return self.get_byte(1)
67 def get_checksum(self):
68 return self.get_word(2)
70 def get_type(self):
71 return self.get_word(4)
73 def get_lenght(self):
74 return self.get_word(6)
76 def getElements(self):
77 return self._elements
80 def __str__(self):
81 tmp_str = 'CDP Details:\n'
82 for element in self._elements:
83 tmp_str += "** Type:" + str(element.get_type()) + " " + str(element) + "\n"
84 return tmp_str
87def get_byte(buffer, offset):
88 return unpack("!B", buffer[offset:offset+1])[0]
90def get_word(buffer, offset):
91 return unpack("!h", buffer[offset:offset+2])[0]
93def get_long(buffer, offset):
94 return unpack("!I", buffer[offset:offset+4])[0]
96def get_bytes(buffer, offset, bytes):
97 return buffer[offset:offset + bytes]
99def mac_to_string(mac_bytes):
100 bytes = unpack('!BBBBBB', mac_bytes)
101 s = ''
102 for byte in bytes:
103 s += '%02x:' % byte
104 return s[0:-1]
108class CDPElement(Header):
110 def __init__(self, aBuffer = None):
111 Header.__init__(self, 8)
112 if aBuffer:
113 self._length = CDPElement.Get_length(aBuffer)
114 self.load_header( aBuffer[:self._length] )
116 @classmethod
117 def Get_length(cls, aBuffer):
118 return unpack('!h', aBuffer[2:4])[0]
120 def get_header_size(self):
121 self._length
123 def get_length(self):
124 return self.get_word(2)
126 def get_data(self):
127 return array_tobytes(self.get_bytes())[4:self.get_length()]
129 def get_ip_address(self, offset = 0, ip = None):
130 if not ip:
131 ip = array_tobytes(self.get_bytes())[offset : offset + IP_ADDRESS_LENGTH]
132 return socket.inet_ntoa( ip )
134class CDPDevice(CDPElement):
135 Type = 1
137 def get_type(self):
138 return CDPDevice.Type
140 def get_device_id(self):
141 return CDPElement.get_data(self)
143 def __str__(self):
144 return "Device:" + self.get_device_id()
146class Address(CDPElement):
147 Type = 2
149 def __init__(self, aBuffer = None):
150 CDPElement.__init__(self, aBuffer)
151 if aBuffer:
152 data = array_tobytes(self.get_bytes())[8:]
153 self._generateAddressDetails(data)
155 def _generateAddressDetails(self, buff):
156 self.address_details = []
157 while buff:
158 address = AddressDetails.create(buff)
159 self.address_details.append( address )
160 buff = buff[address.get_total_length():]
162 def get_type(self):
163 return Address.Type
165 def get_number(self):
166 return self.get_long(4)
168 def get_address_details(self):
169 return self.address_details
171 def __str__(self):
172 tmp_str = "Addresses:"
173 for address_detail in self.address_details:
174 tmp_str += "\n" + str(address_detail)
175 return tmp_str
177class AddressDetails():
179 PROTOCOL_IP = 0xcc
181 @classmethod
182 def create(cls, buff):
183 a = AddressDetails(buff)
184 return a
187 def __init__(self, aBuffer = None):
188 if aBuffer:
189 addr_length = unpack("!h", aBuffer[3:5])[0]
190 self.total_length = addr_length + 5
191 self.buffer = aBuffer[:self.total_length]
193 def get_total_length(self):
194 return self.total_length
196 def get_protocol_type(self):
197 return self.buffer[0:1]
199 def get_protocol_length(self):
200 return get_byte( self.buffer, 1)
202 def get_protocol(self):
203 return get_byte( self.buffer, 2)
205 def get_address_length(self):
206 return get_word( self.buffer, 3)
208 def get_address(self):
209 address = get_bytes( self.buffer, 5, self.get_address_length() )
210 if self.get_protocol()==AddressDetails.PROTOCOL_IP:
211 return socket.inet_ntoa(address)
212 else:
213 LOG.error("Address not IP")
214 return address
216 def is_protocol_IP(self):
217 return self.get_protocol()==AddressDetails.PROTOCOL_IP
219 def __str__(self):
220 return "Protocol Type:%r Protocol:%r Address Length:%r Address:%s" % (self.get_protocol_type(), self.get_protocol(), self.get_address_length(), self.get_address())
222class Port(CDPElement):
223 Type = 3
225 def get_type(self):
226 return Port.Type
228 def get_port(self):
229 return CDPElement.get_data(self)
231 def __str__(self):
232 return "Port:" + self.get_port()
235class Capabilities(CDPElement):
236 Type = 4
238 def __init__(self, aBuffer = None):
239 CDPElement.__init__(self, aBuffer)
240 self._capabilities_processed = False
242 self._router = False
243 self._transparent_bridge = False
244 self._source_route_bridge = False
245 self._switch = False
246 self._host = False
247 self._igmp_capable = False
248 self._repeater = False
249 self._init_capabilities()
251 def get_type(self):
252 return Capabilities.Type
254 def get_capabilities(self):
255 return CDPElement.get_data(self)
257 def _init_capabilities(self):
258 if self._capabilities_processed:
259 return
261 capabilities = unpack("!L", self.get_capabilities())[0]
262 self._router = (capabilities & 0x1) > 0
263 self._transparent_bridge = (capabilities & 0x02) > 0
264 self._source_route_bridge = (capabilities & 0x04) > 0
265 self._switch = (capabilities & 0x08) > 0
266 self._host = (capabilities & 0x10) > 0
267 self._igmp_capable = (capabilities & 0x20) > 0
268 self._repeater = (capabilities & 0x40) > 0
270 def is_router(self):
271 return self._router
273 def is_transparent_bridge(self):
274 return self._transparent_bridge
276 def is_source_route_bridge(self):
277 return self._source_route_bridge
279 def is_switch(self):
280 return self._switch
282 def is_host(self):
283 return self.is_host
285 def is_igmp_capable(self):
286 return self._igmp_capable
288 def is_repeater(self):
289 return self._repeater
292 def __str__(self):
293 return "Capabilities:" + self.get_capabilities()
296class SoftVersion(CDPElement):
297 Type = 5
299 def get_type(self):
300 return SoftVersion.Type
302 def get_version(self):
303 return CDPElement.get_data(self)
305 def __str__(self):
306 return "Version:" + self.get_version()
309class Platform(CDPElement):
310 Type = 6
312 def get_type(self):
313 return Platform.Type
315 def get_platform(self):
316 return CDPElement.get_data(self)
318 def __str__(self):
319 return "Platform:%r" % self.get_platform()
322class IpPrefix(CDPElement):
323 Type = 7
325 def get_type(self):
326 return IpPrefix .Type
328 def get_ip_prefix(self):
329 return CDPElement.get_ip_address(self, 4)
331 def get_bits(self):
332 return self.get_byte(8)
334 def __str__(self):
335 return "IP Prefix/Gateway: %r/%d" % (self.get_ip_prefix(), self.get_bits())
337class ProtocolHello(CDPElement):
338 Type = 8
340 def get_type(self):
341 return ProtocolHello.Type
343 def get_master_ip(self):
344 return self.get_ip_address(9)
346 def get_version(self):
347 return self.get_byte(17)
349 def get_sub_version(self):
350 return self.get_byte(18)
352 def get_status(self):
353 return self.get_byte(19)
355 def get_cluster_command_mac(self):
356 return array_tobytes(self.get_bytes())[20:20+6]
358 def get_switch_mac(self):
359 return array_tobytes(self.get_bytes())[28:28+6]
361 def get_management_vlan(self):
362 return self.get_word(36)
364 def __str__(self):
365 return "\n\n\nProcolHello: Master IP:%s version:%r subversion:%r status:%r Switch's Mac:%r Management VLAN:%r" \
366 % (self.get_master_ip(), self.get_version(), self.get_sub_version(), self.get_status(), mac_to_string(self.get_switch_mac()), self.get_management_vlan())
368class VTPManagementDomain(CDPElement):
369 Type = 9
371 def get_type(self):
372 return VTPManagementDomain.Type
374 def get_domain(self):
375 return CDPElement.get_data(self)
378class Duplex(CDPElement):
379 Type = 0xb
381 def get_type(self):
382 return Duplex.Type
384 def get_duplex(self):
385 return CDPElement.get_data(self)
387 def is_full_duplex(self):
388 return self.get_duplex()==0x1
390class VLAN(CDPElement):
391 Type = 0xa
393 def get_type(self):
394 return VLAN.Type
396 def get_vlan_number(self):
397 return CDPElement.get_data(self)
401class TrustBitmap(CDPElement):
402 Type = 0x12
404 def get_type(self):
405 return TrustBitmap.Type
407 def get_trust_bitmap(self):
408 return self.get_data()
410 def __str__(self):
411 return "TrustBitmap Trust Bitmap:%r" % self.get_trust_bitmap()
413class UntrustedPortCoS(CDPElement):
414 Type = 0x13
416 def get_type(self):
417 return UntrustedPortCoS.Type
419 def get_port_CoS(self):
420 return self.get_data()
422 def __str__(self):
423 return "UntrustedPortCoS port CoS %r" % self.get_port_CoS()
425class ManagementAddresses(Address):
426 Type = 0x16
428 def get_type(self):
429 return ManagementAddresses.Type
431class MTU(CDPElement):
432 Type = 0x11
434 def get_type(self):
435 return MTU.Type
437class SystemName(CDPElement):
438 Type = 0x14
440 def get_type(self):
441 return SystemName.Type
443class SystemObjectId(CDPElement):
444 Type = 0x15
446 def get_type(self):
447 return SystemObjectId.Type
449class SnmpLocation(CDPElement):
450 Type = 0x17
452 def get_type(self):
453 return SnmpLocation.Type
456class DummyCdpElement(CDPElement):
457 Type = 0x99
459 def get_type(self):
460 return DummyCdpElement.Type
462class CDPElementFactory():
464 elementTypeMap = {
465 CDPDevice.Type : CDPDevice,
466 Port.Type : Port,
467 Capabilities.Type : Capabilities,
468 Address.Type : Address,
469 SoftVersion.Type : SoftVersion,
470 Platform.Type : Platform,
471 IpPrefix.Type : IpPrefix,
472 ProtocolHello.Type : ProtocolHello,
473 VTPManagementDomain.Type : VTPManagementDomain,
474 VLAN.Type : VLAN,
475 Duplex.Type : Duplex,
476 TrustBitmap.Type : TrustBitmap,
477 UntrustedPortCoS.Type : UntrustedPortCoS,
478 ManagementAddresses.Type : ManagementAddresses,
479 MTU.Type : MTU,
480 SystemName.Type : SystemName,
481 SystemObjectId.Type : SystemObjectId,
482 SnmpLocation.Type : SnmpLocation
483 }
485 @classmethod
486 def create(cls, aBuffer):
487# print "CDPElementFactory.create aBuffer:", repr(aBuffer)
488# print "CDPElementFactory.create sub_type:", repr(aBuffer[0:2])
489 _type = unpack("!h", aBuffer[0:2])[0]
490# print "CDPElementFactory.create _type:", _type
491 try:
492 class_type = cls.elementTypeMap[_type]
493 except KeyError:
494 class_type = DummyCdpElement
495 #raise Exception("CDP Element type %s not implemented" % _type)
496 return class_type( aBuffer )