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

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

## 317 statements

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

13

14 from struct import unpack

15 import socket

16

17 from impacket.ImpactPacket import Header, array_tobytes

18 from impacket import LOG

19

20 IP_ADDRESS_LENGTH = 4

21

22 class CDPTypes:

23

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

36

37 class CDP(Header):

38

39 Type = 0x2000

40 OUI = 0x00000c

41

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)

47

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

57

58 def get_header_size(self):

59 return 8

60

61 def get_version(self):

62 return self.get_byte(0)

63

64 def get_ttl(self):

65 return self.get_byte(1)

66

67 def get_checksum(self):

68 return self.get_word(2)

69

70 def get_type(self):

71 return self.get_word(4)

72

73 def get_lenght(self):

74 return self.get_word(6)

75

76 def getElements(self):

77 return self._elements

78

79

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

85

86

87 def get_byte(buffer, offset):

88 return unpack("!B", buffer[offset: offset+1])[0]

89

90 def get_word(buffer, offset):

91 return unpack("!h", buffer[offset: offset+2])[0]

92

93 def get_long(buffer, offset):

94 return unpack("!I", buffer[offset: offset+4])[0]

95

96 def get_bytes(buffer, offset, bytes):

97 return buffer[offset: offset + bytes]

98

99 def 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]

105

106

107

108 class CDPElement(Header):

109

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] )

115

116 @classmethod

117 def Get_length(cls, aBuffer):

118 return unpack('!h', aBuffer[2:4])[0]

119

120 def get_header_size(self):

121 self._length

122

123 def get_length(self):

124 return self.get_word(2)

125

126 def get_data(self):

127 return array_tobytes(self.get_bytes())[4: self.get_length()]

128

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 )

133

134 class CDPDevice(CDPElement):

135 Type = 1

136

137 def get_type(self):

138 return CDPDevice.Type

139

140 def get_device_id(self):

141 return CDPElement.get_data(self)

142

143 def __str__(self):

144 return "Device:" + self.get_device_id()

145

146 class Address(CDPElement):

147 Type = 2

148

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)

154

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():]

161

162 def get_type(self):

163 return Address.Type

164

165 def get_number(self):

166 return self.get_long(4)

167

168 def get_address_details(self):

169 return self.address_details

170

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

176

177 class AddressDetails():

178

179 PROTOCOL_IP = 0xcc

180

181 @classmethod

182 def create(cls, buff):

183 a = AddressDetails(buff)

184 return a

185

186

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]

192

193 def get_total_length(self):

194 return self.total_length

195

196 def get_protocol_type(self):

197 return self.buffer[0:1]

198

199 def get_protocol_length(self):

200 return get_byte( self.buffer, 1)

201

202 def get_protocol(self):

203 return get_byte( self.buffer, 2)

204

205 def get_address_length(self):

206 return get_word( self.buffer, 3)

207

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

215

216 def is_protocol_IP(self):

217 return self.get_protocol()==AddressDetails.PROTOCOL_IP

218

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())

221

222 class Port(CDPElement):

223 Type = 3

224

225 def get_type(self):

226 return Port.Type

227

228 def get_port(self):

229 return CDPElement.get_data(self)

230

231 def __str__(self):

232 return "Port:" + self.get_port()

233

234

235 class Capabilities(CDPElement):

236 Type = 4

237

238 def __init__(self, aBuffer = None):

239 CDPElement.__init__(self, aBuffer)

240 self._capabilities_processed = False

241

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()

250

251 def get_type(self):

252 return Capabilities.Type

253

254 def get_capabilities(self):

255 return CDPElement.get_data(self)

256

257 def _init_capabilities(self):

258 if self._capabilities_processed:

259 return

260

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

269

270 def is_router(self):

271 return self._router

272

273 def is_transparent_bridge(self):

274 return self._transparent_bridge

275

276 def is_source_route_bridge(self):

277 return self._source_route_bridge

278

279 def is_switch(self):

280 return self._switch

281

282 def is_host(self):

283 return self.is_host

284

285 def is_igmp_capable(self):

286 return self._igmp_capable

287

288 def is_repeater(self):

289 return self._repeater

290

291

292 def __str__(self):

293 return "Capabilities:" + self.get_capabilities()

294

295

296 class SoftVersion(CDPElement):

297 Type = 5

298

299 def get_type(self):

300 return SoftVersion.Type

301

302 def get_version(self):

303 return CDPElement.get_data(self)

304

305 def __str__(self):

306 return "Version:" + self.get_version()

307

308

309 class Platform(CDPElement):

310 Type = 6

311

312 def get_type(self):

313 return Platform.Type

314

315 def get_platform(self):

316 return CDPElement.get_data(self)

317

318 def __str__(self):

319 return "Platform:%r" % self.get_platform()

320

321

322 class IpPrefix(CDPElement):

323 Type = 7

324

325 def get_type(self):

326 return IpPrefix .Type

327

328 def get_ip_prefix(self):

329 return CDPElement.get_ip_address(self, 4)

330

331 def get_bits(self):

332 return self.get_byte(8)

333

334 def __str__(self):

335 return "IP Prefix/Gateway: %r/%d" % (self.get_ip_prefix(), self.get_bits())

336

337 class ProtocolHello(CDPElement):

338 Type = 8

339

340 def get_type(self):

341 return ProtocolHello.Type

342

343 def get_master_ip(self):

344 return self.get_ip_address(9)

345

346 def get_version(self):

347 return self.get_byte(17)

348

349 def get_sub_version(self):

350 return self.get_byte(18)

351

352 def get_status(self):

353 return self.get_byte(19)

354

355 def get_cluster_command_mac(self):

356 return array_tobytes(self.get_bytes())[20:20+6]

357

358 def get_switch_mac(self):

359 return array_tobytes(self.get_bytes())[28:28+6]

360

361 def get_management_vlan(self):

362 return self.get_word(36)

363

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())

367

368 class VTPManagementDomain(CDPElement):

369 Type = 9

370

371 def get_type(self):

372 return VTPManagementDomain.Type

373

374 def get_domain(self):

375 return CDPElement.get_data(self)

376

377

378 class Duplex(CDPElement):

379 Type = 0xb

380

381 def get_type(self):

382 return Duplex.Type

383

384 def get_duplex(self):

385 return CDPElement.get_data(self)

386

387 def is_full_duplex(self):

388 return self.get_duplex()==0x1

389

390 class VLAN(CDPElement):

391 Type = 0xa

392

393 def get_type(self):

394 return VLAN.Type

395

396 def get_vlan_number(self):

397 return CDPElement.get_data(self)

398

399

400

401 class TrustBitmap(CDPElement):

402 Type = 0x12

403

404 def get_type(self):

405 return TrustBitmap.Type

406

407 def get_trust_bitmap(self):

408 return self.get_data()

409

410 def __str__(self):

411 return "TrustBitmap Trust Bitmap:%r" % self.get_trust_bitmap()

412

413 class UntrustedPortCoS(CDPElement):

414 Type = 0x13

415

416 def get_type(self):

417 return UntrustedPortCoS.Type

418

419 def get_port_CoS(self):

420 return self.get_data()

421

422 def __str__(self):

423 return "UntrustedPortCoS port CoS %r" % self.get_port_CoS()

424

425 class ManagementAddresses(Address):

426 Type = 0x16

427

428 def get_type(self):

429 return ManagementAddresses.Type

430

431 class MTU(CDPElement):

432 Type = 0x11

433

434 def get_type(self):

435 return MTU.Type

436

437 class SystemName(CDPElement):

438 Type = 0x14

439

440 def get_type(self):

441 return SystemName.Type

442

443 class SystemObjectId(CDPElement):

444 Type = 0x15

445

446 def get_type(self):

447 return SystemObjectId.Type

448

449 class SnmpLocation(CDPElement):

450 Type = 0x17

451

452 def get_type(self):

453 return SnmpLocation.Type

454

455

456 class DummyCdpElement(CDPElement):

457 Type = 0x99

458

459 def get_type(self):

460 return DummyCdpElement.Type

461

462 class CDPElementFactory():

463

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 }

484

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 )