diff --git a/RNS/Link.py b/RNS/Link.py index 328894a..0893aad 100644 --- a/RNS/Link.py +++ b/RNS/Link.py @@ -41,7 +41,6 @@ class Link: except Exception as e: RNS.log("Validating link request failed", RNS.LOG_VERBOSE) return None - else: RNS.log("Invalid link request payload size, dropping request", RNS.LOG_VERBOSE) @@ -49,12 +48,15 @@ class Link: def __init__(self, destination=None, owner=None, peer_pub_bytes = None): + if destination != None and destination.type != RNS.Destination.SINGLE: + raise TypeError("Links can only be established to the \"single\" destination type") self.callbacks = LinkCallbacks() self.status = Link.PENDING self.type = RNS.Destination.LINK self.owner = owner self.destination = destination self.attached_interface = None + self.__encryption_disabled = False if self.destination == None: self.initiator = False else: @@ -142,6 +144,8 @@ class Link: self.callbacks.packet(plaintext, packet) def encrypt(self, plaintext): + if self.__encryption_disabled: + return plaintext try: fernet = Fernet(base64.urlsafe_b64encode(self.derived_key)) ciphertext = base64.urlsafe_b64decode(fernet.encrypt(plaintext)) @@ -151,6 +155,8 @@ class Link: def decrypt(self, ciphertext): + if self.__encryption_disabled: + return ciphertext try: fernet = Fernet(base64.urlsafe_b64encode(self.derived_key)) plaintext = fernet.decrypt(base64.urlsafe_b64encode(ciphertext)) @@ -170,5 +176,14 @@ class Link: def resource_completed_callback(self, callback): self.callbacks.resource_completed = callback + def disableEncryption(self): + if (RNS.Reticulum.should_allow_unencrypted()): + RNS.log("The link "+str(self)+" was downgraded to an encryptionless link", RNS.LOG_NOTICE) + self.__encryption_disabled = True + else: + RNS.log("Attempt to disable encryption on link, but encryptionless links are not allowed by config.", RNS.LOG_CRITICAL) + RNS.log("Shutting down Reticulum now!", RNS.LOG_CRITICAL) + RNS.panic() + def __str__(self): return RNS.prettyhexrep(self.link_id) \ No newline at end of file diff --git a/RNS/Reticulum.py b/RNS/Reticulum.py index 9cfedbf..5069f65 100755 --- a/RNS/Reticulum.py +++ b/RNS/Reticulum.py @@ -28,6 +28,8 @@ class Reticulum: Reticulum.storagepath = Reticulum.configdir+"/storage" Reticulum.cachepath = Reticulum.configdir+"/storage/cache" + Reticulum.__allow_unencrypted = False + if not os.path.isdir(Reticulum.storagepath): os.makedirs(Reticulum.storagepath) @@ -61,6 +63,24 @@ class Reticulum: if RNS.loglevel > 6: RNS.loglevel = 6 + if "reticulum" in self.config: + for option in self.config["reticulum"]: + value = self.config["reticulum"][option] + if option == "allow_unencrypted": + if value == "true": + RNS.log("", RNS.LOG_CRITICAL) + RNS.log("! ! !", RNS.LOG_CRITICAL) + RNS.log("", RNS.LOG_CRITICAL) + RNS.log("Danger! Encryptionless links have been allowed in the config file!", RNS.LOG_CRITICAL) + RNS.log("Beware of the consequences! Any data sent over a link can potentially be intercepted,", RNS.LOG_CRITICAL) + RNS.log("read and modified! If you are not absolutely sure that you want this,", RNS.LOG_CRITICAL) + RNS.log("you should exit Reticulum NOW and change your config file!", RNS.LOG_CRITICAL) + RNS.log("", RNS.LOG_CRITICAL) + RNS.log("! ! !", RNS.LOG_CRITICAL) + RNS.log("", RNS.LOG_CRITICAL) + Reticulum.__allow_unencrypted = True + + for name in self.config["interfaces"]: c = self.config["interfaces"][name] try: @@ -235,4 +255,8 @@ class Reticulum: if not os.path.isdir(Reticulum.configdir): os.makedirs(Reticulum.configdir) self.config.write() - self.applyConfig() \ No newline at end of file + self.applyConfig() + + @staticmethod + def should_allow_unencrypted(): + return Reticulum.__allow_unencrypted \ No newline at end of file diff --git a/RNS/__init__.py b/RNS/__init__.py index f566c32..45b4d0c 100755 --- a/RNS/__init__.py +++ b/RNS/__init__.py @@ -1,4 +1,5 @@ import os +import sys import glob import time @@ -73,4 +74,7 @@ def hexrep(data, delimit=True): def prettyhexrep(data): delimiter = "" hexrep = "<"+delimiter.join("{:02x}".format(ord(c)) for c in data)+">" - return hexrep \ No newline at end of file + return hexrep + +def panic(): + os._exit(255) \ No newline at end of file