예제 #1
0
 def test_banner(self):
     banner = "Welcome stranger!"
     server = backdoor.BackdoorServer(('127.0.0.1', 0), banner=banner)
     server.start()
     try:
         conn = socket.create_connection(('127.0.0.1', server.server_port))
         response = read_until(conn, '>>> ')
         self.assertEqual(response[:len(banner)], banner)
     finally:
         server.stop()
예제 #2
0
 def test_builtins(self):
     server = backdoor.BackdoorServer(('127.0.0.1', 0))
     server.start()
     try:
         conn = socket.create_connection(('127.0.0.1', server.server_port))
         read_until(conn, '>>> ')
         conn.sendall('locals()["__builtins__"]\r\n')
         response = read_until(conn, '>>> ')
         self.assertTrue(len(response) < 300, msg="locals() unusable: %s..." % response[:100])
     finally:
         server.stop()
예제 #3
0
 def test_quit(self):
     server = backdoor.BackdoorServer(('127.0.0.1', 0))
     server.start()
     try:
         conn = create_connection(('127.0.0.1', server.server_port))
         read_until(conn, '>>> ')
         conn.sendall('quit()\r\n')
         line = conn.makefile('r').read()
         self.assertEqual(line, '')
     finally:
         server.stop()
예제 #4
0
 def test_sys_exit(self):
     server = backdoor.BackdoorServer(('127.0.0.1', 0))
     server.start()
     try:
         conn = socket.create_connection(('127.0.0.1', server.server_port))
         read_until(conn, '>>> ')
         conn.sendall('import sys; sys.exit(0)\r\n')
         line = conn.makefile().read()
         self.assertEqual(line, '')
     finally:
         server.stop()
예제 #5
0
 def test_banner(self):
     banner = "Welcome stranger!"  # native string
     server = backdoor.BackdoorServer(('127.0.0.1', 0), banner=banner)
     server.start()
     try:
         conn = create_connection(('127.0.0.1', server.server_port))
         response = read_until(conn, b'>>> ')
         self.assertEqual(response[:len(banner)], banner, response)
         conn.close()
     finally:
         server.stop()
예제 #6
0
 def test_sys_exit(self):
     server = backdoor.BackdoorServer(('127.0.0.1', 0))
     server.start()
     try:
         conn = create_connection(('127.0.0.1', server.server_port))
         read_until(conn, b'>>> ')
         conn.sendall(b'import sys; sys.exit(0)\r\n')
         line = readline(conn)
         self.assertEqual(line, '')
     finally:
         conn.close()
         server.stop()
예제 #7
0
    def test(self):
        server = backdoor.BackdoorServer(('127.0.0.1', 0))
        server.start()

        def connect():
            conn = socket.create_connection(('127.0.0.1', server.server_port))
            read_until(conn, '>>> ')
            conn.sendall('2+2\r\n')
            line = conn.makefile().readline()
            assert line.strip() == '4', repr(line)

        jobs = [gevent.spawn(connect) for _ in xrange(10)]
        gevent.joinall(jobs)
        server.close()
예제 #8
0
 def test_quit(self):
     server = backdoor.BackdoorServer(('127.0.0.1', 0))
     server.start()
     conn = None
     try:
         conn = create_connection(('127.0.0.1', server.server_port))
         read_until(conn, '>>> ')
         conn.sendall(b'quit()\r\n')
         line = readline(conn)
         self.assertEqual(line, '')
     finally:
         if conn is not None:
             conn.close()
         server.stop()
예제 #9
0
 def test_builtins(self):
     server = backdoor.BackdoorServer(('127.0.0.1', 0))
     server.start()
     conn = None
     try:
         conn = create_connection(('127.0.0.1', server.server_port))
         read_until(conn, b'>>> ')
         conn.sendall(b'locals()["__builtins__"]\r\n')
         response = read_until(conn, '>>> ')
         self.assertTrue(len(response) < 300,
                         msg="locals() unusable: %s..." % response)
     finally:
         if conn is not None:
             conn.close()
         server.stop()
예제 #10
0
    def test(self):
        server = backdoor.BackdoorServer(('127.0.0.1', 0))
        server.start()

        def connect():
            conn = create_connection(('127.0.0.1', server.server_port))
            try:
                read_until(conn, '>>> ')
                conn.sendall(b'2+2\r\n')
                line = readline(conn)
                self.assertEqual(line.strip(), '4', repr(line))
            finally:
                conn.close()

        try:
            jobs = [gevent.spawn(connect) for _ in xrange(10)]
            gevent.joinall(jobs, raise_error=True)
        finally:
            server.close()
예제 #11
0
 def _make_server(self, *args, **kwargs):
     assert self._server is None
     self._server = backdoor.BackdoorServer(('127.0.0.1', 0), *args,
                                            **kwargs)
     self._close_on_teardown(self._server.stop)
     self._server.start()
예제 #12
0
 def _make_server(self, *args, **kwargs):
     assert self._server is None
     self._server = backdoor.BackdoorServer(DEFAULT_BIND_ADDR_TUPLE, *args,
                                            **kwargs)
     self._close_on_teardown(self._server.stop)
     self._server.start()
예제 #13
0
 def _make_and_start_server(self, *args, **kwargs):
     server = backdoor.BackdoorServer(DEFAULT_BIND_ADDR_TUPLE, *args,
                                      **kwargs)
     server.start()
     return server
예제 #14
0
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
    #sock.settimeout(5)
    sock.connect((app.remote_host, app.remote_port))

    return sock


if __name__ == "__main__":
    host, port = get_args()
    app.debug = True
    app.connected_mode = True if host and port else False
    app.sock = None
    app.last_read = None
    try:
        if app.connected_mode:
            app.remote_host = host
            app.remote_port = port
            app.tail = gevent.spawn(tail)
            manhole = backdoor.BackdoorServer(("127.0.0.1", 1337),
                                              locals={"app": app})
            manhole.start()

        server = WSGIServer(("", 5000), app)
        server.serve_forever()
    except KeyboardInterrupt:
        if app.sock:
            app.sock.close()
        manhole.close()
        server.close()
예제 #15
0
def main(command=None):
    """
    Main entrypoint
    """
    auth_manager = None
    repl_server_handle = None  # Used for Command.REPLServer

    if command:
        # Take passed command and append actual cmdline
        cmdline_arguments = sys.argv[1:]
        cmdline_arguments.insert(0, command)
    else:
        cmdline_arguments = None

    args = parse_arguments(cmdline_arguments)
    handle_logging_setup(args)

    LOGGER.debug('Parsed arguments: {0}'.format(args))

    command = args.command
    LOGGER.debug('Chosen command: {0}'.format(command))

    if command == Commands.RESTServer:
        LOGGER.info(
            'Make sure you used the dedicated \'xbox-rest-server\' script'
            ' to start the REST server!')

    elif 'interactive' in args and args.interactive and \
         (args.address or args.liveid):
        LOGGER.error(
            'Flag \'--interactive\' is incompatible with'
            ' providing an IP address (--address) or LiveID (--liveid) explicitly'
        )
        sys.exit(ExitCodes.ArgParsingError)
    elif args.liveid and args.address:
        LOGGER.warning(
            'You passed --address AND --liveid: Will only use that specific'
            'combination!')
    elif command == Commands.PowerOff and args.all and (args.liveid
                                                        or args.address):
        LOGGER.error(
            'Poweroff with --all flag + explicitly provided LiveID / IP address makes no sense'
        )
        sys.exit(ExitCodes.ArgParsingError)
    elif command == Commands.PowerOff and args.interactive and args.all:
        LOGGER.error('Combining args --all and --interactive not supported')
        sys.exit(ExitCodes.ArgParsingError)

    print('Xbox SmartGlass main client started')

    if command == Commands.RESTServer:
        """
        REST Server
        """

        if args.port == 0:
            LOGGER.info('No defaults provided, '
                        'Setting REST server port to {0}'.format(
                            REST_DEFAULT_SERVER_PORT))
            args.port = REST_DEFAULT_SERVER_PORT

        print('Xbox Smartglass REST server started on {0}:{1}'.format(
            args.bind, args.port))

        flask_app.token_file = args.tokens
        server = rest_pywsgi.WSGIServer((args.bind, args.port), flask_app)
        server.serve_forever()
        sys.exit(ExitCodes.OK)
    elif command == Commands.TUI:
        """
        Text user interface (powered by urwid)
        """
        # Removing stream handlers to not pollute TUI
        for h in [
                sh for sh in logging.root.handlers
                if isinstance(sh, logging.StreamHandler)
        ]:
            LOGGER.debug(
                'Removing StreamHandler {0} from root logger'.format(h))
            logging.root.removeHandler(h)

        sys.exit(
            tui.run_tui(args.consoles, args.address, args.liveid, args.tokens,
                        args.refresh))

    elif 'tokens' in args:
        """
        Do Xbox live authentication
        """
        LOGGER.debug(
            'Command {0} supports authenticated connection'.format(command))
        try:
            auth_manager = do_authentication(args.tokens, args.refresh)
        except AuthenticationException:
            LOGGER.exception('Authentication failed!')
            LOGGER.error("Please re-run xbox-authenticate to get a fresh set")
            sys.exit(ExitCodes.AuthenticationError)

    elif command == Commands.PowerOn:
        """
        Powering up console
        """
        if not args.liveid:
            LOGGER.error('No LiveID (--liveid) provided for power on!')
            sys.exit(ExitCodes.ArgParsingError)

        LOGGER.info('Sending poweron packet for LiveId: {0} to {1}'.format(
            args.liveid,
            'IP: ' + args.address if args.address else '<MULTICAST>'))
        Console.power_on(args.liveid, args.address, tries=10)
        sys.exit(0)
    """
    Discovery
    """
    discovered = cli_discover_consoles(args)

    if command == Commands.Discover:
        """
        Simply print discovered consoles
        """
        print("Discovered %d consoles: " % len(discovered))
        for console in discovered:
            print("  %s" % console)
        sys.exit(ExitCodes.OK)

    elif command == Commands.PowerOff and args.all:
        """
        Early call for poweroff --all
        """
        """Powering off all discovered consoles"""
        for c in discovered:
            print('Powering off console {0}'.format(c))
            c.power_off()
        sys.exit(ExitCodes.OK)
    """
    Choosing/filtering a console from the discovered ones
    """
    console = None
    if args.interactive:
        LOGGER.debug('Starting interactive console choice')
        console = choose_console_interactively(discovered)
    elif len(discovered) == 1:
        LOGGER.debug('Choosing sole console, no user interaction required')
        console = discovered[0]
    elif len(discovered) > 1:
        LOGGER.error('More than one console was discovered and no exact'
                     ' connection parameters were provided')

    if not console:
        LOGGER.error('Choosing a console failed!')
        sys.exit(ExitCodes.ConsoleChoice)

    LOGGER.info('Choosen target console: {0}'.format(console))

    LOGGER.debug('Setting console callbacks')
    console.on_device_status += \
        lambda x: LOGGER.info('Device status: {0}'.format(x))
    console.on_connection_state += \
        lambda x: LOGGER.info('Connection state: {0}'.format(x))
    console.on_pairing_state += \
        lambda x: LOGGER.info('Pairing state: {0}'.format(x))
    console.on_console_status += \
        lambda x: LOGGER.info('Console status: {0}'.format(x))
    console.on_timeout += \
        lambda x: LOGGER.error('Timeout occured!') or sys.exit(1)

    userhash = auth_manager.userinfo.userhash
    xtoken = auth_manager.xsts_token

    LOGGER.debug('Authentication info:')
    LOGGER.debug('Userhash: {0}'.format(userhash))
    LOGGER.debug('XToken: {0}'.format(xtoken))

    LOGGER.info('Attempting connection...')
    state = console.connect(userhash, xtoken.jwt)
    if state != ConnectionState.Connected:
        LOGGER.error('Connection failed! Console: {0}'.format(console))
        sys.exit(1)

    # FIXME: Waiting explicitly
    LOGGER.info('Connected to console: {0}'.format(console))
    LOGGER.debug('Waiting a second before proceeding...')
    console.wait(1)

    if command == Commands.PowerOff:
        """
        Power off (single console)
        """
        print('Powering off console {0}'.format(console))
        console.power_off()
        sys.exit(ExitCodes.OK)

    elif command == Commands.REPL or \
            command == Commands.REPLServer:

        banner = 'You are connected to the console @ {0}\n'\
                 .format(console.address)
        banner += 'Type in \'console\' to acccess the object\n'
        banner += 'Type in \'exit()\' to quit the application'

        scope_vars = {'console': console}

        if command == Commands.REPL:
            LOGGER.info('Starting up local REPL console')
            repl_local = InteractiveConsole(locals=scope_vars)
            repl_local.interact(banner)
        else:

            if args.port == 0:
                LOGGER.info('No defaults provided, '
                            'Setting REPL server port to {0}'.format(
                                REPL_DEFAULT_SERVER_PORT))
                args.port = REPL_DEFAULT_SERVER_PORT

            startinfo = 'Starting up REPL server @ {0}:{1}'.format(
                args.bind, args.port)
            print(startinfo)
            LOGGER.info(startinfo)

            repl_server_handle = backdoor.BackdoorServer(listener=(args.bind,
                                                                   args.port),
                                                         banner=banner,
                                                         locals=scope_vars)

    elif command == Commands.FalloutRelay:
        """
        Fallout 4 relay
        """
        print('Starting Fallout 4 relay service...')
        console.add_manager(TitleManager)
        console.title.on_connection_info += fallout4_relay.on_connection_info
        console.start_title_channel(title_id=fallout4_relay.FALLOUT_TITLE_ID)
        print('Fallout 4 relay started')
    elif command == Commands.GamepadInput:
        """
        Gamepad input
        """
        print('Starting gamepad input handler...')
        console.add_manager(manager.InputManager)
        gamepad_input.input_loop(console)
    elif command == Commands.TextInput:
        """
        Text input
        """
        print('Starting text input handler...')
        console.add_manager(manager.TextManager)
        console.text.on_systemtext_configuration += text_input.on_text_config
        console.text.on_systemtext_input += functools.partial(
            text_input.on_text_input, console)
        console.text.on_systemtext_done += text_input.on_text_done

    LOGGER.debug('Installing gevent SIGINT handler')
    signal.signal(signal.SIGINT, lambda *a: console.protocol.stop())

    if repl_server_handle:
        LOGGER.debug('Starting REPL server protocol')

    LOGGER.debug('Starting console.protocol.serve_forever()')
    console.protocol.serve_forever()

    LOGGER.debug('Protocol serving exited')
    if repl_server_handle:
        LOGGER.debug('Stopping REPL server protocol')
        repl_server_handle.stop()