def get_servers(CFG): """ Given a configuration file, instantiate and return a list of enabled servers. """ servers = [] if (CFG.has_section('telnet') and (not CFG.has_option('telnet', 'enabled') or CFG.getboolean('telnet', 'enabled'))): # start telnet server instance from x84.telnet import TelnetServer servers.append(TelnetServer(config=CFG)) if (CFG.has_section('ssh') and not CFG.has_option('ssh', 'enabled') or CFG.getboolean('ssh', 'enabled')): # start ssh server instance # # may raise an ImportError for systems where pyOpenSSL and etc. could # not be installed (due to any issues with missing python-dev, libffi, # cc, etc.). Allow it to raise naturally, the curious user should # either discover and resolve the root issue, or disable ssh if it # cannot be resolved. from x84.ssh import SshServer servers.append(SshServer(config=CFG)) if (CFG.has_section('rlogin') and (not CFG.has_option('rlogin', 'enabled') or CFG.getboolean('rlogin', 'enabled'))): # start rlogin server instance from x84.rlogin import RLoginServer servers.append(RLoginServer(config=CFG)) return servers
def get_servers(CFG): """ Instantiate and return enabled servers by configuration ``CFG``. """ servers = [] if (CFG.has_section('telnet') and (not CFG.has_option('telnet', 'enabled') or CFG.getboolean('telnet', 'enabled'))): # start telnet server instance from x84.telnet import TelnetServer servers.append(TelnetServer(config=CFG)) if (CFG.has_section('ssh') and not CFG.has_option('ssh', 'enabled') or CFG.getboolean('ssh', 'enabled')): # start ssh server instance # # may raise an ImportError for systems where pyOpenSSL and etc. could # not be installed (due to any issues with missing python-dev, libffi, # cc, etc.). Allow it to raise naturally, the curious user should # either discover and resolve the root issue, or disable ssh if it # cannot be resolved. from x84.ssh import SshServer servers.append(SshServer(config=CFG)) if (CFG.has_section('rlogin') and (not CFG.has_option('rlogin', 'enabled') or CFG.getboolean('rlogin', 'enabled'))): # start rlogin server instance from x84.rlogin import RLoginServer servers.append(RLoginServer(config=CFG)) return servers
def describe_ssh_availability(term, session): from x84.bbs.ini import CFG if session.kind == 'ssh': # what a good citizen! return if not (CFG.has_section('ssh') and not CFG.has_option('ssh', 'enabled') or CFG.getboolean('ssh', 'enabled')): # ssh not enabled return about_key = (u"You may even use an ssh key, which you can configure from " u"your user profile, " if not session.user.get('pubkey') else u'') big_msg = term.bold_blue("Big Brother is Watching You") description = ( u"\r\n\r\n" u" {term.red}You are using {session.kind}, but ssh is available " u"on port {ssh_port} of this server. If you want a secure connection " u"with shorter latency, we recommend instead to use ssh! {about_key}" u"Remember: {big_msg}!\r\n\r\n".format(term=term, session=session, ssh_port=ssh_port, about_key=about_key, big_msg=big_msg)) show_description(term, description, color=None) waitprompt(term)
def describe_ssh_availability(term, session): from x84.bbs.ini import CFG if session.kind == 'ssh': # what a good citizen! return if not (CFG.has_section('ssh') and not CFG.has_option('ssh', 'enabled') or CFG.getboolean('ssh', 'enabled')): # ssh not enabled return about_key = (u"You may even use an ssh key, which you can configure from " u"your user profile, " if not session.user.get('pubkey') else u'') big_msg = term.bold_blue("Big Brother is Watching You") description = ( u"\r\n\r\n" u" {term.red}You are using {session.kind}, but ssh is available " u"on port {ssh_port} of this server. If you want a secure connection " u"with shorter latency, we recommend instead to use ssh! {about_key}" u"Remember: {big_msg}!\r\n\r\n".format( term=term, session=session, ssh_port=ssh_port, about_key=about_key, big_msg=big_msg)) show_description(term, description, color=None) waitprompt(term)
def describe_ssh_availability(term, session): from x84.bbs.ini import CFG if session.kind == 'ssh': # what a good citizen! return if not (CFG.has_section('ssh') and not CFG.has_option('ssh', 'enabled') or CFG.getboolean('ssh', 'enabled')): # ssh not enabled return about_key = (u"You may even use an ssh key, which you can configure from " u"your user profile, " if not session.user.get('pubkey') else u'') big_msg = term.bold_blue("Big Brother is Watching You") description = ( " {term.red}You are using {session.kind}, but ssh is available " "on port {ssh_port} of this server. If you want a secure connection " "with shorter latency, we recommend instead to use ssh! {about_key}" "Remember: {big_msg}!" .format(term=term, session=session, ssh_port=ssh_port, about_key=about_key, big_msg=big_msg) ) echo(u'\r\n\r\n') for txt in term.wrap(description, width=min(80, term.width)): echo(term.move_x(max(0, (term.width // 2) - 40))) echo(term.red(txt.rstrip() + '\r\n')) echo(u'\r\n\r\n') echo(term.center(term.bold_black('Press any key to continue: ')).rstrip()) term.inkey()
def main(): """ x84 main entry point. The system begins and ends here. Command line arguments to engine.py: - ``--config=`` location of alternate configuration file - ``--logger=`` location of alternate logging.ini file """ import x84.bbs.ini # load existing .ini files or create default ones. x84.bbs.ini.init(*parse_args()) from x84.bbs import get_ini from x84.bbs.ini import CFG if sys.maxunicode == 65535: # apple is the only known bastardized variant that does this; # presumably for memory/speed savings (UCS-2 strings are faster # than UCS-4). Python 3 dynamically allocates string types by # their widest content, so such things aren't necessary ... import warnings warnings.warn('This python is built without wide unicode support. ' 'some internationalized languages will not be possible.') # retrieve list of managed servers servers = get_servers(CFG) # begin unmanaged servers if (CFG.has_section('web') and (not CFG.has_option('web', 'enabled') or CFG.getboolean('web', 'enabled'))): # start https server for one or more web modules. from x84 import webserve webserve.main() if get_ini(section='msg', key='network_tags'): # start background timer to poll for new messages # of message networks we may be a member of. from x84 import msgpoll msgpoll.main() try: # begin main event loop _loop(servers) except KeyboardInterrupt: # exit on ^C, killing any client sessions. from x84.terminal import kill_session for server in servers: for idx, thread in enumerate(server.threads[:]): if not thread.stopped: thread.stopped = True server.threads.remove(thread) for key, client in server.clients.items()[:]: kill_session(client, 'server shutdown') del server.clients[key] return 0
def main(): """ x84 main entry point. The system begins and ends here. Command line arguments to engine.py: - ``--config=`` location of alternate configuration file - ``--logger=`` location of alternate logging.ini file """ # load existing .ini files or create default ones. import x84.bbs.ini x84.bbs.ini.init(*cmdline.parse_args()) from x84.bbs import get_ini from x84.bbs.ini import CFG if sys.maxunicode == 65535: # apple is the only known bastardized variant that does this; # presumably for memory/speed savings (UCS-2 strings are faster # than UCS-4). Python 3 dynamically allocates string types by # their widest content, so such things aren't necessary, there. import warnings warnings.warn('This python is built without wide unicode support. ' 'some internationalized languages will not be possible.') # retrieve list of managed servers servers = get_servers(CFG) # begin unmanaged servers if (CFG.has_section('web') and (not CFG.has_option('web', 'enabled') or CFG.getboolean('web', 'enabled'))): # start https server for one or more web modules. from x84 import webserve webserve.main() if get_ini(section='msg', key='network_tags'): # start background timer to poll for new messages # of message networks we may be a member of. from x84 import msgpoll msgpoll.main() try: # begin main event loop _loop(servers) except KeyboardInterrupt: # exit on ^C, killing any client sessions. for server in servers: for thread in server.threads[:]: if not thread.stopped: thread.stopped = True server.threads.remove(thread) for key, client in server.clients.items()[:]: kill_session(client, 'server shutdown') del server.clients[key] return 0
def _loop(servers): """ Main event loop. Never returns. """ # pylint: disable=R0912,R0914,R0915 # Too many local variables (24/15) import logging import select import sys from x84.terminal import get_terminals, kill_session from x84.bbs.ini import CFG from x84.fail2ban import get_fail2ban_function SELECT_POLL = 0.02 # polling time is 20ms # WIN32 has no session_fds (multiprocess queues are not polled using # select), use a persistently empty set; for WIN32, sessions are always # polled for data at every loop. WIN32 = sys.platform.lower().startswith('win32') session_fds = set() log = logging.getLogger('x84.engine') if not len(servers): raise ValueError("No servers configured for event loop! (ssh, telnet)") tap_events = CFG.getboolean('session', 'tap_events') check_ban = get_fail2ban_function() locks = dict() while True: # shutdown, close & delete inactive clients, for server in servers: # bbs sessions that are no longer active on the socket # level -- send them a 'kill signal' for key, client in server.clients.items()[:]: if not client.is_active(): kill_session(client, 'socket shutdown') del server.clients[key] # on-connect negotiations that have completed or failed. # delete their thread instance from further evaluation for thread in [_thread for _thread in server.threads if _thread.stopped][:]: server.threads.remove(thread) server_fds = [server.server_socket.fileno() for server in servers] client_fds = [fd for fd in server.client_fds() for server in servers] check_r = server_fds + client_fds if not WIN32: session_fds = get_session_output_fds(servers) check_r += session_fds # We'd like to use timeout 'None', but the registration of # a new client in terminal.start_process surprises us with new # file descriptors for the session i/o. unless we loop for # additional `session_fds', a connecting client would block. ready_r, _, _ = select.select(check_r, [], [], SELECT_POLL) for fd in ready_r: # see if any new tcp connections were made server = find_server(servers, fd) if server is not None: accept(log, server, check_ban) # receive new data from tcp clients. client_recv(servers, log) terms = get_terminals() # receive new data from session terminals if WIN32 or set(session_fds) & set(ready_r): try: session_recv(locks, terms, log, tap_events) except IOError, err: # if the ipc closes while we poll, warn and continue log.warn(err) # send tcp data to clients client_send(terms, log) # send session data, poll for user-timeout and disconnect them session_send(terms)