Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/layers/isakmp.py: 77%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

186 statements  

1# SPDX-License-Identifier: GPL-2.0-only 

2# This file is part of Scapy 

3# See https://scapy.net/ for more information 

4# Copyright (C) Philippe Biondi <phil@secdev.org> 

5 

6""" 

7ISAKMP (Internet Security Association and Key Management Protocol). 

8""" 

9 

10# Mostly based on https://tools.ietf.org/html/rfc2408 

11 

12import struct 

13from scapy.config import conf 

14from scapy.packet import Packet, bind_bottom_up, bind_top_down, bind_layers 

15from scapy.compat import chb 

16from scapy.fields import ( 

17 ByteEnumField, 

18 ByteField, 

19 FieldLenField, 

20 FieldListField, 

21 FlagsField, 

22 IPField, 

23 IntEnumField, 

24 IntField, 

25 MultipleTypeField, 

26 PacketLenField, 

27 ShortEnumField, 

28 ShortField, 

29 StrLenEnumField, 

30 StrLenField, 

31 XByteField, 

32 XStrFixedLenField, 

33 XStrLenField, 

34) 

35from scapy.layers.inet import IP, UDP 

36from scapy.layers.ipsec import NON_ESP 

37from scapy.sendrecv import sr 

38from scapy.volatile import RandString 

39from scapy.error import warning 

40from functools import reduce 

41 

42# TODO: some ISAKMP payloads are not implemented, 

43# and inherit a default ISAKMP_payload 

44 

45 

46# see https://www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml#ipsec-registry-2 for details # noqa: E501 

47ISAKMPAttributeTypes = { 

48 "Encryption": (1, {"DES-CBC": 1, 

49 "IDEA-CBC": 2, 

50 "Blowfish-CBC": 3, 

51 "RC5-R16-B64-CBC": 4, 

52 "3DES-CBC": 5, 

53 "CAST-CBC": 6, 

54 "AES-CBC": 7, 

55 "CAMELLIA-CBC": 8, }, 0), 

56 "Hash": (2, {"MD5": 1, 

57 "SHA": 2, 

58 "Tiger": 3, 

59 "SHA2-256": 4, 

60 "SHA2-384": 5, 

61 "SHA2-512": 6, }, 0), 

62 "Authentication": (3, {"PSK": 1, 

63 "DSS": 2, 

64 "RSA Sig": 3, 

65 "RSA Encryption": 4, 

66 "RSA Encryption Revised": 5, 

67 "ElGamal Encryption": 6, 

68 "ElGamal Encryption Revised": 7, 

69 "ECDSA Sig": 8, 

70 "HybridInitRSA": 64221, 

71 "HybridRespRSA": 64222, 

72 "HybridInitDSS": 64223, 

73 "HybridRespDSS": 64224, 

74 "XAUTHInitPreShared": 65001, 

75 "XAUTHRespPreShared": 65002, 

76 "XAUTHInitDSS": 65003, 

77 "XAUTHRespDSS": 65004, 

78 "XAUTHInitRSA": 65005, 

79 "XAUTHRespRSA": 65006, 

80 "XAUTHInitRSAEncryption": 65007, 

81 "XAUTHRespRSAEncryption": 65008, 

82 "XAUTHInitRSARevisedEncryption": 65009, # noqa: E501 

83 "XAUTHRespRSARevisedEncryptio": 65010, }, 0), # noqa: E501 

84 "GroupDesc": (4, {"768MODPgr": 1, 

85 "1024MODPgr": 2, 

86 "EC2Ngr155": 3, 

87 "EC2Ngr185": 4, 

88 "1536MODPgr": 5, 

89 "2048MODPgr": 14, 

90 "3072MODPgr": 15, 

91 "4096MODPgr": 16, 

92 "6144MODPgr": 17, 

93 "8192MODPgr": 18, }, 0), 

94 "GroupType": (5, {"MODP": 1, 

95 "ECP": 2, 

96 "EC2N": 3}, 0), 

97 "GroupPrime": (6, {}, 1), 

98 "GroupGenerator1": (7, {}, 1), 

99 "GroupGenerator2": (8, {}, 1), 

100 "GroupCurveA": (9, {}, 1), 

101 "GroupCurveB": (10, {}, 1), 

102 "LifeType": (11, {"Seconds": 1, 

103 "Kilobytes": 2}, 0), 

104 "LifeDuration": (12, {}, 1), 

105 "PRF": (13, {}, 0), 

106 "KeyLength": (14, {}, 0), 

107 "FieldSize": (15, {}, 0), 

108 "GroupOrder": (16, {}, 1), 

109} 

110 

111# see https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xhtml#isakmp-registry-13 for details # noqa: E501 

112IPSECAttributeTypes = { 

113 "LifeType": (1, {"Reserved": 0, 

114 "seconds": 1, 

115 "kilobytes": 2}, 0), 

116 "LifeDuration": (2, {}, 1), 

117 "GroupDesc": (3, ISAKMPAttributeTypes["GroupDesc"][1], 0), 

118 "EncapsulationMode": (4, {"Reserved": 0, 

119 "Tunnel": 1, 

120 "Transport": 2, 

121 "UDP-Encapsulated-Tunnel": 3, 

122 "UDP-Encapsulated-Transport": 4}, 0), 

123 "AuthenticationAlgorithm": (5, {"HMAC-MD5": 1, 

124 "HMAC-SHA": 2, 

125 "DES-MAC": 3, 

126 "KPDK": 4, 

127 "HMAC-SHA2-256": 5, 

128 "HMAC-SHA2-384": 6, 

129 "HMAC-SHA2-512": 7, 

130 "HMAC-RIPEMD": 8, 

131 "AES-XCBC-MAC": 9, 

132 "SIG-RSA": 10, 

133 "AES-128-GMAC": 11, 

134 "AES-192-GMAC": 12, 

135 "AES-256-GMAC": 13}, 0), 

136 "KeyLength": (6, {}, 0), 

137 "KeyRounds": (7, {}, 0), 

138 "CompressDictionarySize": (8, {}, 0), 

139 "CompressPrivateAlgorithm": (9, {}, 1), 

140} 

141 

142_rev = lambda x: { 

143 v[0]: (k, {vv: kk for kk, vv in v[1].items()}, v[2]) 

144 for k, v in x.items() 

145} 

146ISAKMPTransformNum = _rev(ISAKMPAttributeTypes) 

147IPSECTransformNum = _rev(IPSECAttributeTypes) 

148 

149# See IPSEC Security Protocol Identifiers entry in 

150# https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xhtml#isakmp-registry-3 

151PROTO_ISAKMP = 1 

152PROTO_IPSEC_AH = 2 

153PROTO_IPSEC_ESP = 3 

154PROTO_IPCOMP = 4 

155PROTO_GIGABEAM_RADIO = 5 

156 

157 

158class ISAKMPTransformSetField(StrLenField): 

159 islist = 1 

160 

161 @staticmethod 

162 def type2num(type_val_tuple, proto=0): 

163 typ, val = type_val_tuple 

164 if proto == PROTO_ISAKMP: 

165 type_val, enc_dict, tlv = ISAKMPAttributeTypes.get(typ, (typ, {}, 0)) 

166 elif proto == PROTO_IPSEC_ESP: 

167 type_val, enc_dict, tlv = IPSECAttributeTypes.get(typ, (typ, {}, 0)) 

168 else: 

169 type_val, enc_dict, tlv = (typ, {}, 0) 

170 val = enc_dict.get(val, val) 

171 if isinstance(val, str): 

172 raise ValueError("Unknown attribute '%s'" % val) 

173 s = b"" 

174 if (val & ~0xffff): 

175 if not tlv: 

176 warning("%r should not be TLV but is too big => using TLV encoding" % typ) # noqa: E501 

177 n = 0 

178 while val: 

179 s = chb(val & 0xff) + s 

180 val >>= 8 

181 n += 1 

182 val = n 

183 else: 

184 type_val |= 0x8000 

185 return struct.pack("!HH", type_val, val) + s 

186 

187 @staticmethod 

188 def num2type(typ, enc, proto=0): 

189 if proto == PROTO_ISAKMP: 

190 val = ISAKMPTransformNum.get(typ, (typ, {})) 

191 elif proto == PROTO_IPSEC_ESP: 

192 val = IPSECTransformNum.get(typ, (typ, {})) 

193 else: 

194 val = (typ, {}) 

195 enc = val[1].get(enc, enc) 

196 return (val[0], enc) 

197 

198 def _get_proto(self, pkt): 

199 # Ugh 

200 cur = pkt 

201 while cur and getattr(cur, "proto", None) is None: 

202 cur = cur.parent or cur.underlayer 

203 if cur is None: 

204 return PROTO_ISAKMP 

205 return cur.proto 

206 

207 def i2m(self, pkt, i): 

208 if i is None: 

209 return b"" 

210 proto = self._get_proto(pkt) 

211 i = [ISAKMPTransformSetField.type2num(e, proto=proto) for e in i] 

212 return b"".join(i) 

213 

214 def m2i(self, pkt, m): 

215 # I try to ensure that we don't read off the end of our packet based 

216 # on bad length fields we're provided in the packet. There are still 

217 # conditions where struct.unpack() may not get enough packet data, but 

218 # worst case that should result in broken attributes (which would 

219 # be expected). (wam) 

220 lst = [] 

221 proto = self._get_proto(pkt) 

222 while len(m) >= 4: 

223 trans_type, = struct.unpack("!H", m[:2]) 

224 is_tlv = not (trans_type & 0x8000) 

225 if is_tlv: 

226 # We should probably check to make sure the attribute type we 

227 # are looking at is allowed to have a TLV format and issue a 

228 # warning if we're given an TLV on a basic attribute. 

229 value_len, = struct.unpack("!H", m[2:4]) 

230 if value_len + 4 > len(m): 

231 warning("Bad length for ISAKMP transform type=%#6x" % trans_type) # noqa: E501 

232 value = m[4:4 + value_len] 

233 value = reduce(lambda x, y: (x << 8) | y, struct.unpack("!%s" % ("B" * len(value),), value), 0) # noqa: E501 

234 else: 

235 trans_type &= 0x7fff 

236 value_len = 0 

237 value, = struct.unpack("!H", m[2:4]) 

238 m = m[4 + value_len:] 

239 lst.append(ISAKMPTransformSetField.num2type(trans_type, value, proto=proto)) 

240 if len(m) > 0: 

241 warning("Extra bytes after ISAKMP transform dissection [%r]" % m) 

242 return lst 

243 

244 

245ISAKMP_payload_type = { 

246 0: "None", 

247 1: "SA", 

248 2: "Proposal", 

249 3: "Transform", 

250 4: "KE", 

251 5: "ID", 

252 6: "CERT", 

253 7: "CR", 

254 8: "Hash", 

255 9: "SIG", 

256 10: "Nonce", 

257 11: "Notification", 

258 12: "Delete", 

259 13: "VendorID", 

260} 

261 

262ISAKMP_exchange_type = { 

263 0: "None", 

264 1: "base", 

265 2: "identity protection", 

266 3: "authentication only", 

267 4: "aggressive", 

268 5: "informational", 

269 32: "quick mode", 

270} 

271 

272# https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xhtml#isakmp-registry-3 

273# IPSEC Security Protocol Identifiers 

274ISAKMP_protos = { 

275 1: "ISAKMP", 

276 2: "IPSEC_AH", 

277 3: "IPSEC_ESP", 

278 4: "IPCOMP", 

279 5: "GIGABEAM_RADIO" 

280} 

281 

282ISAKMP_doi = { 

283 0: "ISAKMP", 

284 1: "IPSEC", 

285} 

286 

287 

288class _ISAKMP_class(Packet): 

289 def default_payload_class(self, payload): 

290 if self.next_payload == 0: 

291 return conf.raw_layer 

292 return ISAKMP_payload 

293 

294# -- ISAKMP 

295 

296 

297class ISAKMP(_ISAKMP_class): # rfc2408 

298 name = "ISAKMP" 

299 fields_desc = [ 

300 XStrFixedLenField("init_cookie", "", 8), 

301 XStrFixedLenField("resp_cookie", "", 8), 

302 ByteEnumField("next_payload", 0, ISAKMP_payload_type), 

303 XByteField("version", 0x10), 

304 ByteEnumField("exch_type", 0, ISAKMP_exchange_type), 

305 FlagsField("flags", 0, 8, ["encryption", "commit", "auth_only"]), 

306 IntField("id", 0), 

307 IntField("length", None) 

308 ] 

309 

310 def guess_payload_class(self, payload): 

311 if self.flags & 1: 

312 return conf.raw_layer 

313 return _ISAKMP_class.guess_payload_class(self, payload) 

314 

315 def answers(self, other): 

316 if isinstance(other, ISAKMP): 

317 if other.init_cookie == self.init_cookie: 

318 return 1 

319 return 0 

320 

321 def post_build(self, p, pay): 

322 p += pay 

323 if self.length is None: 

324 p = p[:24] + struct.pack("!I", len(p)) + p[28:] 

325 return p 

326 

327 

328# -- ISAKMP payloads 

329 

330class ISAKMP_payload(_ISAKMP_class): 

331 name = "ISAKMP payload" 

332 show_indent = 0 

333 fields_desc = [ 

334 ByteEnumField("next_payload", None, ISAKMP_payload_type), 

335 ByteField("res", 0), 

336 ShortField("length", None), 

337 XStrLenField("load", "", length_from=lambda x:x.length - 4), 

338 ] 

339 

340 def post_build(self, pkt, pay): 

341 if self.length is None: 

342 pkt = pkt[:2] + struct.pack("!H", len(pkt)) + pkt[4:] 

343 return pkt + pay 

344 

345 

346class ISAKMP_payload_Transform(ISAKMP_payload): 

347 name = "IKE Transform" 

348 deprecated_fields = { 

349 "num": ("transform_count", ("2.5.0")), 

350 "id": ("transform_id", ("2.5.0")), 

351 } 

352 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

353 ByteField("transform_count", None), 

354 ByteEnumField("transform_id", 1, {1: "KEY_IKE"}), 

355 ShortField("res2", 0), 

356 ISAKMPTransformSetField("transforms", None, length_from=lambda x: x.length - 8) # noqa: E501 

357 # XIntField("enc",0x80010005L), 

358 # XIntField("hash",0x80020002L), 

359 # XIntField("auth",0x80030001L), 

360 # XIntField("group",0x80040002L), 

361 # XIntField("life_type",0x800b0001L), 

362 # XIntField("durationh",0x000c0004L), 

363 # XIntField("durationl",0x00007080L), 

364 ] 

365 

366 

367# https://tools.ietf.org/html/rfc2408#section-3.5 

368class ISAKMP_payload_Proposal(ISAKMP_payload): 

369 name = "IKE proposal" 

370 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

371 ByteField("proposal", 1), 

372 ByteEnumField("proto", 1, ISAKMP_protos), 

373 FieldLenField("SPIsize", None, "SPI", "B"), 

374 ByteField("trans_nb", None), 

375 StrLenField("SPI", "", length_from=lambda x: x.SPIsize), 

376 PacketLenField("trans", conf.raw_layer(), ISAKMP_payload_Transform, length_from=lambda x: x.length - 8), # noqa: E501 

377 ] 

378 

379 

380# VendorID: https://www.rfc-editor.org/rfc/rfc2408#section-3.16 

381 

382# packet-isakmp.c from wireshark 

383ISAKMP_VENDOR_IDS = { 

384 b"\x09\x00\x26\x89\xdf\xd6\xb7\x12": "XAUTH", 

385 b"\xaf\xca\xd7\x13h\xa1\xf1\xc9k\x86\x96\xfcwW\x01\x00": "RFC 3706 DPD", 

386 b"@H\xb7\xd5n\xbc\xe8\x85%\xe7\xde\x7f\x00\xd6\xc2\xd3\x80": "Cisco Fragmentation", 

387 b"J\x13\x1c\x81\x07\x03XE\\W(\xf2\x0e\x95E/": "RFC 3947 Negotiation of NAT-Transversal", # noqa: E501 

388 b"\x90\xcb\x80\x91>\xbbin\x08c\x81\xb5\xecB{\x1f": "draft-ietf-ipsec-nat-t-ike-02", 

389} 

390 

391 

392class ISAKMP_payload_VendorID(ISAKMP_payload): 

393 name = "ISAKMP Vendor ID" 

394 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

395 StrLenEnumField("VendorID", b"", 

396 ISAKMP_VENDOR_IDS, 

397 length_from=lambda x: x.length - 4) 

398 ] 

399 

400 

401class ISAKMP_payload_SA(ISAKMP_payload): 

402 name = "ISAKMP SA" 

403 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

404 IntEnumField("doi", 1, ISAKMP_doi), 

405 IntEnumField("situation", 1, {1: "identity"}), 

406 PacketLenField("prop", conf.raw_layer(), ISAKMP_payload_Proposal, length_from=lambda x: x.length - 12), # noqa: E501 

407 ] 

408 

409 

410class ISAKMP_payload_Nonce(ISAKMP_payload): 

411 name = "ISAKMP Nonce" 

412 deprecated_fields = {"load": ("nonce", "2.6.2")} 

413 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

414 StrLenField("nonce", "", length_from=lambda x: x.length - 4) 

415 ] 

416 

417 

418class ISAKMP_payload_KE(ISAKMP_payload): 

419 name = "ISAKMP Key Exchange" 

420 deprecated_fields = {"load": ("ke", "2.6.2")} 

421 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

422 StrLenField("ke", "", length_from=lambda x: x.length - 4) 

423 ] 

424 

425 

426class ISAKMP_payload_ID(ISAKMP_payload): 

427 name = "ISAKMP Identification" 

428 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

429 ByteEnumField("IDtype", 1, { 

430 # Beware, apparently in-the-wild the values used 

431 # appear to be the ones from IKEv2 (RFC4306 sect 3.5) 

432 # and not ISAKMP (RFC2408 sect A.4) 

433 1: "IPv4_addr", 

434 11: "Key" 

435 }), 

436 ByteEnumField("ProtoID", 0, {0: "Unused"}), 

437 ShortEnumField("Port", 0, {0: "Unused"}), 

438 MultipleTypeField( 

439 [ 

440 (IPField("IdentData", "127.0.0.1"), 

441 lambda pkt: pkt.IDtype == 1), 

442 ], 

443 StrLenField("IdentData", "", length_from=lambda x: x.length - 8), 

444 ) 

445 ] 

446 

447 

448class ISAKMP_payload_Hash(ISAKMP_payload): 

449 name = "ISAKMP Hash" 

450 deprecated_fields = {"load": ("hash", "2.6.2")} 

451 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

452 StrLenField("hash", "", length_from=lambda x: x.length - 4) 

453 ] 

454 

455 

456class ISAKMP_payload_SIG(ISAKMP_payload): 

457 name = "ISAKMP Signature" 

458 deprecated_fields = {"load": ("sig", "2.6.2")} 

459 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

460 StrLenField("sig", "", length_from=lambda x: x.length - 4) 

461 ] 

462 

463 

464NotifyMessageType = { 

465 1: "INVALID-PAYLOAD-TYPE", 

466 2: "DOI-NOT-SUPPORTED", 

467 3: "SITUATION-NOT-SUPPORTED", 

468 4: "INVALID-COOKIE", 

469 5: "INVALID-MAJOR-VERSION", 

470 6: "INVALID-MINOR-VERSION", 

471 7: "INVALID-EXCHANGE-TYPE", 

472 8: "INVALID-FLAGS", 

473 9: "INVALID-MESSAGE-ID", 

474 10: "INVALID-PROTOCOL-ID", 

475 11: "INVALID-SPI", 

476 12: "INVALID-TRANSFORM-ID", 

477 13: "ATTRIBUTES-NOT-SUPPORTED", 

478 14: "NO-PROPOSAL-CHOSEN", 

479 15: "BAD-PROPOSAL-SYNTAX", 

480 16: "PAYLOAD-MALFORMED", 

481 17: "INVALID-KEY-INFORMATION", 

482 18: "INVALID-ID-INFORMATION", 

483 19: "INVALID-CERT-ENCODING", 

484 20: "INVALID-CERTIFICATE", 

485 21: "CERT-TYPE-UNSUPPORTED", 

486 22: "INVALID-CERT-AUTHORITY", 

487 23: "INVALID-HASH-INFORMATION", 

488 24: "AUTHENTICATION-FAILED", 

489 25: "INVALID-SIGNATURE", 

490 26: "ADDRESS-NOTIFICATION", 

491 27: "NOTIFY-SA-LIFETIME", 

492 28: "CERTIFICATE-UNAVAILABLE", 

493 29: "UNSUPPORTED-EXCHANGE-TYPE", 

494 30: "UNEQUAL-PAYLOAD-LENGTHS", 

495 16384: "CONNECTED", 

496 # RFC 3706 

497 36136: "R-U-THERE", 

498 36137: "R-U-THERE-ACK", 

499} 

500 

501 

502class ISAKMP_payload_Notify(ISAKMP_payload): 

503 name = "ISAKMP Notify (Notification)" 

504 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

505 IntEnumField("doi", 0, ISAKMP_doi), 

506 ByteEnumField("proto", 1, ISAKMP_protos), 

507 FieldLenField("SPIsize", None, "SPI", "B"), 

508 ShortEnumField("notify_msg_type", None, NotifyMessageType), 

509 StrLenField("SPI", "", length_from=lambda x: x.SPIsize), 

510 StrLenField("notify_data", "", 

511 length_from=lambda x: x.length - x.SPIsize - 12) 

512 ] 

513 

514 

515class ISAKMP_payload_Delete(ISAKMP_payload): 

516 name = "ISAKMP Delete" 

517 fields_desc = ISAKMP_payload.fields_desc[:3] + [ 

518 IntEnumField("doi", 0, ISAKMP_doi), 

519 ByteEnumField("proto", 1, ISAKMP_protos), 

520 FieldLenField("SPIsize", None, length_of="SPIs", fmt="B", 

521 adjust=lambda pkt, x: x and x // len(pkt.SPIs)), 

522 FieldLenField("SPIcount", None, count_of="SPIs", fmt="H"), 

523 FieldListField("SPIs", [], 

524 StrLenField("", "", length_from=lambda pkt: pkt.SPIsize), 

525 count_from=lambda pkt: pkt.SPIcount), 

526 ] 

527 

528 

529bind_bottom_up(UDP, ISAKMP, dport=500) 

530bind_bottom_up(UDP, ISAKMP, sport=500) 

531bind_top_down(UDP, ISAKMP, dport=500, sport=500) 

532 

533bind_bottom_up(NON_ESP, ISAKMP) 

534 

535# Add bindings 

536bind_top_down(_ISAKMP_class, ISAKMP_payload, next_payload=0) 

537bind_layers(_ISAKMP_class, ISAKMP_payload_SA, next_payload=1) 

538bind_layers(_ISAKMP_class, ISAKMP_payload_Proposal, next_payload=2) 

539bind_layers(_ISAKMP_class, ISAKMP_payload_Transform, next_payload=3) 

540bind_layers(_ISAKMP_class, ISAKMP_payload_KE, next_payload=4) 

541bind_layers(_ISAKMP_class, ISAKMP_payload_ID, next_payload=5) 

542# bind_layers(_ISAKMP_class, ISAKMP_payload_CERT, next_payload=6) 

543# bind_layers(_ISAKMP_class, ISAKMP_payload_CR, next_payload=7) 

544bind_layers(_ISAKMP_class, ISAKMP_payload_Hash, next_payload=8) 

545bind_layers(_ISAKMP_class, ISAKMP_payload_SIG, next_payload=9) 

546bind_layers(_ISAKMP_class, ISAKMP_payload_Nonce, next_payload=10) 

547bind_layers(_ISAKMP_class, ISAKMP_payload_Notify, next_payload=11) 

548bind_layers(_ISAKMP_class, ISAKMP_payload_Delete, next_payload=12) 

549bind_layers(_ISAKMP_class, ISAKMP_payload_VendorID, next_payload=13) 

550 

551 

552def ikescan(ip): 

553 """Sends/receives a ISAMPK payload SA with payload proposal""" 

554 pkt = IP(dst=ip) 

555 pkt /= UDP() 

556 pkt /= ISAKMP(init_cookie=RandString(8), exch_type=2) 

557 pkt /= ISAKMP_payload_SA(prop=ISAKMP_payload_Proposal()) 

558 return sr(pkt)