Example #1
0
class Ability(ns.AbilityBase):
    _info = ns.AbilityInfo(
        name='Call another Ability',
        description='Demonstrate how to call synchronously another ability',
    )
    _option_list = [
        ns.ChoiceOpt('option', ['normal', 'bypass_cache'],
                     default='normal',
                     comment='Define if cache must be bypassed when using '
                     'generators (except "nb")'),
        ns.StrOpt('msg',
                  default='I was called by another ability',
                  comment='Message we want to see in our called ability'),
        ns.NumOpt('nb', default=3, comment='Times to display everything'),
    ]

    _dependencies = [('abl_demo_opt', 'base', 'Demo options')]

    def main(self, **kwargs):
        # Parameters of the called ability can be set in different way
        abl = self.get_dependency('abl_demo_opt',
                                  nb=self.nb,
                                  ip_dst='RandIP6',
                                  msg=self.msg)
        abl.port_dst = 42
        abl.option = self.option
        abl.set_opt("path", "/bin/true")
        abl.start()
        self._view.info(abl.result())
Example #2
0
class Ability(ns.ThreadedAbilityBase):
    _info = ns.AbilityInfo(
        name='Hello from a thread',
        description='Display an hello message and wait to be stopped to exit',
    )

    _option_list = [
        ns.StrOpt('msg',
                  default='Hi there',
                  comment='hello message to display'),
        ns.NumOpt('sleep_time',
                  default=2,
                  comment='Time to wait before displaying the hello message')
    ]

    def main(self):
        time.sleep(self.sleep_time)
        self._view.info('{}!'.format(self.msg).capitalize())
        self._view.warning('Hit Ctrl+c to stop me')
        self._wait()
        self._view.info('Ctrl+c received, exiting…')
        return 'Done'

    def howto(self):
        self._view.delimiter('Hello')
        self._view.info("""
        Display an hello message passed in argument after a defined time.
        It will then hang until receiving a ctrl+c interrupt.
        """)
Example #3
0
class Ability(ns.ThreadedAbilityBase):
    _option_list = [
        ns.StrOpt(
            'cacert_file', '/etc/ssl/certs/ca-certificates.crt',
            'Path of a file containing the list of trusted CAs', optional=True
        ),
        ns.StrOpt('alpn', None, 'Application-Layer Protocol Negotiation value (as a CSV)', optional=True),
        ns.StrOpt('cipher_suites', ':'.join([  # List from ANSSI TLS guide v.1.1 p.51
            'ECDHE-ECDSA-AES256-GCM-SHA384',
            'ECDHE-RSA-AES256-GCM-SHA384',
            'ECDHE-ECDSA-AES128-GCM-SHA256',
            'ECDHE-RSA-AES128-GCM-SHA256',
            'ECDHE-ECDSA-AES256-SHA384',
            'ECDHE-RSA-AES256-SHA384',
            'ECDHE-ECDSA-AES128-SHA256',
            'ECDHE-RSA-AES128-SHA256',
            'ECDHE-ECDSA-CAMELLIA256-SHA384',
            'ECDHE-RSA-CAMELLIA256-SHA384',
            'ECDHE-ECDSA-CAMELLIA128-SHA256',
            'ECDHE-RSA-CAMELLIA128-SHA256',
            'DHE-RSA-AES256-GCM-SHA384',
            'DHE-RSA-AES128-GCM-SHA256',
            'DHE-RSA-AES256-SHA256',
            'DHE-RSA-AES128-SHA256',
            'AES256-GCM-SHA384',
            'AES128-GCM-SHA256',
            'AES256-SHA256',
            'AES128-SHA256',
            'CAMELLIA128-SHA256'
        ]), 'Proposed Ordered Cipher Suite List'),
        ns.BoolOpt('compress', False, 'Should TLS compression be used?'),
        ns.ChoiceOpt(
            'version', ['SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2'], default='TLSv1.2', comment='SSL/TLS protocol version',
        ),
        ns.StrOpt('cert_file', '/etc/ssl/certs/ssl-cert-snakeoil.pem', 'Server Certificate'),
        ns.StrOpt('key_file', '/etc/ssl/private/ssl-cert-snakeoil.key', 'Server Private Key'),
        ns.ChoiceOpt('protocol', ['IPv4', 'IPv6'], comment='IPv4 or IPv6'),
        ns.IpOpt(ns.OptNames.IP_DST, '127.0.0.1', 'Binding IP'),
        ns.PortOpt(ns.OptNames.PORT_DST, 0, 'Binding Port'),
        ns.NumOpt('backlog_size', 10, 'Backlog size provided to listen()'),
        ns.NumOpt('timeout', 30, 'Timeout for sockets'),
        ns.CallbackOpt(ns.OptNames.CALLBACK, comment='Callback returning a service ability to handle a new connection'),
        ns.StrOpt('client_info_name', 'client_info',
            'Name of the service ability option that will contain the information about the client that is at the other end of the TCP connection'
        )
    ]

    _info = ns.AbilityInfo(
        name='TLS Server',
        description='Binds to a port, accept TLS connections and starts new abilities to handle them',
        authors=['Florian Maury',],
        tags=[ns.Tag.TCP_STACK_L4],
        type=ns.AbilityType.COMPONENT
    )

    def __init__(self, *args, **kwargs):
        super(Ability, self).__init__(*args, **kwargs)
        self._stop_evt = threading.Event()

    def stop(self):
        super(Ability, self).stop()
        self._stop_evt.set()

    def _accept_new_connection(self, s):
        # accepting the connection
        clt_sock, clt_info = s.accept()

        # Getting the service ability
        new_abl = self.callback()

        # Giving to the service ability the informations about the client
        new_abl.set_opt(self.client_info_name, '{}:{}'.format(clt_info[0], clt_info[1]))

        # Creating the pipes
        in_pipe_in, in_pipe_out = multiprocessing.Pipe()
        out_pipe_in, out_pipe_out = multiprocessing.Pipe()
        new_abl.add_in_pipe(in_pipe_out)
        new_abl.add_out_pipe(out_pipe_in)

        # Starting the service ability
        new_abl.start()

        return clt_sock, in_pipe_in, out_pipe_out, new_abl

    def _serve(self, server_sock):
        to_read = [server_sock]
        to_write = []
        ready_to_read = []
        ready_to_write = []
        service_abilities = []

        while not self._stop_evt.is_set():
            # Waiting for sockets to be ready
            readable, writable, errored = select.select(to_read, to_write, [], 0.1)
            # Adding the sockets that are ready to the list of the already ready sockets
            ready_to_write += writable
            to_write = [x for x in to_write if x not in ready_to_write]
            ready_to_read += readable
            to_read = [x for x in to_read if x not in ready_to_read]

            if len(ready_to_read) > 0:
                # For each socket that is ready to be read
                for s in ready_to_read:
                    if s is server_sock:
                        # This socket is the server_sock (the one we can run accept upon)
                        new_sock, new_in_pipe, new_out_pipe, new_abl = self._accept_new_connection(s)
                        to_read.append(new_sock)
                        to_read.append(new_out_pipe)
                        to_read.append(s)
                        to_write.append(new_sock)
                        to_write.append(new_in_pipe)
                        service_abilities.append((new_abl, new_sock, new_in_pipe, new_out_pipe))
                        ready_to_read.pop(ready_to_read.index(s))
                    else:
                        # The socket is one of the socket connected to a client

                        # StopIteration should not happen because we know that the element must be present
                        # We also know that there should be only one answer so calling on next is efficient
                        # Finally, we use a generator expression because it is more efficient (only generates up to the
                        # first matching occurrence. A list expression would have iterated over the whole list
                        abl, sock, in_pipe, out_pipe = next(
                            (srv for srv in service_abilities if s is srv[1] or s is srv[3])
                        )
                        if s is sock and in_pipe in ready_to_write:
                            try:
                                in_pipe.send(s.recv(65535))
                                to_read.append(s)
                                to_write.append(in_pipe)
                            except:
                                abl.stop()
                                sock.close()
                                in_pipe.close()
                                out_pipe.close()
                                abl.join()
                            finally:
                                ready_to_write.pop(ready_to_write.index(in_pipe))
                                ready_to_read.pop(ready_to_read.index(sock))

                        elif s is out_pipe and sock in ready_to_write:
                            try:
                                sock.send(out_pipe.recv())
                                to_read.append(out_pipe)
                                to_write.append(sock)
                            except:
                                abl.stop()
                                sock.close()
                                in_pipe.close()
                                out_pipe.close()
                                abl.join()
                            finally:
                                ready_to_write.pop(ready_to_write.index(sock))
                                ready_to_read.pop(ready_to_read.index(out_pipe))

        for abl, sock, in_pipe, out_pipe in service_abilities:
            abl.stop()
            sock.close()
            in_pipe.close()
            out_pipe.close()
            abl.join()

    def main(self):
        # Check Python version
        py_ver = sys.version_info
        if (
            py_ver.major < 2
            or (
                py_ver.major == 2
                and (
                    py_ver.minor < 7
                    or (py_ver.minor >= 7 and py_ver.micro < 10)
                )
            )
        ):
            raise Exception('Your version of Python and Python-ssl are too old. Please upgrade to more "current" versions')

        # Set up SSL/TLS context
        tls_version_table = {
            'SSLv3': ssl.PROTOCOL_SSLv23,
            'TLSv1': ssl.PROTOCOL_TLSv1,
            'TLSv1.1': ssl.PROTOCOL_TLSv1_1,
            'TLSv1.2': ssl.PROTOCOL_TLSv1_2,
        }

        tls_version = tls_version_table[self.version]

        ctx = ssl.SSLContext(tls_version)
        if not isinstance(self.alpn, type(None)):
            ctx.set_alpn_protocols(','.join(self.alpn))
        ctx.set_ciphers(self.cipher_suites)
        if not isinstance(self.cacert_file, type(None)):
            ctx.load_verify_locations(cafile=self.cacert_file)

        ctx.load_cert_chain(self.cert_file, self.key_file)

        if self.protocol == 'IPv4':
            server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        else:
            server_sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)

        server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

        ssl_sock = ctx.wrap_socket(server_sock, server_side=True)

        ssl_sock.bind(('' if isinstance(self.ip_dst, type(None)) else self.ip_dst, self.port_dst))

        ssl_sock.listen(self.backlog_size)
        ssl_sock.settimeout(self.timeout)

        self._serve(ssl_sock)

        try:
            server_sock = ssl_sock.unwrap()
            server_sock.shutdown(socket.SHUT_RDWR)
        except:
            pass
        finally:
            server_sock.close()
Example #4
0
class Ability(ns.ThreadedAbilityBase):
    _option_list = [
        ns.StrOpt('cacert_file', '/etc/ssl/certs/ca-certificates.crt',
                  'Path of a file containing the list of trusted CAs'),
        ns.StrOpt('alpn',
                  None,
                  'Application-Layer Protocol Negotiation value (as a CSV)',
                  optional=True),
        ns.StrOpt(
            'cipher_suites',
            ':'.join([  # List from ANSSI TLS guide v.1.1 p.51
                'ECDHE-ECDSA-AES256-GCM-SHA384', 'ECDHE-RSA-AES256-GCM-SHA384',
                'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES128-GCM-SHA256',
                'ECDHE-ECDSA-AES256-SHA384', 'ECDHE-RSA-AES256-SHA384',
                'ECDHE-ECDSA-AES128-SHA256', 'ECDHE-RSA-AES128-SHA256',
                'ECDHE-ECDSA-CAMELLIA256-SHA384',
                'ECDHE-RSA-CAMELLIA256-SHA384',
                'ECDHE-ECDSA-CAMELLIA128-SHA256',
                'ECDHE-RSA-CAMELLIA128-SHA256', 'DHE-RSA-AES256-GCM-SHA384',
                'DHE-RSA-AES128-GCM-SHA256', 'DHE-RSA-AES256-SHA256',
                'DHE-RSA-AES128-SHA256', 'AES256-GCM-SHA384',
                'AES128-GCM-SHA256', 'AES256-SHA256', 'AES128-SHA256',
                'CAMELLIA128-SHA256'
            ]),
            'Proposed Ordered Cipher Suite List'),
        ns.BoolOpt('compress', False, 'Should TLS compression be used?'),
        ns.ChoiceOpt(
            'version',
            ['SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2'],
            default='TLSv1.2',
            comment='SSL/TLS protocol version',
        ),
        ns.StrOpt('cert_file', None, 'Client Certificate',
                  optional=True),  # To be set only in case of mutual authn
        ns.StrOpt('key_file', None, 'Client Private Key',
                  optional=True),  # To be set only in case of mutual authn
        ns.ChoiceOpt('protocol', ['IPv4', 'IPv6'], comment='IPv4 or IPv6'),
        ns.IpOpt(ns.OptNames.IP_SRC, None, 'Local (Source) IP', optional=True),
        ns.IpOpt(ns.OptNames.IP_DST, '127.0.0.1', 'Remote (Destination) IP'),
        ns.StrOpt('hostname', None, 'Remote Name (dnsName)', optional=True),
        ns.PortOpt(ns.OptNames.PORT_SRC, 0,
                   'Local (Source) Port (0 = Random Port)'),
        ns.PortOpt(ns.OptNames.PORT_DST, 0, 'Remote (Destination) Port'),
        ns.OptionTemplateEntry(lambda x: 0 <= x <= 10,
                               ns.NumOpt('timeout', 5, 'Connect Timeout'))
    ]

    _info = ns.AbilityInfo(
        name='TLS Client',
        description='Connects then sends and receives TLS records',
        authors=['Florian Maury'],
        tags=[ns.Tag.TCP_STACK_L4],
        type=ns.AbilityType.COMPONENT)

    def __init__(self, *args, **kwargs):
        super(Ability, self).__init__(*args, **kwargs)
        self._stop_evt = threading.Event()

    def stop(self):
        super(Ability, self).stop()
        self._stop_evt.set()

    def _serve(self, ssl_sock):
        to_read = [ssl_sock] + self._builtin_in_pipes
        to_write = [ssl_sock] + self._builtin_out_pipes
        ready_to_read = []
        ready_to_write = []

        while not self._stop_evt.is_set():
            # Waiting for sockets to be ready
            readable, writable, errored = select.select(
                to_read, to_write, [], 0.1)
            # Adding the sockets that are ready to the list of the already ready sockets
            ready_to_write += writable
            to_write = [x for x in to_write if x not in ready_to_write]
            ready_to_read += readable
            to_read = [x for x in to_read if x not in ready_to_read]

            if len(ready_to_read) > 0:
                # For each socket that is ready to be read
                for s in ready_to_read:
                    if s is ssl_sock and all([
                            out in ready_to_write
                            for out in self._builtin_out_pipes
                    ]):
                        try:
                            msg = ssl_sock.recv(65535)
                            if len(msg) == 0:
                                raise EOFError
                            self._send(msg)
                            to_read.append(ssl_sock)
                            to_write += self._builtin_out_pipes
                        except:
                            self.stop()
                        finally:
                            ready_to_read.pop(ready_to_read.index(s))
                            for out in self._builtin_out_pipes:
                                ready_to_write.pop(ready_to_write.index(out))
                    elif s in self._builtin_in_pipes and ssl_sock in ready_to_write:
                        try:
                            ssl_sock.send(self._recv())
                            to_read += self._builtin_in_pipes
                            to_write.append(ssl_sock)
                        except:
                            self.stop()
                        finally:
                            for p in self._builtin_in_pipes:
                                ready_to_read.pop(ready_to_read.index(p))
                            ready_to_write.pop(ready_to_write.index(ssl_sock))

    def main(self):
        # Check Python version
        py_ver = sys.version_info
        if (py_ver.major < 2 or (py_ver.major == 2 and
                                 (py_ver.minor < 7 or
                                  (py_ver.minor >= 7 and py_ver.micro < 10)))):
            raise Exception(
                'Your version of Python and Python-ssl are too old. Please upgrade to more "current" versions'
            )

        if self._is_sink() or self._is_source():
            raise Exception(
                'This ability must be connected through pipes to other abilities!'
            )

        # Set up SSL/TLS context
        tls_version_table = {
            'SSLv3': ssl.PROTOCOL_SSLv23,
            'TLSv1': ssl.PROTOCOL_TLSv1,
            'TLSv1.1': ssl.PROTOCOL_TLSv1_1,
            'TLSv1.2': ssl.PROTOCOL_TLSv1_2,
        }

        tls_version = tls_version_table[self.version]

        ctx = ssl.SSLContext(tls_version)
        if not isinstance(self.alpn, type(None)):
            ctx.set_alpn_protocols(','.join(self.alpn))
        ctx.set_ciphers(self.cipher_suites)
        ctx.load_verify_locations(cafile=self.cacert_file)

        if isinstance(self.key_file, type(None)) ^ isinstance(
                self.cert_file, type(None)):
            raise Exception(
                'Both key_file and cert_file must be set or none of them.')
        if not isinstance(self.key_file, type(None)):
            ctx.load_cert_chain(self.cert_file, self.key_file)

        if self.protocol == 'IPv4':
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        else:
            s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)

        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

        if isinstance(self.hostname, type(None)):
            ssl_sock = ctx.wrap_socket(s)
        else:
            ssl_sock = ctx.wrap_socket(s, server_hostname=self.hostname)

        ssl_sock.bind(
            ('' if isinstance(self.ip_src, type(None)) else self.ip_src,
             self.port_src))
        ssl_sock.connect((self.ip_dst, self.port_dst))

        self._serve(ssl_sock)

        try:
            s = ssl_sock.unwrap()
            s.shutdown(socket.SHUT_RDWR)
        except:
            pass
        finally:
            s.close()
Example #5
0
class Ability(ns.ThreadedAbilityBase):
    _option_list = [
        ns.ChoiceOpt('protocol', ['IPv4', 'IPv6'], comment='IPv4 or IPv6'),
        ns.IpOpt(ns.OptNames.IP_SRC, None, 'Local (Source) IP', optional=True),
        ns.IpOpt(ns.OptNames.IP_DST, '127.0.0.1', 'Remote (Destination) IP'),
        ns.PortOpt(ns.OptNames.PORT_SRC, 0,
                   'Local (Source) Port (0 = Random Port)'),
        ns.PortOpt(ns.OptNames.PORT_DST, 0, 'Remote (Destination) Port'),
        ns.OptionTemplateEntry(lambda x: 0 <= x <= 10,
                               ns.NumOpt('timeout', 5, 'Connect Timeout'))
    ]

    _info = ns.AbilityInfo(name='TCP Client',
                           description='Sends and receives segments',
                           authors=[
                               'Florian Maury',
                           ],
                           tags=[ns.Tag.TCP_STACK_L4],
                           type=ns.AbilityType.COMPONENT)

    @staticmethod
    def _forward_outgoing(sock, stop_evt, poller, receiver):
        while not stop_evt.is_set():
            if poller(0.1):
                try:
                    s = receiver()
                except EOFError:
                    break
                sock.send(str(s))

    @staticmethod
    def _forward_incoming(sock, stop_evt, sender, stopper):
        # Timeout is set back to 0.1 second for polling purposes
        sock.settimeout(0.1)
        while not stop_evt.is_set():
            try:
                s = sock.recv(65535)
            except socket.timeout:
                continue
            if len(s) == 0:
                # Socket is closed!
                break
            sender(s)
        stopper()

    def main(self):
        if self._is_sink() or self._is_source():
            raise Exception(
                'This ability must be connected through pipes to other abilities!'
            )

        if self.protocol == 'IPv4':
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        else:
            s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)

        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

        s.bind(('' if isinstance(self.ip_src, type(None)) else self.ip_src,
                self.port_src))
        s.settimeout(self.timeout)
        s.connect((self.ip_dst, self.port_dst))

        stop_evt = threading.Event()

        out_thr = threading.Thread(target=self._forward_outgoing,
                                   args=(s, stop_evt, self._poll, self._recv))
        out_thr.start()

        in_thr = threading.Thread(target=self._forward_incoming,
                                  args=(s, stop_evt, self._send, self.stop))
        in_thr.start()

        self._wait()

        stop_evt.set()

        out_thr.join()
        in_thr.join()
        s.close()
Example #6
0
class Ability(ns.ThreadedAbilityBase):
    _option_list = [
        ns.ChoiceOpt('protocol', ['IPv4', 'IPv6'], comment='IPv4 or IPv6'),
        ns.IpOpt(ns.OptNames.IP_DST, '127.0.0.1', 'Binding IP'),
        ns.PortOpt(ns.OptNames.PORT_DST, 0, 'Binding Port'),
        ns.NumOpt('backlog_size', 10, 'Backlog size provided to listen()'),
        ns.NumOpt('timeout', 30, 'Timeout for sockets'),
        ns.CallbackOpt(
            ns.OptNames.CALLBACK,
            comment='Callback returning an ability to handle a new connection'
        ),
        ns.StrOpt(
            'client_info_name',
            None,
            'Name of the service ability option that will contain the information about the client that is at the other end of the TCP connection',
            optional=True)
    ]

    _info = ns.AbilityInfo(
        name='TCP Server',
        description=
        'Binds to a port, accept connections and starts new abilities to handle them',
        authors=[
            'Florian Maury',
        ],
        tags=[ns.Tag.TCP_STACK_L4],
        type=ns.AbilityType.COMPONENT)

    def __init__(self, *args, **kwargs):
        super(Ability, self).__init__(*args, **kwargs)
        self._stop_evt = threading.Event()

    def stop(self):
        super(Ability, self).stop()
        self._stop_evt.set()

    def _accept_new_connection(self, s):
        # accepting the connection
        clt_sock, clt_info = s.accept()

        # Getting the service ability
        new_abl = self.callback()

        # Giving to the service ability the information about the client
        if not isinstance(self.client_info_name, type(None)):
            new_abl.set_opt(self.client_info_name,
                            '{}:{}'.format(clt_info[0], clt_info[1]))

        # Creating the pipes
        in_pipe_in, in_pipe_out = multiprocessing.Pipe()
        out_pipe_in, out_pipe_out = multiprocessing.Pipe()
        new_abl.add_in_pipe(in_pipe_out)
        new_abl.add_out_pipe(out_pipe_in)

        # Starting the service ability
        new_abl.start()

        return clt_sock, in_pipe_in, out_pipe_out, new_abl

    def _serve(self, server_sock):
        to_read = [server_sock]
        to_write = []
        ready_to_read = []
        ready_to_write = []
        service_abilities = []

        while not self._stop_evt.is_set():
            # Waiting for sockets to be ready
            readable, writable, errored = select.select(
                to_read, to_write, [], 0.1)
            # Adding the sockets that are ready to the list of the already ready sockets
            ready_to_write += writable
            to_write = [x for x in to_write if x not in ready_to_write]
            ready_to_read += readable
            to_read = [x for x in to_read if x not in ready_to_read]

            if len(ready_to_read) > 0:
                # For each socket that is ready to be read
                for s in ready_to_read:
                    if s is server_sock:
                        # This socket is the server_sock (the one we can run accept upon)
                        new_sock, new_in_pipe, new_out_pipe, new_abl = self._accept_new_connection(
                            s)
                        to_read.append(new_sock)
                        to_read.append(new_out_pipe)
                        to_read.append(s)
                        to_write.append(new_sock)
                        to_write.append(new_in_pipe)
                        service_abilities.append(
                            (new_abl, new_sock, new_in_pipe, new_out_pipe))
                        ready_to_read.pop(ready_to_read.index(s))
                    else:
                        # The socket is one of the socket connected to a client

                        # StopIteration should not happen because we know that the element must be present
                        # We also know that there should be only one answer so calling on next is efficient
                        # Finally, we use a generator expression because it is more efficient (only generates up to the
                        # first matching occurrence. A list expression would have iterated over the whole list
                        abl, sock, in_pipe, out_pipe = next(
                            (srv for srv in service_abilities
                             if s is srv[1] or s is srv[3]))
                        if s is sock and in_pipe in ready_to_write:
                            try:
                                in_pipe.send(s.recv(65535))
                                to_read.append(s)
                                to_write.append(in_pipe)
                            except:
                                abl.stop()
                                sock.close()
                                in_pipe.close()
                                out_pipe.close()
                                abl.join()
                            finally:
                                ready_to_write.pop(
                                    ready_to_write.index(in_pipe))
                                ready_to_read.pop(ready_to_read.index(sock))

                        elif s is out_pipe and sock in ready_to_write:
                            try:
                                sock.send(out_pipe.recv())
                                to_read.append(out_pipe)
                                to_write.append(sock)
                            except:
                                abl.stop()
                                sock.close()
                                in_pipe.close()
                                out_pipe.close()
                                abl.join()
                            finally:
                                ready_to_write.pop(ready_to_write.index(sock))
                                ready_to_read.pop(
                                    ready_to_read.index(out_pipe))

        for abl, sock, in_pipe, out_pipe in service_abilities:
            abl.stop()
            sock.close()
            in_pipe.close()
            out_pipe.close()
            abl.join()

    def main(self):
        if self.protocol == 'IPv4':
            server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        else:
            server_sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)

        server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

        server_sock.bind(
            ('' if isinstance(self.ip_dst, type(None)) else self.ip_dst,
             self.port_dst))

        server_sock.listen(self.backlog_size)
        server_sock.settimeout(self.timeout)

        self._serve(server_sock)

        server_sock.close()
Example #7
0
class Ability(ns.AbilityBase):
    _info = ns.AbilityInfo(
        name='Demo options',
        description='Demonstrate all available options',
        tags=[ns.Tag.EXAMPLE],
    )

    _option_list = [
        ns.ChoiceOpt('option', ['normal', 'bypass_cache'],
                     default='normal',
                     comment='Define if cache must be bypassed '
                     'when using generators (except "nb")'),
        ns.NumOpt('nb', default=3, comment='Times to display everything'),
        ns.IpOpt(ns.OptNames.IP_DST,
                 default='127.0.0.1',
                 comment='use as default the standardized dst_ip option name'),
        ns.StrOpt('msg', default='my message', comment='A string message'),
        ns.PortOpt(ns.OptNames.PORT_DST,
                   default=2222,
                   comment='A string message'),
        ns.MacOpt(ns.OptNames.MAC_SRC,
                  default='Mac00',
                  comment='Source MAC address'),
        ns.BoolOpt('a_bool', default=True, comment='A True/False value'),
        ns.PathOpt('path',
                   default='pw.ini',
                   comment='Path to an existing file')  # must_exist=True),
    ]

    def display(self):
        for i in range(self.nb):
            self._view.delimiter('Round {}'.format(i + 1))
            self._view.info('[{}] - {} - {}'.format(self.mac_src, self.ip_dst,
                                                    self.port_dst))
            self._view.progress('{}'.format(self.msg))
            self._view.debug('{}'.format(self.a_bool))
            self._view.warning('{} (abs: {})'.format(
                self.path, os.path.abspath(self.path)))
            self._view.delimiter()
            self._view.info('')

    def display_bypass_cache(self):
        for i in range(self.nb):
            self._view.delimiter('Round {}'.format(i + 1))
            self._view.info('[{}] - {} - {}'.format(
                self.get_opt('mac_src', bypass_cache=True),
                self.get_opt('ip_dst', bypass_cache=True),
                self.get_opt('port_dst', bypass_cache=True),
            ))
            self._view.progress('{}'.format(
                self.get_opt('msg', bypass_cache=True)))
            self._view.debug('{}'.format(
                self.get_opt('a_bool', bypass_cache=True)))
            self._view.warning('{} (abs: {})'.format(
                self.get_opt('path', bypass_cache=True),
                os.path.abspath(self.get_opt('path', bypass_cache=True))))
            self._view.delimiter()
            self._view.info('')

    def main(self):
        if self.nb <= 0:
            self._view.error(
                'The number must be greater than 0 ({} given)'.format(self.nb))
            return
        elif self.nb > 2000:
            self._view.warning('{} rounds is quite a lot! '
                               'Please try with a lower number.'.format(
                                   self.nb))
            return

        if self.option == 'normal':
            self.display()
        elif self.option == 'bypass_cache':
            self.display_bypass_cache()

        self._view.success('Done!')
        return 'Done'

    def howto(self):
        self._view.delimiter('Module option demonstration')
        self._view.info("""
        This ability make use of all the PacketWeaver framework supported
        options.

        Their names are either specified using a label, or a predefined value
        using a OptNames.VAL . The latter solution is preferred as it helps
        getting a clean input interface across different abilities.

        You may play with the different options, modifying their value with
        either:
        - a fixed value
        - a fixed value randomly drawn (e.g RandIP4() for the dst_ip)
        - a random generator (e.g RandIP4)

        The ability will display their value three times so you can see how
        they behave.
        """)