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

View File

@ -214,30 +214,38 @@ class Identity:
if packet.packet_type == RNS.Packet.ANNOUNCE: if packet.packet_type == RNS.Packet.ANNOUNCE:
destination_hash = packet.destination_hash destination_hash = packet.destination_hash
public_key = packet.data[:Identity.KEYSIZE//8] public_key = packet.data[:Identity.KEYSIZE//8]
random_hash = packet.data[Identity.KEYSIZE//8:Identity.KEYSIZE//8+10] name_hash = packet.data[Identity.KEYSIZE//8:Identity.KEYSIZE//8+Identity.HASHLENGTH//8]
signature = packet.data[Identity.KEYSIZE//8+10:Identity.KEYSIZE//8+10+Identity.KEYSIZE//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"" 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:] 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 app_data = None
announced_identity = Identity(create_keys=False) announced_identity = Identity(create_keys=False)
announced_identity.load_public_key(public_key) announced_identity.load_public_key(public_key)
if announced_identity.pub != None and announced_identity.validate(signature, signed_data): if announced_identity.pub != None and announced_identity.validate(signature, signed_data):
RNS.Identity.remember(packet.get_hash(), destination_hash, public_key, app_data) hash_material = name_hash+announced_identity.hash
del announced_identity 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
if hasattr(packet, "transport_id") and packet.transport_id != None:
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" "+str(packet.hops)+" hops away, received via "+RNS.prettyhexrep(packet.transport_id)+" on "+str(packet.receiving_interface), RNS.LOG_EXTREME)
else:
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" "+str(packet.hops)+" hops away, received on "+str(packet.receiving_interface), RNS.LOG_EXTREME)
return True
if hasattr(packet, "transport_id") and packet.transport_id != None:
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" "+str(packet.hops)+" hops away, received via "+RNS.prettyhexrep(packet.transport_id)+" on "+str(packet.receiving_interface), RNS.LOG_EXTREME)
else: else:
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" "+str(packet.hops)+" hops away, received on "+str(packet.receiving_interface), RNS.LOG_EXTREME) return False
return True
else: else:
RNS.log("Received invalid announce for "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG) RNS.log("Received invalid announce for "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG)