webssh

Web based ssh client https://github.com/huashengdun/webssh webssh.huashengdun.org/
git clone http://git.hanabi.in/repos/webssh.git
Log | Files | Refs | README | LICENSE

commit 838d453336427f2dff71dc3e0281a3131cc151d9
parent 0f8771f0777edcf2786440ea0b15f1736adcbfe9
Author: Sheng <webmaster0115@gmail.com>
Date:   Mon,  9 Apr 2018 22:08:45 +0800

Redefined AutoAddPolicy class for thread-safety

Diffstat:
Mmain.py | 39++++++++++++++++++++++++---------------
1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/main.py b/main.py @@ -8,7 +8,6 @@ import uuid import weakref import paramiko import tornado.gen -import tornado.ioloop import tornado.web import tornado.websocket from tornado.ioloop import IOLoop @@ -27,7 +26,6 @@ define('port', default=8888, help='listen port', type=int) define('debug', default=False, help='debug mode', type=bool) define('policy', default='warning', help='missing host key policy, reject|autoadd|warning') -define('period', default=10, help='seconds for periodic callback', type=int) BUF_SIZE = 1024 @@ -35,6 +33,28 @@ DELAY = 3 workers = {} +class AutoAddPolicy(paramiko.client.MissingHostKeyPolicy): + + """ + thread-safe AutoAddPolicy + """ + lock = threading.Lock() + + def missing_host_key(self, client, hostname, key): + with self.lock: + keytype = key.get_name() + logging.info( + 'Adding {} host key for {}'.format(keytype, hostname) + ) + client._host_keys.add(hostname, keytype, key) + + with open(client._host_keys_filename, 'a') as f: + f.write('{} {} {}\n'.format( + hostname, keytype, key.get_base64() + )) +paramiko.client.AutoAddPolicy = AutoAddPolicy + + class Worker(object): def __init__(self, loop, ssh, chan, dst_addr): self.loop = loop @@ -209,6 +229,7 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler): ssh = paramiko.SSHClient() ssh._system_host_keys = self.settings['system_host_keys'] ssh._host_keys = self.settings['host_keys'] + ssh._host_keys_filename = self.settings['host_keys_filename'] ssh.set_missing_host_key_policy(self.settings['policy']) args = self.get_args() @@ -314,14 +335,6 @@ def get_host_keys(path): return paramiko.hostkeys.HostKeys() -def save_host_keys(host_keys, filename): - length = len(host_keys) - if length != host_keys._last_len: - logging.info('Updating {}'.format(filename)) - host_keys.save(filename) - host_keys._last_len = length - - def get_policy_class(policy): origin_policy = policy policy = policy.lower() @@ -347,11 +360,6 @@ def get_application_settings(): if policy_class is paramiko.client.AutoAddPolicy: host_keys.save(filename) # for permission test - host_keys._last_len = len(host_keys) - tornado.ioloop.PeriodicCallback( - lambda: save_host_keys(host_keys, filename), - options.period * 1000 # milliseconds - ).start() elif policy_class is paramiko.client.RejectPolicy: if not host_keys and not system_host_keys: raise ValueError('Empty known_hosts with reject policy?') @@ -362,6 +370,7 @@ def get_application_settings(): cookie_secret=uuid.uuid4().hex, xsrf_cookies=True, host_keys=host_keys, + host_keys_filename=filename, system_host_keys=system_host_keys, policy=policy_class(), debug=options.debug