Exemple #1
0
    def __advertise_job(self):
        data = ResourceAdvertisement(self).pack()
        self.advertisement_packet = RNS.Packet(self.link,
                                               data,
                                               context=RNS.Packet.RESOURCE_ADV)
        while not self.link.ready_for_new_resource():
            self.status = Resource.QUEUED
            sleep(0.25)

        try:
            self.advertisement_packet.send()
            self.last_activity = time.time()
            self.adv_sent = self.last_activity
            self.rtt = None
            self.status = Resource.ADVERTISED
            self.link.register_outgoing_resource(self)
            RNS.log(
                "Sent resource advertisement for " +
                RNS.prettyhexrep(self.hash), RNS.LOG_DEBUG)
        except Exception as e:
            RNS.log(
                "Could not advertise resource, the contained exception was: " +
                str(e), RNS.LOG_ERROR)
            self.cancel()
            return

        self.watchdog_job()
Exemple #2
0
def client_loop():
    global server_link

    # Wait for the link to become active
    while not server_link:
        time.sleep(0.1)

    should_quit = False
    while not should_quit:
        try:
            print("> ", end=" ")
            text = input()

            # Check if we should quit the example
            if text == "quit" or text == "q" or text == "exit":
                should_quit = True
                server_link.teardown()

            # If not, send the entered text over the link
            if text != "":
                data = text.encode("utf-8")
                if len(data) <= RNS.Link.MDU:
                    RNS.Packet(server_link, data).send()
                else:
                    RNS.log(
                        "Cannot send this packet, the data size of "+
                        str(len(data))+" bytes exceeds the link packet MDU of "+
                        str(RNS.Link.MDU)+" bytes",
                        RNS.LOG_ERROR
                    )

        except Exception as e:
            RNS.log("Error while sending data over the link: "+str(e))
            should_quit = True
            server_link.teardown()
Exemple #3
0
	def assemble(self):
		if not self.status == Resource.FAILED:
			try:
				self.status = Resource.ASSEMBLING
				stream = ""
				for part in self.parts:
					stream += part

				if self.encrypted:
					data = self.link.decrypt(stream)
				else:
					data = stream

				if self.compressed:
					self.data = bz2.decompress(data)
				else:
					self.data = data

				calculated_hash = RNS.Identity.fullHash(self.data+self.random_hash)

				if calculated_hash == self.hash:
					self.status = Resource.COMPLETE
					self.prove()
				else:
					self.status = Resource.CORRUPT

			except Exception as e:
				RNS.log("Error while assembling received resource.", RNS.LOG_ERROR)
				RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
				self.status = Resource.CORRUPT

			if self.callback != None:
				self.link.resource_concluded(self)
				self.callback(self)
Exemple #4
0
	def loadPublicKey(self, key):
		try:
			self.pub_bytes = key
			self.pub = load_der_public_key(self.pub_bytes, backend=default_backend())
			self.updateHashes()
		except Exception as e:
			RNS.log("Error while loading public key, the contained exception was: "+str(e), RNS.LOG_ERROR)
Exemple #5
0
def client_connected(link):
    global latest_client_link

    RNS.log("Client connected")
    link.set_link_closed_callback(client_disconnected)
    link.set_packet_callback(server_packet_received)
    latest_client_link = link
Exemple #6
0
 def query_for_peer(source_hash):
     try:
         RNS.Transport.request_path(bytes.fromhex(source_hash))
     except Exception as e:
         RNS.log(
             "Error while querying network for peer identity. The contained exception was: "
             + str(e), RNS.LOG_ERROR)
Exemple #7
0
    def __init__(self, app):
        RNS.log("Nomad Network Node starting...", RNS.LOG_VERBOSE)
        self.app = app
        self.identity = self.app.identity
        self.destination = RNS.Destination(self.identity, RNS.Destination.IN, RNS.Destination.SINGLE, "nomadnetwork", "node")
        self.last_announce = time.time()
        self.announce_interval = self.app.node_announce_interval
        self.job_interval = Node.JOB_INTERVAL
        self.should_run_jobs = True
        self.app_data = None
        self.name = self.app.node_name

        self.register_pages()
        self.register_files()

        self.destination.set_link_established_callback(self.peer_connected)

        if self.name == None:
            self.name = self.app.peer_settings["display_name"]+"'s Node"

        RNS.log("Node \""+self.name+"\" ready for incoming connections on "+RNS.prettyhexrep(self.destination.hash), RNS.LOG_VERBOSE)

        if self.app.node_announce_at_start:
            def delayed_announce():
                time.sleep(Node.START_ANNOUNCE_DELAY)
                self.announce()

            da_thread = threading.Thread(target=delayed_announce)
            da_thread.setDaemon(True)
            da_thread.start()

        job_thread = threading.Thread(target=self.__jobs)
        job_thread.setDaemon(True)
        job_thread.start()
Exemple #8
0
    def write_to_directory(self, directory_path):
        file_name = RNS.hexrep(self.hash, delimit=False)
        file_path = directory_path + "/" + file_name

        try:
            if not self.packed:
                self.pack()

            container = {
                "state": self.state,
                "lxmf_bytes": self.packed,
                "transport_encrypted": self.transport_encrypted,
                "transport_encryption": self.transport_encryption
            }

            packed_container = msgpack.packb(container)

            file = open(file_path, "wb")
            file.write(packed_container)
            file.close()

            return file_path

        except Exception as e:
            RNS.log(
                "Error while writing LXMF message to file \"" +
                str(file_path) + "\". The contained exception was: " + str(e),
                RNS.LOG_ERROR)
            return None
Exemple #9
0
def client_connected(link):
    # Check if the served directory still exists
    if os.path.isdir(serve_path):
        RNS.log("Client connected, sending file list...")

        link.set_link_closed_callback(client_disconnected)

        # We pack a list of files for sending in a packet
        data = umsgpack.packb(list_files())

        # Check the size of the packed data
        if len(data) <= RNS.Link.MDU:
            # If it fits in one packet, we will just
            # send it as a single packet over the link.
            list_packet = RNS.Packet(link, data)
            list_receipt = list_packet.send()
            list_receipt.set_timeout(APP_TIMEOUT)
            list_receipt.set_delivery_callback(list_delivered)
            list_receipt.set_timeout_callback(list_timeout)
        else:
            RNS.log("Too many files in served directory!", RNS.LOG_ERROR)
            RNS.log(
                "You should implement a function to split the filelist over multiple packets.",
                RNS.LOG_ERROR)
            RNS.log("Hint: The client already supports it :)", RNS.LOG_ERROR)

        # After this, we're just going to keep the link
        # open until the client requests a file. We'll
        # configure a function that get's called when
        # the client sends a packet with a file request.
        link.set_packet_callback(client_request)
    else:
        RNS.log("Client connected, but served path no longer exists!",
                RNS.LOG_ERROR)
        link.teardown()
Exemple #10
0
    def file_received(self, request_receipt):
        try:
            file_name = request_receipt.response[0]
            file_data = request_receipt.response[1]
            file_destination = self.app.downloads_path + "/" + file_name

            counter = 0
            while os.path.isfile(file_destination):
                counter += 1
                file_destination = self.app.downloads_path + "/" + file_name + "." + str(
                    counter)

            fh = open(file_destination, "wb")
            fh.write(file_data)
            fh.close()

            self.saved_file_name = file_destination.replace(
                self.app.downloads_path + "/", "", 1)
            self.status = Browser.DONE
            self.response_progress = 0

            self.update_display()
        except Exception as e:
            RNS.log(
                "An error occurred while handling file response. The contained exception was: "
                + str(e), RNS.LOG_ERROR)
Exemple #11
0
    def load_private_key(self, prv_bytes):
        """
        Load a private key into the instance.

        :param prv_bytes: The private key as *bytes*.
        :returns: True if the key was loaded, otherwise False.
        """
        try:
            self.prv_bytes = prv_bytes[:Identity.KEYSIZE // 8 // 2]
            self.prv = X25519PrivateKey.from_private_bytes(self.prv_bytes)
            self.sig_prv_bytes = prv_bytes[Identity.KEYSIZE // 8 // 2:]
            self.sig_prv = Ed25519PrivateKey.from_private_bytes(
                self.sig_prv_bytes)

            self.pub = self.prv.public_key()
            self.pub_bytes = self.pub.public_bytes(
                encoding=serialization.Encoding.Raw,
                format=serialization.PublicFormat.Raw)

            self.sig_pub = self.sig_prv.public_key()
            self.sig_pub_bytes = self.sig_pub.public_bytes(
                encoding=serialization.Encoding.Raw,
                format=serialization.PublicFormat.Raw)

            self.update_hashes()

            return True

        except Exception as e:
            raise e
            RNS.log("Failed to load identity key", RNS.LOG_ERROR)
            RNS.log("The contained exception was: " + str(e), RNS.LOG_ERROR)
            return False
Exemple #12
0
    def download_local_file(self, path):
        try:
            file_path = self.app.filespath + path.replace("/file", "", 1)
            if os.path.isfile(file_path):
                file_name = os.path.basename(file_path)
                file_destination = self.app.downloads_path + "/" + file_name

                counter = 0
                while os.path.isfile(file_destination):
                    counter += 1
                    file_destination = self.app.downloads_path + "/" + file_name + "." + str(
                        counter)

                fs = open(file_path, "rb")
                fd = open(file_destination, "wb")
                fd.write(fs.read())
                fd.close()
                fs.close()

                self.saved_file_name = file_destination.replace(
                    self.app.downloads_path + "/", "", 1)

                self.update_display()
            else:
                RNS.log(
                    "The requested local download file does not exist: " +
                    str(file_path), RNS.LOG_ERROR)

            self.status = Browser.DONE
            self.response_progress = 0

        except Exception as e:
            RNS.log(
                "An error occurred while handling file response. The contained exception was: "
                + str(e), RNS.LOG_ERROR)
Exemple #13
0
def filelist_timeout_job():
    time.sleep(APP_TIMEOUT)

    global server_files
    if len(server_files) == 0:
        RNS.log("Timed out waiting for filelist, exiting")
        os._exit(0)
Exemple #14
0
    def decrypt(self, ciphertext):
        if self.prv != None:
            plaintext = None
            try:
                chunksize = Identity.DECRYPT_CHUNKSIZE
                chunks = int(math.ceil(len(ciphertext) / (float(chunksize))))

                plaintext = b""
                for chunk in range(chunks):
                    start = chunk * chunksize
                    end = (chunk + 1) * chunksize
                    if (chunk + 1) * chunksize > len(ciphertext):
                        end = len(ciphertext)

                    plaintext += self.prv.decrypt(
                        ciphertext[start:end],
                        padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA1()),
                                     algorithm=hashes.SHA1(),
                                     label=None))
            except:
                RNS.log(
                    "Decryption by " + RNS.prettyhexrep(self.hash) + " failed",
                    RNS.LOG_VERBOSE)

            return plaintext
        else:
            raise KeyError(
                "Decryption failed because identity does not hold a private key"
            )
Exemple #15
0
        def confirmed(sender):
            try:
                display_name = e_name.get_edit_text()
                source_hash = bytes.fromhex(e_id.get_edit_text())
                trust_level = DirectoryEntry.UNTRUSTED
                if r_unknown.state == True:
                    trust_level = DirectoryEntry.UNKNOWN
                elif r_trusted.state == True:
                    trust_level = DirectoryEntry.TRUSTED

                delivery = DirectoryEntry.DIRECT
                if r_propagated.state == True:
                    delivery = DirectoryEntry.PROPAGATED

                entry = DirectoryEntry(source_hash,
                                       display_name,
                                       trust_level,
                                       preferred_delivery=delivery)
                self.app.directory.remember(entry)
                self.update_conversation_list()
                self.dialog_open = False
                self.app.ui.main_display.sub_displays.network_display.directory_change_callback(
                )
            except Exception as e:
                RNS.log(
                    "Could not save directory entry. The contained exception was: "
                    + str(e), RNS.LOG_VERBOSE)
                if not dialog_pile.error_display:
                    dialog_pile.error_display = True
                    options = dialog_pile.options(height_type="pack")
                    dialog_pile.contents.append((urwid.Text(""), options))
                    dialog_pile.contents.append((urwid.Text(
                        ("error_text",
                         "Could not save entry. Check your input."),
                        align="center"), options))
Exemple #16
0
    def send(self):
        """
        Sends the packet.
        
        :returns: A :ref:`RNS.PacketReceipt<api-packetreceipt>` instance if *create_receipt* was set to *True* when the packet was instantiated, if not returns *None*. If the packet could not be sent *False* is returned.
        """
        if not self.sent:
            if self.destination.type == RNS.Destination.LINK:
                if self.destination.status == RNS.Link.CLOSED:
                    raise IOError("Attempt to transmit over a closed link")
                else:
                    self.destination.last_outbound = time.time()
                    self.destination.tx += 1
                    self.destination.txbytes += len(self.data)

            if not self.packed:
                self.pack()

            if RNS.Transport.outbound(self):
                return self.receipt
            else:
                RNS.log("No interfaces could process the outbound packet",
                        RNS.LOG_ERROR)
                self.sent = False
                self.receipt = None
                return False

        else:
            raise IOError("Packet was already sent")
Exemple #17
0
    def received_announce(self, destination_hash, announced_identity,
                          app_data):
        RNS.log("Received an announce from " +
                RNS.prettyhexrep(destination_hash))

        RNS.log("The announce contained the following app data: " +
                app_data.decode("utf-8"))
Exemple #18
0
def menu():
    global server_files, server_link
    # Wait until we have a filelist
    while len(server_files) == 0:
        time.sleep(0.1)
    RNS.log("Ready!")
    time.sleep(0.5)

    global menu_mode
    menu_mode = "main"
    should_quit = False
    while (not should_quit):
        print_menu()

        while not menu_mode == "main":
            # Wait
            time.sleep(0.25)

        user_input = input()
        if user_input == "q" or user_input == "quit" or user_input == "exit":
            should_quit = True
            print("")
        else:
            if user_input in server_files:
                download(user_input)
            else:
                try:
                    if 0 <= int(user_input) < len(server_files):
                        download(server_files[int(user_input)])
                except:
                    pass

    if should_quit:
        server_link.teardown()
Exemple #19
0
    def create_keys(self):
        self.prv = X25519PrivateKey.generate()
        self.prv_bytes = self.prv.private_bytes(
            encoding=serialization.Encoding.Raw,
            format=serialization.PrivateFormat.Raw,
            encryption_algorithm=serialization.NoEncryption())

        self.sig_prv = Ed25519PrivateKey.generate()
        self.sig_prv_bytes = self.sig_prv.private_bytes(
            encoding=serialization.Encoding.Raw,
            format=serialization.PrivateFormat.Raw,
            encryption_algorithm=serialization.NoEncryption())

        self.pub = self.prv.public_key()
        self.pub_bytes = self.pub.public_bytes(
            encoding=serialization.Encoding.Raw,
            format=serialization.PublicFormat.Raw)

        self.sig_pub = self.sig_prv.public_key()
        self.sig_pub_bytes = self.sig_pub.public_bytes(
            encoding=serialization.Encoding.Raw,
            format=serialization.PublicFormat.Raw)

        self.update_hashes()

        RNS.log("Identity keys created for " + RNS.prettyhexrep(self.hash),
                RNS.LOG_VERBOSE)
Exemple #20
0
    def received_announce(destination_hash, announced_identity, app_data):
        app = nomadnet.NomadNetworkApp.get_shared_instance()

        if not destination_hash in app.ignored_list:
            destination_hash_text = RNS.hexrep(destination_hash, delimit=False)
            # Check if the announced destination is in
            # our list of conversations
            if destination_hash_text in [
                    e[0] for e in Conversation.conversation_list(app)
            ]:
                if app.directory.find(destination_hash):
                    if Conversation.created_callback != None:
                        Conversation.created_callback()
                else:
                    if Conversation.created_callback != None:
                        Conversation.created_callback()

            # Add the announce to the directory announce
            # stream logger
            app.directory.lxmf_announce_received(destination_hash, app_data)

        else:
            RNS.log(
                "Ignored announce from " + RNS.prettyhexrep(destination_hash),
                RNS.LOG_DEBUG)
Exemple #21
0
    def __mark_delivered(self, receipt=None):
        RNS.log("Received delivery notification for " + str(self),
                RNS.LOG_DEBUG)
        self.state = LXMessage.DELIVERED

        if self.__delivery_callback != None:
            self.__delivery_callback(self)
Exemple #22
0
    def send(self, content="", title=""):
        if self.send_destination:
            dest = self.send_destination
            source = self.app.lxmf_destination
            desired_method = LXMF.LXMessage.DIRECT
            if self.app.directory.preferred_delivery(
                    dest.hash) == DirectoryEntry.PROPAGATED:
                if self.app.message_router.get_outbound_propagation_node(
                ) != None:
                    desired_method = LXMF.LXMessage.PROPAGATED

            lxm = LXMF.LXMessage(dest,
                                 source,
                                 content,
                                 title=title,
                                 desired_method=desired_method)
            lxm.register_delivery_callback(self.message_notification)
            lxm.register_failed_callback(self.message_notification)

            if self.app.message_router.get_outbound_propagation_node() != None:
                lxm.try_propagation_on_fail = self.app.try_propagation_on_fail

            self.app.message_router.handle_outbound(lxm)

            message_path = Conversation.ingest(lxm, self.app, originator=True)
            self.messages.append(ConversationMessage(message_path))

            return True
        else:
            RNS.log("Destination is not known, cannot create LXMF Message.",
                    RNS.LOG_VERBOSE)
            return False
Exemple #23
0
    def lxmf_delivery(self, lxmf_data, destination_type=None):
        try:
            message = LXMessage.unpack_from_bytes(lxmf_data)

            if RNS.Reticulum.should_allow_unencrypted():
                message.transport_encrypted = False
                message.transport_encryption = LXMessage.ENCRYPTION_DESCRIPTION_UNENCRYPTED
            else:
                if destination_type == RNS.Destination.SINGLE:
                    message.transport_encrypted = True
                    message.transport_encryption = LXMessage.ENCRYPTION_DESCRIPTION_RSA
                elif destination_type == RNS.Destination.GROUP:
                    message.transport_encrypted = True
                    message.transport_encryption = LXMessage.ENCRYPTION_DESCRIPTION_AES
                elif destination_type == RNS.Destination.LINK:
                    message.transport_encrypted = True
                    message.transport_encryption = LXMessage.ENCRYPTION_DESCRIPTION_EC
                else:
                    message.transport_encrypted = False
                    message.transport_encryption = None

            if self.__delivery_callback != None:
                self.__delivery_callback(message)

            return True

        except Exception as e:
            RNS.log("Could not assemble LXMF message from received data",
                    RNS.LOG_NOTICE)
            RNS.log("The contained exception was: " + str(e), RNS.LOG_DEBUG)
            return False
Exemple #24
0
	def updateBitrate(self):
		try:
			self.bitrate = self.r_sf * ( (4.0/self.cr) / (math.pow(2,self.r_sf)/(self.r_bandwidth/1000)) ) * 1000
			self.bitrate_kbps = round(self.bitrate/1000.0, 2)
			RNS.log(str(self)+" On-air bitrate is now "+str(self.bitrate_kbps)+ " kbps", RNS.LOG_DEBUG)
		except:
			self.bitrate = 0
Exemple #25
0
    def assemble(self):
        if not self.status == Resource.FAILED:
            try:
                self.status = Resource.ASSEMBLING
                stream = b"".join(self.parts)

                if self.encrypted:
                    data = self.link.decrypt(stream)
                else:
                    data = stream

                # Strip off random hash
                data = data[Resource.RANDOM_HASH_SIZE:]

                if self.compressed:
                    self.data = bz2.decompress(data)
                else:
                    self.data = data

                calculated_hash = RNS.Identity.fullHash(self.data +
                                                        self.random_hash)

                if calculated_hash == self.hash:
                    self.file = open(self.storagepath, "ab")
                    self.file.write(self.data)
                    self.file.close()
                    self.status = Resource.COMPLETE
                    self.prove()
                else:
                    self.status = Resource.CORRUPT

            except Exception as e:
                RNS.log("Error while assembling received resource.",
                        RNS.LOG_ERROR)
                RNS.log("The contained exception was: " + str(e),
                        RNS.LOG_ERROR)
                self.status = Resource.CORRUPT

            self.link.resource_concluded(self)

            if self.segment_index == self.total_segments:
                if self.callback != None:
                    self.data = open(self.storagepath, "rb")
                    self.callback(self)

                try:
                    self.data.close()
                    os.unlink(self.storagepath)
                except Exception as e:
                    RNS.log(
                        "Error while cleaning up resource files, the contained exception was:",
                        RNS.LOG_ERROR)
                    RNS.log(str(e))
            else:
                RNS.log(
                    "Resource segment " + str(self.segment_index) + " of " +
                    str(self.total_segments) +
                    " received, waiting for next segment to be announced",
                    RNS.LOG_DEBUG)
Exemple #26
0
	def prove(self, destination=None):
		if self.fromPacked and hasattr(self, "destination") and self.destination:
			if self.destination.identity and self.destination.identity.prv:
				self.destination.identity.prove(self, destination)
		elif self.fromPacked and hasattr(self, "link") and self.link:
			self.link.prove_packet(self)
		else:
			RNS.log("Could not prove packet associated with neither a destination nor a link", RNS.LOG_ERROR)
Exemple #27
0
    def link_established(self, link):
        self.status = Browser.LINK_ESTABLISHED

        if self.app.directory.should_identify_on_connect(
                self.destination_hash):
            RNS.log("Link established, identifying to remote system...",
                    RNS.LOG_VERBOSE)
            self.link.identify(self.app.identity)
Exemple #28
0
    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.rtt = None
        self.callbacks = LinkCallbacks()
        self.resource_strategy = Link.ACCEPT_NONE
        self.outgoing_resources = []
        self.incoming_resources = []
        self.last_inbound = 0
        self.last_outbound = 0
        self.tx = 0
        self.rx = 0
        self.txbytes = 0
        self.rxbytes = 0
        self.default_timeout = Link.DEFAULT_TIMEOUT
        self.proof_timeout = self.default_timeout
        self.timeout_factor = Link.TIMEOUT_FACTOR
        self.keepalive = Link.KEEPALIVE
        self.watchdog_lock = False
        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:
            self.initiator = True

        self.prv = ec.generate_private_key(Link.CURVE, default_backend())
        self.pub = self.prv.public_key()
        self.pub_bytes = self.pub.public_bytes(
            encoding=serialization.Encoding.DER,
            format=serialization.PublicFormat.SubjectPublicKeyInfo)

        if peer_pub_bytes == None:
            self.peer_pub = None
            self.peer_pub_bytes = None
        else:
            self.loadPeer(peer_pub_bytes)

        if (self.initiator):
            self.request_data = self.pub_bytes
            self.packet = RNS.Packet(destination,
                                     self.request_data,
                                     packet_type=RNS.Packet.LINKREQUEST)
            self.packet.pack()
            self.setLinkID(self.packet)
            RNS.Transport.registerLink(self)
            self.request_time = time.time()
            self.start_watchdog()
            self.packet.send()
            RNS.log(
                "Link request " + RNS.prettyhexrep(self.link_id) +
                " sent to " + str(self.destination), RNS.LOG_VERBOSE)
Exemple #29
0
def link_established(link):
    # We store a reference to the link
    # instance for later use
    global server_link
    server_link = link

    # Inform the user that the server is
    # connected
    RNS.log("Link established with server, enter some text to send, or \"quit\" to quit")
Exemple #30
0
    def fail_message(self, lxmessage):
        RNS.log(str(lxmessage) + " failed to send", RNS.LOG_DEBUG)

        self.pending_outbound.remove(lxmessage)
        self.failed_outbound.append(lxmessage)

        lxmessage.state = LXMessage.FAILED
        if lxmessage.failed_callback != None:
            lxmessage.failed_callback(lxmessage)