示例#1
0
    def client_establish_socket(self) -> None:
        """Initialize the transmitter (IPC client)."""
        try:
            target = RECEIVER if self.settings.software_operation == NC else RELAY
            phase(f"Connecting to {target}")
            while True:
                try:
                    if self.settings.software_operation == TX:
                        socket_number = SRC_DD_LISTEN_SOCKET if self.settings.data_diode_sockets else RP_LISTEN_SOCKET
                    else:
                        socket_number = DST_DD_LISTEN_SOCKET if self.settings.data_diode_sockets else DST_LISTEN_SOCKET

                    try:
                        self.tx_socket = multiprocessing.connection.Client((LOCALHOST, socket_number))
                    except ConnectionRefusedError:
                        time.sleep(0.1)
                        continue

                    phase(DONE)
                    break

                except socket.error:
                    time.sleep(0.1)

        except KeyboardInterrupt:
            graceful_exit()
示例#2
0
    def read(self) -> bytes:
        """Read data via socket/serial interface."""
        if self.settings.local_testing_mode:
            while True:
                try:
                    return self.txm_interface.recv()
                except KeyboardInterrupt:
                    pass
                except EOFError:
                    graceful_exit("IPC client disconnected.")
        else:
            while True:
                try:
                    start_time = 0.0
                    read_buffer = bytearray()
                    while True:
                        read = self.txm_interface.read(1000)
                        if read:
                            start_time = time.monotonic()
                            read_buffer.extend(read)
                        else:
                            if read_buffer:
                                delta = time.monotonic() - start_time
                                if delta > self.settings.receive_timeout:
                                    return bytes(read_buffer)
                            else:
                                time.sleep(0.001)

                except KeyboardInterrupt:
                    pass
                except SerialException:
                    self.txm_interface = self.establish_serial()
                    self.read()
示例#3
0
 def establish_serial(self) -> Any:
     """Create a new Serial object."""
     try:
         serial_nh = self.search_serial_interface()
         return serial.Serial(serial_nh,
                              self.settings.session_serial_baudrate,
                              timeout=0)
     except SerialException:
         graceful_exit(
             "SerialException. Ensure $USER is in the dialout group.")
示例#4
0
    def __init__(self, operation: str, local_test: bool) -> None:
        """Create a new MasterKey object."""
        self.file_name = f'{DIR_USER_DATA}{operation}_login_data'
        self.local_test = local_test

        ensure_dir(DIR_USER_DATA)
        try:
            if os.path.isfile(self.file_name):
                self.master_key = self.load_master_key()
            else:
                self.master_key = self.new_master_key()
        except (EOFError, KeyboardInterrupt):
            graceful_exit()
示例#5
0
    def client_establish_socket(self) -> None:
        """Establish IPC client."""
        try:
            phase("Waiting for connection to NH", offset=11)
            while True:
                try:
                    socket_number = TXM_DD_LISTEN_SOCKET if self.settings.data_diode_sockets else NH_LISTEN_SOCKET
                    self.interface = multiprocessing.connection.Client(
                        ('localhost', socket_number))
                    phase("Established", done=True)
                    break
                except socket.error:
                    time.sleep(0.1)

        except KeyboardInterrupt:
            graceful_exit()
示例#6
0
    def server_establish_socket(self) -> None:
        """Initialize the receiver (IPC server).

        The multiprocessing connection during local test does not
        utilize authentication keys* because a MITM-attack against the
        connection requires endpoint compromise, and in such situation,
        MITM attack is not nearly as effective as key/screen logging or
        RAM dump.

            * https://docs.python.org/3/library/multiprocessing.html#authentication-keys

        Similar to the case of standard mode of operation, all sensitive
        data that passes through the socket/serial interface and Relay
        Program is encrypted. A MITM attack between the sockets could of
        course be used to e.g. inject public keys, but like with all key
        exchanges, that would only work if the user neglects fingerprint
        verification.

        Another reason why the authentication key is useless, is the key
        needs to be pre-shared. This means there's two ways to share it:

            1) Hard-code the key to source file from where malware could
               read it.

            2) Force the user to manually copy the PSK from one program
               to another. This would change the workflow that the local
               test configuration tries to simulate.

        To conclude, the local test configuration should never be used
        under a threat model where endpoint security is of importance.
        """
        try:
            socket_number = RP_LISTEN_SOCKET if self.settings.software_operation == NC else DST_LISTEN_SOCKET
            listener = multiprocessing.connection.Listener(
                (LOCALHOST, socket_number))
            self.rx_socket = listener.accept()
        except KeyboardInterrupt:
            graceful_exit()
示例#7
0
 def test_graceful_exit(self):
     with self.assertRaises(SystemExit):
         graceful_exit('test message')
         graceful_exit('test message', clear=False)
         graceful_exit('test message', exit_code=1)
         graceful_exit('test message', exit_code=2)