Exemplo n.º 1
0
    def sign(self,data, dad=False, nonce=None):
        """sign the data with RSA signature option, adds timestamp, nonce, etc.
        Data must be a valid NS, NA, RS, RA or ICMPv6 redirect packet"""
        ndp_msg = IPv6(data)

        if dad and ndp_msg[IPv6].src != "::" :
            raise AddressException("tried to sign a DAD message with the null address")
        elif not dad and ndp_msg[IPv6].src != self.__address:
            raise AddressException("tried to sign a message with an incorrect source address")


        if not ndp_msg.haslayer(ICMPv6ND_RS) \
           and not ndp_msg.haslayer(ICMPv6ND_RA) \
           and not ndp_msg.haslayer(ICMPv6ND_NS) \
           and not ndp_msg.haslayer(ICMPv6ND_NA) \
           and not ndp_msg.haslayer(ICMPv6ND_Redirect) :
           raise AddressException("tried to sign a packet that is not a NDP message")


        # TODO:
        # for now, we only take the first algorithm of the list,
        # latter, we will implement a round-robin mechanism
        nc = NeighCache()
        ( sign, verif ) = nc.get_ssao(ndp_msg.dst)
        neigh_sigalg = (sign + verif)
        sigtypeID = self.sign_doable(neigh_sigalg)
        if sigtypeID == None:
            if NDprotector.ECCsupport and isinstance(self.__key,ECCkey):
                sigtypeID = self.__key.get_sigtypeID()[0]
                warn("No matching Signature Algorithm to sign the message, using %s\n" \
                       % SigTypeID[sigtypeID])
            else:
                warn("No matching Signature Algorithm to sign the message, using RSA/SHA-1\n")
                sigtypeID = 0


        cgapds = CGAParams(modifier = pkcs_i2osp(self.__modifier, 16), \
                prefix = self.__prefix, \
                ccount = self.__collcount, \
                pubkey = self.__pubkey, \
                ext = self.__ext)
        # in some case, we may not really want to add a nonce value
        if nonce is None:
            # no nonce value are joined with this message
            ndp_msg /= ICMPv6NDOptCGA(cgaparams = cgapds) / \
                       ICMPv6NDOptTimestamp()
        else:

            # add the different options to a message 
            ndp_msg /= ICMPv6NDOptCGA(cgaparams = cgapds) / \
                       ICMPv6NDOptTimestamp() / \
                       ICMPv6NDOptNonce(nonce=nonce) 

        # compute the available Signature Algorithms
        sigalgs = SigAlgList_compute(sigtypeID, NDprotector.SignatureAlgorithms)

        ndp_msg /= ICMPv6NDOptSSA(sigalgs=sigalgs)

        # dirty hack: force the update of the payload length
        extra_payload_len = len(str(ndp_msg.getlayer(ICMPv6NDOptCGA)))
        ndp_msg[IPv6].plen += extra_payload_len

        # dirty hack: force to recompute the (ICMP) checksum
        del(ndp_msg[IPv6].payload.cksum)

        # freezing data inside the new option fields
        ndp_msg = IPv6(str(ndp_msg))

        # need to bind the key hash with address' PubKey
        pubkey = load_pkey(self.__key, NDprotector.ECCsupport)

        keyh = get_public_key_hash(pubkey, sigtypeID=sigtypeID)

        # adding the signature
        ndp_msg /= ICMPv6NDOptUSSig(key=self.__key, pos = self.__keypos,
                keyh = keyh, sigtypeID=sigtypeID)
        


        # dirty hack: force the update of the payload length
        extra_payload_len = len(str(ndp_msg.getlayer(ICMPv6NDOptUSSig)))
        ndp_msg[IPv6].plen += extra_payload_len


        # dirty hack: force to recompute the (ICMP) checksum (once again)
        del(ndp_msg[IPv6].payload.cksum)


        return ndp_msg
Exemplo n.º 2
0
    def sign(self,data, dad=False, nonce=None):
        """sign the data with RSA signature option, adds timestamp, nonce, etc.
        Data must be a valid NS, NA, RS, RA or ICMPv6 redirect packet"""
        ndp_msg = IPv6(data)

        if dad and ndp_msg[IPv6].src != "::" :
            raise AddressException("tried to sign a DAD message with the null address")
        elif not dad and ndp_msg[IPv6].src != self.__address:
            raise AddressException("tried to sign a message with an incorrect source address")


        if not ndp_msg.haslayer(ICMPv6ND_RS) \
           and not ndp_msg.haslayer(ICMPv6ND_RA) \
           and not ndp_msg.haslayer(ICMPv6ND_NS) \
           and not ndp_msg.haslayer(ICMPv6ND_NA) \
           and not ndp_msg.haslayer(ICMPv6ND_Redirect) :
           raise AddressException("tried to sign a packet that is not a NDP message")


        # TODO:
        # for now, we only take the first algorithm of the list,
        # latter, we will implement a round-robin mechanism
        nc = NeighCache()
        ( sign, verif ) = nc.get_ssao(ndp_msg.dst)
        neigh_sigalg = (sign + verif)
        sigtypeID = self.sign_doable(neigh_sigalg)
        if sigtypeID == None:
            if NDprotector.ECCsupport and isinstance(self.__key,ECCkey):
                sigtypeID = self.__key.get_sigtypeID()[0]
                warn("No matching Signature Algorithm to sign the message, using %s\n" \
                       % SigTypeID[sigtypeID])
            else:
                warn("No matching Signature Algorithm to sign the message, using RSA/SHA-1\n")
                sigtypeID = 0


        cgapds = CGAParams(modifier = pkcs_i2osp(self.__modifier, 16), \
                prefix = self.__prefix, \
                ccount = self.__collcount, \
                pubkey = self.__pubkey, \
                ext = self.__ext)
        # in some case, we may not really want to add a nonce value
        if nonce is None:
            # no nonce value are joined with this message
            ndp_msg /= ICMPv6NDOptCGA(cgaparams = cgapds) / \
                       ICMPv6NDOptTimestamp()
        else:

            # add the different options to a message 
            ndp_msg /= ICMPv6NDOptCGA(cgaparams = cgapds) / \
                       ICMPv6NDOptTimestamp() / \
                       ICMPv6NDOptNonce(nonce=nonce) 

        # compute the available Signature Algorithms
        sigalgs = SigAlgList_compute(sigtypeID, NDprotector.SignatureAlgorithms)

        ndp_msg /= ICMPv6NDOptSSA(sigalgs=sigalgs)

        # dirty hack: force the update of the payload length
        extra_payload_len = len(str(ndp_msg.getlayer(ICMPv6NDOptCGA)))
        ndp_msg[IPv6].plen += extra_payload_len

        # dirty hack: force to recompute the (ICMP) checksum
        del(ndp_msg[IPv6].payload.cksum)

        # freezing data inside the new option fields
        ndp_msg = IPv6(str(ndp_msg))

        # need to bind the key hash with address' PubKey
        pubkey = load_pkey(self.__key, NDprotector.ECCsupport)

        keyh = get_public_key_hash(pubkey, sigtypeID=sigtypeID)

        # adding the signature
        ndp_msg /= ICMPv6NDOptUSSig(key=self.__key, pos = self.__keypos,
                keyh = keyh, sigtypeID=sigtypeID)
        


        # dirty hack: force the update of the payload length
        extra_payload_len = len(str(ndp_msg.getlayer(ICMPv6NDOptUSSig)))
        ndp_msg[IPv6].plen += extra_payload_len


        # dirty hack: force to recompute the (ICMP) checksum (once again)
        del(ndp_msg[IPv6].payload.cksum)


        return ndp_msg
Exemplo n.º 3
0
    def __init__(self,interface=None,\
            address=None,prefix=None,\
            key=None,modifier=None,sec=None,\
            collcount=0, ext=None, keypos=0,\
            publickey=None,\
            autoconf=False, dad=True,\
            ** extrap):
        """if no interface name is given,
        we'll use scapy6send to determine
        a working one and use it"""

        self.__interface = None
        self.__address = None
        self.__prefix = None
        self.__key = None
        self.__pubkey = None
        self.__modifier = 0
        self.__collcount = 0
        self.__sec = 0
        self.__ext = []
        self.__keypos = keypos
        self.__autoconf = autoconf

        # we can't put ext=[] as a default argument because of its "mutable" nature
        if ext == None: ext = []
        
        self.__ext = ext

        plugins = get_plugins_by_capability("Address")

        for plugin in plugins:
            plugin.init_address(self,extrap)

        # time at the beginning of the function
        beginning = time.time()

        if not address and not prefix:
            raise Exception("can not configure an address without at least a prefix")
        if address and (not key or (not modifier and modifier !=0 )):
            raise Exception("can not use an address without at least the key and the modifier")
        if interface == None:
            warn("no interface name given, using %s\n" % conf.iface)
            self.__interface = conf.iface
        else:
            if interface in get_if_list():
                self.__interface = interface
            else:
                raise AddressException("No such interface for the address: %s", interface)
        
        if collcount >= 0 and collcount <= 3:
            self.__collcount = collcount
        else:
            raise AddressException("The collision counter must be between 0 and 3")

        if modifier == None:
            self.__modifier= random.randint(0,2**128 -1)
        else:
            self.__modifier= modifier

        if sec !=  None:
            self.__sec=sec
        else:
            self.__sec=NDprotector.default_sec_value

        if prefix:
            # prefix length is /64
            if socket.inet_pton(socket.AF_INET6,prefix)[8:] == \
                    '\x00'*8 :
                self.__prefix == prefix
            else:
                raise AddressException("prefix %s is not valid" % prefix)

        # generate a key or use a default one when none is passed
        if key is None and NDprotector.default_publickey:
            self.__key = load_key(NDprotector.default_publickey, NDprotector.ECCsupport)
            self.__pubkey = load_pkey(NDprotector.default_publickey, NDprotector.ECCsupport)

        elif key is None and not NDprotector.default_publickey:
            warn("Computing an RSA key pair\n")
            k = Popen( [ OpenSSL , "genrsa", str(NDprotector.rsa_key_size)], stdout=PIPE, stderr=PIPE)
            key = k.stdout.read()
            if not "BEGIN RSA PRIVATE KEY" in key:
                raise AddressException("unable to compute the RSA public Key")
            self.__key = Key(key)
            self.__pubkey = self.__key.toPubKey()

        # a key was passed
        else: 
            self.__key  = load_key(key, NDprotector.ECCsupport)
            self.__pubkey = load_pkey(key, NDprotector.ECCsupport)

        # set the Public Key that will be store in the CGA PDS
        # in the Public Key field
        if publickey:
            self.__pubkey = load_pkey(NDprotector.default_publickey, NDprotector.ECCsupport)


        if address == None:
            self.__prefix = prefix
            warn("Generating CGA\n")
            if type(modifier) == int:
                modifier = pkcs_i2osp(modifier,16)
            res = CGAgen(prefix, self.__pubkey, self.__sec, modifier = modifier, ext=ext, do_dad=False)
            if type(res) is tuple:
                (self.__address,param) = res
                self.__modifier =  pkcs_os2ip(param.modifier)
            else:
                raise AddressException("failed to create an address, perhaps you should investage on the public key files")
        else:
            # we use the address passed in parameter
            self.__address = address

            # weak TODO: find something cleaner to extract the prefix from the address
            self.__prefix = socket.inet_ntop(socket.AF_INET6, \
                    socket.inet_pton(socket.AF_INET6,address)[:8]+"\x00"*8)
            modifier = pkcs_i2osp(self.__modifier,16)

            self.__sec = ord(socket.inet_pton(\
                socket.AF_INET6,self.__address)[8]) >> 5

	    print "About to invoke CGAverify in Address.py, check 1" # jochoi: debug
            if not CGAverify(self.__address, CGAParams(modifier=modifier, prefix=self.__prefix, \
                            ccount = self.__collcount, pubkey = self.__pubkey, \
                            ext = ext)):
                raise AddressException("Address %s is not a valid CGA" % self.__address)
        if NDprotector.assign_addresses:
            self.assign(dad=dad)

        end = time.time()
        warn("CGA address %s computed and assigned in %f seconds\n" %\
                (self.__address, end - beginning))
Exemplo n.º 4
0
    def __init__(self,interface=None,\
            address=None,prefix=None,\
            key=None,modifier=None,sec=None,\
            collcount=0, ext=None, keypos=0,\
            publickey=None,\
            autoconf=False, dad=True,\
            ** extrap):
        """if no interface name is given,
        we'll use scapy6send to determine
        a working one and use it"""

        self.__interface = None
        self.__address = None
        self.__prefix = None
        self.__key = None
        self.__pubkey = None
        self.__modifier = 0
        self.__collcount = 0
        self.__sec = 0
        self.__ext = []
        self.__keypos = keypos
        self.__autoconf = autoconf

        # we can't put ext=[] as a default argument because of its "mutable" nature
        if ext == None: ext = []
        
        self.__ext = ext

        plugins = get_plugins_by_capability("Address")

        for plugin in plugins:
            plugin.init_address(self,extrap)

        # time at the beginning of the function
        beginning = time.time()

        if not address and not prefix:
            raise Exception("can not configure an address without at least a prefix")
        if address and (not key or (not modifier and modifier !=0 )):
            raise Exception("can not use an address without at least the key and the modifier")
        if interface == None:
            warn("no interface name given, using %s\n" % conf.iface)
            self.__interface = conf.iface
        else:
            if interface in get_if_list():
                self.__interface = interface
            else:
                raise AddressException("No such interface for the address: %s", interface)
        
        if collcount >= 0 and collcount <= 3:
            self.__collcount = collcount
        else:
            raise AddressException("The collision counter must be between 0 and 3")

        if modifier == None:
            self.__modifier= random.randint(0,2**128 -1)
        else:
            self.__modifier= modifier

        if sec !=  None:
            self.__sec=sec
        else:
            self.__sec=NDprotector.default_sec_value

        if prefix:
            # prefix length is /64
            if socket.inet_pton(socket.AF_INET6,prefix)[8:] == \
                    '\x00'*8 :
                self.__prefix == prefix
            else:
                raise AddressException("prefix %s is not valid" % prefix)

        # generate a key or use a default one when none is passed
        if key is None and NDprotector.default_publickey:
            self.__key = load_key(NDprotector.default_publickey, NDprotector.ECCsupport)
            self.__pubkey = load_pkey(NDprotector.default_publickey, NDprotector.ECCsupport)

        elif key is None and not NDprotector.default_publickey:
            warn("Computing an RSA key pair\n")
            k = Popen( [ OpenSSL , "genrsa", str(NDprotector.rsa_key_size)], stdout=PIPE, stderr=PIPE)
            key = k.stdout.read()
            if not "BEGIN RSA PRIVATE KEY" in key:
                raise AddressException("unable to compute the RSA public Key")
            self.__key = Key(key)
            self.__pubkey = self.__key.toPubKey()

        # a key was passed
        else: 
            self.__key  = load_key(key, NDprotector.ECCsupport)
            self.__pubkey = load_pkey(key, NDprotector.ECCsupport)

        # set the Public Key that will be store in the CGA PDS
        # in the Public Key field
        if publickey:
            self.__pubkey = load_pkey(NDprotector.default_publickey, NDprotector.ECCsupport)


        if address == None:
            self.__prefix = prefix
            warn("Generating CGA\n")
            if type(modifier) == int:
                modifier = pkcs_i2osp(modifier,16)
            res = CGAgen(prefix, self.__pubkey, self.__sec, modifier = modifier, ext=ext, do_dad=False)
            if type(res) is tuple:
                (self.__address,param) = res
                self.__modifier =  pkcs_os2ip(param.modifier)
            else:
                raise AddressException("failed to create an address, perhaps you should investage on the public key files")
        else:
            # we use the address passed in parameter
            self.__address = address

            # weak TODO: find something cleaner to extract the prefix from the address
            self.__prefix = socket.inet_ntop(socket.AF_INET6, \
                    socket.inet_pton(socket.AF_INET6,address)[:8]+"\x00"*8)
            modifier = pkcs_i2osp(self.__modifier,16)

            self.__sec = ord(socket.inet_pton(\
                socket.AF_INET6,self.__address)[8]) >> 5

            if not CGAverify(self.__address, CGAParams(modifier=modifier, prefix=self.__prefix, \
                            ccount = self.__collcount, pubkey = self.__pubkey, \
                            ext = ext)):
                raise AddressException("Address %s is not a valid CGA" % self.__address)
        if NDprotector.assign_addresses:
            self.assign(dad=dad)

        end = time.time()
        warn("CGA address %s computed and assigned in %f seconds\n" %\
                (self.__address, end - beginning))