Fixed race condition for link initiators on timed out link establishment
This commit is contained in:
parent
97f97eb063
commit
bab779a34c
83
RNS/Link.py
83
RNS/Link.py
@ -264,41 +264,50 @@ class Link:
|
|||||||
self.had_outbound()
|
self.had_outbound()
|
||||||
|
|
||||||
def validate_proof(self, packet):
|
def validate_proof(self, packet):
|
||||||
if self.status == Link.PENDING:
|
try:
|
||||||
if self.initiator and len(packet.data) == RNS.Identity.SIGLENGTH//8+Link.ECPUBSIZE//2:
|
if self.status == Link.PENDING:
|
||||||
peer_pub_bytes = packet.data[RNS.Identity.SIGLENGTH//8:RNS.Identity.SIGLENGTH//8+Link.ECPUBSIZE//2]
|
if self.initiator and len(packet.data) == RNS.Identity.SIGLENGTH//8+Link.ECPUBSIZE//2:
|
||||||
peer_sig_pub_bytes = self.destination.identity.get_public_key()[Link.ECPUBSIZE//2:Link.ECPUBSIZE]
|
peer_pub_bytes = packet.data[RNS.Identity.SIGLENGTH//8:RNS.Identity.SIGLENGTH//8+Link.ECPUBSIZE//2]
|
||||||
self.load_peer(peer_pub_bytes, peer_sig_pub_bytes)
|
peer_sig_pub_bytes = self.destination.identity.get_public_key()[Link.ECPUBSIZE//2:Link.ECPUBSIZE]
|
||||||
self.handshake()
|
self.load_peer(peer_pub_bytes, peer_sig_pub_bytes)
|
||||||
|
self.handshake()
|
||||||
|
|
||||||
self.establishment_cost += len(packet.raw)
|
self.establishment_cost += len(packet.raw)
|
||||||
signed_data = self.link_id+self.peer_pub_bytes+self.peer_sig_pub_bytes
|
signed_data = self.link_id+self.peer_pub_bytes+self.peer_sig_pub_bytes
|
||||||
signature = packet.data[:RNS.Identity.SIGLENGTH//8]
|
signature = packet.data[:RNS.Identity.SIGLENGTH//8]
|
||||||
|
|
||||||
if self.destination.identity.validate(signature, signed_data):
|
|
||||||
self.rtt = time.time() - self.request_time
|
|
||||||
self.attached_interface = packet.receiving_interface
|
|
||||||
self.__remote_identity = self.destination.identity
|
|
||||||
self.status = Link.ACTIVE
|
|
||||||
self.activated_at = time.time()
|
|
||||||
self.last_proof = self.activated_at
|
|
||||||
RNS.Transport.activate_link(self)
|
|
||||||
RNS.log("Link "+str(self)+" established with "+str(self.destination)+", RTT is "+str(round(self.rtt, 3))+"s", RNS.LOG_VERBOSE)
|
|
||||||
|
|
||||||
if self.rtt != None and self.establishment_cost != None and self.rtt > 0 and self.establishment_cost > 0:
|
if self.destination.identity.validate(signature, signed_data):
|
||||||
self.establishment_rate = self.establishment_cost/self.rtt
|
if self.status != Link.PENDING:
|
||||||
|
raise IOError("Invalid link state for proof validation")
|
||||||
|
|
||||||
rtt_data = umsgpack.packb(self.rtt)
|
self.rtt = time.time() - self.request_time
|
||||||
rtt_packet = RNS.Packet(self, rtt_data, context=RNS.Packet.LRRTT)
|
self.attached_interface = packet.receiving_interface
|
||||||
rtt_packet.send()
|
self.__remote_identity = self.destination.identity
|
||||||
self.had_outbound()
|
self.status = Link.ACTIVE
|
||||||
|
self.activated_at = time.time()
|
||||||
|
self.last_proof = self.activated_at
|
||||||
|
RNS.Transport.activate_link(self)
|
||||||
|
RNS.log("Link "+str(self)+" established with "+str(self.destination)+", RTT is "+str(round(self.rtt, 3))+"s", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
|
if self.rtt != None and self.establishment_cost != None and self.rtt > 0 and self.establishment_cost > 0:
|
||||||
|
self.establishment_rate = self.establishment_cost/self.rtt
|
||||||
|
|
||||||
if self.callbacks.link_established != None:
|
rtt_data = umsgpack.packb(self.rtt)
|
||||||
thread = threading.Thread(target=self.callbacks.link_established, args=(self,))
|
rtt_packet = RNS.Packet(self, rtt_data, context=RNS.Packet.LRRTT)
|
||||||
thread.daemon = True
|
rtt_packet.send()
|
||||||
thread.start()
|
self.had_outbound()
|
||||||
else:
|
|
||||||
RNS.log("Invalid link proof signature received by "+str(self)+". Ignoring.", RNS.LOG_DEBUG)
|
if self.callbacks.link_established != None:
|
||||||
|
thread = threading.Thread(target=self.callbacks.link_established, args=(self,))
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
else:
|
||||||
|
RNS.log("Invalid link proof signature received by "+str(self)+". Ignoring.", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.status = Link.CLOSED
|
||||||
|
RNS.log("An error ocurred while validating link request proof on "+str(self)+".", RNS.LOG_ERROR)
|
||||||
|
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
|
||||||
def identify(self, identity):
|
def identify(self, identity):
|
||||||
@ -520,16 +529,16 @@ class Link:
|
|||||||
next_check = self.request_time + self.establishment_timeout
|
next_check = self.request_time + self.establishment_timeout
|
||||||
sleep_time = next_check - time.time()
|
sleep_time = next_check - time.time()
|
||||||
if time.time() >= self.request_time + self.establishment_timeout:
|
if time.time() >= self.request_time + self.establishment_timeout:
|
||||||
if self.initiator:
|
|
||||||
RNS.log("Timeout waiting for link request proof", RNS.LOG_DEBUG)
|
|
||||||
else:
|
|
||||||
RNS.log("Timeout waiting for RTT packet from link initiator", RNS.LOG_DEBUG)
|
|
||||||
|
|
||||||
self.status = Link.CLOSED
|
self.status = Link.CLOSED
|
||||||
self.teardown_reason = Link.TIMEOUT
|
self.teardown_reason = Link.TIMEOUT
|
||||||
self.link_closed()
|
self.link_closed()
|
||||||
sleep_time = 0.001
|
sleep_time = 0.001
|
||||||
|
|
||||||
|
if self.initiator:
|
||||||
|
RNS.log("Timeout waiting for link request proof", RNS.LOG_DEBUG)
|
||||||
|
else:
|
||||||
|
RNS.log("Timeout waiting for RTT packet from link initiator", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
elif self.status == Link.ACTIVE:
|
elif self.status == Link.ACTIVE:
|
||||||
activated_at = self.activated_at if self.activated_at != None else 0
|
activated_at = self.activated_at if self.activated_at != None else 0
|
||||||
last_inbound = max(max(self.last_inbound, self.last_proof), activated_at)
|
last_inbound = max(max(self.last_inbound, self.last_proof), activated_at)
|
||||||
@ -847,7 +856,7 @@ class Link:
|
|||||||
try:
|
try:
|
||||||
self.fernet = Fernet(self.derived_key)
|
self.fernet = Fernet(self.derived_key)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not "+str(self)+" instantiate Fernet while performin encryption on link. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Could not instantiate Fernet while performin encryption on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
return self.fernet.encrypt(plaintext)
|
return self.fernet.encrypt(plaintext)
|
||||||
|
@ -1741,6 +1741,8 @@ class Transport:
|
|||||||
def activate_link(link):
|
def activate_link(link):
|
||||||
RNS.log("Activating link "+str(link), RNS.LOG_EXTREME)
|
RNS.log("Activating link "+str(link), RNS.LOG_EXTREME)
|
||||||
if link in Transport.pending_links:
|
if link in Transport.pending_links:
|
||||||
|
if link.status != Link.PENDING:
|
||||||
|
raise IOError("Invalid link state for link activation")
|
||||||
Transport.pending_links.remove(link)
|
Transport.pending_links.remove(link)
|
||||||
Transport.active_links.append(link)
|
Transport.active_links.append(link)
|
||||||
link.status = RNS.Link.ACTIVE
|
link.status = RNS.Link.ACTIVE
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "0.5.4"
|
__version__ = "0.5.5"
|
||||||
|
Loading…
Reference in New Issue
Block a user