Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 33 additions & 5 deletions lisp.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
archive for more details.
"""

import socket,struct,random,netifaces,sys
import socket,struct,random,netifaces,sys,hmac,hashlib
from string import ascii_letters
from scapy import *
from scapy.all import *
Expand Down Expand Up @@ -46,6 +46,12 @@
"lcaf" : 16387
}

_KEY_LENGTH = {
0 : 0,
1 : 20,
2 : 32
}

""" nonce_max determines the maximum value of a nonce field. The default is set to 18446744073709551615, since this is the maximum possible value (>>> int('f'*16, 16)). TODO - see about the entropy for this source"""
nonce_max = 16777215000
nonce_min = 15000000000
Expand Down Expand Up @@ -99,6 +105,7 @@ def guess_payload_class(self, payload):
"""

class LISP_AddressField(Field):
__slots__ = ["fld_name", "_ip_field", "_ip6_field"]
def __init__(self, fld_name, ip_fld_name):
Field.__init__(self, ip_fld_name, '0')

Expand Down Expand Up @@ -225,20 +232,41 @@ class LISP_MapReply(Packet):
class LISP_MapRegister(Packet):
""" map reply part used after the first 16 bits have been read by the LISP_Type class"""
name = "LISP Map-Register packet"
authentication_key = "password" # the key to use in the HMAC SHA computation
fields_desc = [
BitField("ptype", 0, 4),
FlagsField("register_flags", None, 1, ["proxy_map_reply"]),
BitField("p3", 0, 18),
FlagsField("register_flags", None, 1, ["want-map-notify"]),
FlagsField("register_flags", None, 4, ["proxy_map_reply", "lisp_sec", "itr_id_present", "rtr"]),
BitField("p3", 0, 13),
FlagsField("additional_register_flags", None, 3, ["merge", "something", "want-map-notify"]),
FieldLenField("register_count", None, "register_records", "B", count_of="register_records", adjust=lambda pkt,x:x/16 - 1),
XLongField("nonce", random.randint(nonce_min, nonce_max)),
ShortField("key_id", 0),
ShortField("authentication_length", 0),
# authentication length expresses itself in bytes, so no modifications needed here
StrLenField("authentication_data", None, length_from = lambda pkt: pkt.authentication_length),
PacketListField("register_records", None, LISP_MapRecord, count_from=lambda pkt:pkt.register_count + 1)
PacketListField("register_records", None, LISP_MapRecord, count_from=lambda pkt:pkt.register_count + 1),
ConditionalField(XLongField("xtr_id_high", 0), lambda pkt:pkt.register_flags & 2 == 2),
ConditionalField(XLongField("xtr_id_low", 0), lambda pkt:pkt.register_flags & 2 == 2),
ConditionalField(XLongField("site_id", 0), lambda pkt:pkt.register_flags & 2 == 2)
]

def post_build(self, p, pay):
key_length = _KEY_LENGTH[self.key_id]
if self.key_id == 0:
# no HMAC
return p
# add authentication field with the correct length and bytes set to zero
self.authentication_data = '\x00' * key_length
p = p[:14] + struct.pack("!H", key_length) + self.authentication_data + p[16:]
if self.key_id == 1:
# compute HMAC-SHA1 checksum
self.authentication_data = hmac.new(self.authentication_key, msg=str(p), digestmod=hashlib.sha1).digest()
elif self.key_id == 2:
# compute HMAC-SHA256
self.authentication_data = hmac.new(self.authentication_key, msg=str(p), digestmod=hashlib.sha256).digest()
p = p[:16] + self.authentication_data + p[(16+key_length):]
return p

class LISP_MapNotify(Packet):
""" map notify part used after the first 16 bits have been read by the LISP_Type class"""
name = "LISP Map-Notify packet"
Expand Down