Fixed missing validation in announce processing

This commit is contained in:
Mark Qvist 2022-10-04 06:59:33 +02:00
parent 1380016995
commit 8a61d2c8d5
2 changed files with 56 additions and 33 deletions

View File

@ -70,7 +70,7 @@ class Destination:
directions = [IN, OUT]
@staticmethod
def full_name(app_name, *aspects):
def expand_name(identity, app_name, *aspects):
"""
:returns: A string containing the full human-readable name of the destination, for an app_name and a number of aspects.
"""
@ -81,20 +81,27 @@ class Destination:
name = app_name
for aspect in aspects:
if "." in aspect: raise ValueError("Dots can't be used in aspects")
name = name + "." + aspect
name += "." + aspect
if identity != None:
name += "." + identity.hexhash
return name
@staticmethod
def hash(app_name, *aspects):
"""
:returns: A destination name in adressable hash form, for an app_name and a number of aspects.
"""
name = Destination.full_name(app_name, *aspects)
# @staticmethod
# def hash(identity, app_name, *aspects):
# """
# :returns: A destination name in adressable hash form, for an app_name and a number of aspects.
# """
# base_name = Destination.expand_name(None, app_name, *aspects)
# hash_material = RNS.Identity.full_hash(base_name.encode("utf-8"))
# Create a digest for the destination
return RNS.Identity.full_hash(name.encode("utf-8"))[:RNS.Reticulum.TRUNCATED_HASHLENGTH//8]
# if identity != None:
# hash_material += identity.hash
# # Create a digest for the destination
# return RNS.Identity.full_hash(hash_material)[:RNS.Reticulum.TRUNCATED_HASHLENGTH//8]
@staticmethod
def app_and_aspects_from_name(full_name):
@ -129,9 +136,6 @@ class Destination:
self.links = []
if identity != None and type == Destination.SINGLE:
aspects = aspects+(identity.hexhash,)
if identity == None and direction == Destination.IN and self.type != Destination.PLAIN:
identity = RNS.Identity()
aspects = aspects+(identity.hexhash,)
@ -140,12 +144,18 @@ class Destination:
raise TypeError("Selected destination type PLAIN cannot hold an identity")
self.identity = identity
self.full_name = Destination.expand_name(identity, app_name, *aspects)
self.name = Destination.full_name(app_name, *aspects)
self.hash = Destination.hash(app_name, *aspects)
self.name_hash = RNS.Identity.full_hash(self.expand_name(None, app_name, *aspects).encode("utf-8"))
self.addr_hash_material = self.name_hash
if self.identity != None:
self.addr_hash_material += self.identity.hash
# Generate the destination address hash
self.hash = RNS.Identity.full_hash(self.addr_hash_material)[:RNS.Reticulum.TRUNCATED_HASHLENGTH//8]
self.hexhash = self.hash.hex()
self.default_app_data = None
self.default_app_data = None
self.callback = None
self.proofcallback = None
@ -156,10 +166,10 @@ class Destination:
"""
:returns: A human-readable representation of the destination including addressable hash and full name.
"""
return "<"+self.name+"/"+self.hexhash+">"
return "<"+self.full_name+"/"+self.hexhash+">"
def announce(self, app_data=None, path_response=False):
def announce(self, app_data=None, path_response=False, send=True):
"""
Creates an announce packet for this destination and broadcasts it on all
relevant interfaces. Application specific data can be added to the announce.
@ -181,13 +191,13 @@ class Destination:
if isinstance(returned_app_data, bytes):
app_data = returned_app_data
signed_data = self.hash+self.identity.get_public_key()+random_hash
signed_data = self.hash+self.identity.get_public_key()+self.name_hash+random_hash
if app_data != None:
signed_data += app_data
signature = self.identity.sign(signed_data)
announce_data = self.identity.get_public_key()+random_hash+signature
announce_data = self.identity.get_public_key()+self.name_hash+random_hash+signature
if app_data != None:
announce_data += app_data
@ -197,7 +207,12 @@ class Destination:
else:
announce_context = RNS.Packet.NONE
RNS.Packet(self, announce_data, RNS.Packet.ANNOUNCE, context = announce_context).send()
announce_packet = RNS.Packet(self, announce_data, RNS.Packet.ANNOUNCE, context = announce_context)
if send:
announce_packet.send()
else:
return announce_packet
def accepts_links(self, accepts = None):
"""

View File

@ -214,21 +214,26 @@ class Identity:
if packet.packet_type == RNS.Packet.ANNOUNCE:
destination_hash = packet.destination_hash
public_key = packet.data[:Identity.KEYSIZE//8]
random_hash = packet.data[Identity.KEYSIZE//8:Identity.KEYSIZE//8+10]
signature = packet.data[Identity.KEYSIZE//8+10:Identity.KEYSIZE//8+10+Identity.KEYSIZE//8]
name_hash = packet.data[Identity.KEYSIZE//8:Identity.KEYSIZE//8+Identity.HASHLENGTH//8]
random_hash = packet.data[Identity.KEYSIZE//8+Identity.HASHLENGTH//8:Identity.KEYSIZE//8+Identity.HASHLENGTH//8+10]
signature = packet.data[Identity.KEYSIZE//8+Identity.HASHLENGTH//8+10:Identity.KEYSIZE//8+Identity.HASHLENGTH//8+10+Identity.SIGLENGTH//8]
app_data = b""
if len(packet.data) > Identity.KEYSIZE//8+10+Identity.KEYSIZE//8:
if len(packet.data) > Identity.KEYSIZE//8+Identity.HASHLENGTH//8+10+Identity.SIGLENGTH//8:
app_data = packet.data[Identity.KEYSIZE//8+10+Identity.KEYSIZE//8:]
signed_data = destination_hash+public_key+random_hash+app_data
signed_data = destination_hash+public_key+name_hash+random_hash+app_data
if not len(packet.data) > Identity.KEYSIZE//8+10+Identity.KEYSIZE//8:
if not len(packet.data) > Identity.KEYSIZE//8+Identity.HASHLENGTH//8+10+Identity.SIGLENGTH//8:
app_data = None
announced_identity = Identity(create_keys=False)
announced_identity.load_public_key(public_key)
if announced_identity.pub != None and announced_identity.validate(signature, signed_data):
hash_material = name_hash+announced_identity.hash
expected_hash = RNS.Identity.full_hash(hash_material)[:RNS.Reticulum.TRUNCATED_HASHLENGTH//8]
if destination_hash == expected_hash:
RNS.Identity.remember(packet.get_hash(), destination_hash, public_key, app_data)
del announced_identity
@ -239,6 +244,9 @@ class Identity:
return True
else:
return False
else:
RNS.log("Received invalid announce for "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG)
del announced_identity