diff --git a/butterfly.server.py b/butterfly.server.py index 1716001..6d677c3 100644 --- a/butterfly.server.py +++ b/butterfly.server.py @@ -20,16 +20,20 @@ import tornado.options import tornado.ioloop import tornado.httpserver +import ssl tornado.options.define("secret", default='secret', help="Secret") tornado.options.define("debug", default=False, help="Debug mode") tornado.options.define("host", default='127.0.0.1', help="Server host") tornado.options.define("port", default=57575, type=int, help="Server port") tornado.options.define("shell", help="Shell to execute at login") +tornado.options.define("secure", default=False, \ + help="Choose whether or not to use SSL") +tornado.options.define("reallysecure", default=False, \ + help="Require certificate authentication.") tornado.options.parse_command_line() - import logging for logger in ('tornado.access', 'tornado.application', 'tornado.general', 'butterfly'): @@ -42,11 +46,23 @@ ioloop = tornado.ioloop.IOLoop.instance() from butterfly import application -http_server = tornado.httpserver.HTTPServer(application) + +if tornado.options.options.reallysecure: + tornado.options.options.secure = True + reqs = ssl.CERT_REQUIRED +elif tornado.options.options.secure: + reqs = ssl.CERT_OPTIONAL + +ssl_opts = None +if tornado.options.options.secure: + ssl_opts = dict(certfile="butterfly.crt", keyfile="butterfly.key", \ + cert_reqs=reqs, ca_certs="butterflyca.crt") + +http_server = tornado.httpserver.HTTPServer(application, ssl_options=ssl_opts) http_server.listen( tornado.options.options.port, address=tornado.options.options.host) -url = "http://%s:%d/*" % ( +url = "http%s://%s:%d/*" % ( "s" if tornado.options.options.secure else "", tornado.options.options.host, tornado.options.options.port) # This is for debugging purpose diff --git a/butterfly/routes.py b/butterfly/routes.py index f0296a2..8062fc2 100644 --- a/butterfly/routes.py +++ b/butterfly/routes.py @@ -123,8 +123,9 @@ class TermWebSocket(Route, tornado.websocket.WebSocketHandler): env["TERM"] = "xterm-256color" env["COLORTERM"] = "butterfly" env["HOME"] = self.callee.dir - env["LOCATION"] = "http://%s:%d/" % ( - tornado.options.options.host, tornado.options.options.port) + env["LOCATION"] = "http%s://%s:%d/" % \ + ("s" if tornado.options.options.secure else "", \ + tornado.options.options.host, tornado.options.options.port) env["PATH"] = '%s:%s' % (os.path.abspath(os.path.join( os.path.dirname(__file__), '..', 'bin')), env.get("PATH")) args = [shell] @@ -180,7 +181,8 @@ class TermWebSocket(Route, tornado.websocket.WebSocketHandler): self.fd, self.shell_handler, ioloop.READ | ioloop.ERROR) def open(self, user, path): - if self.request.headers['Origin'] != 'http://%s' % ( + if self.request.headers['Origin'] != 'http%s://%s' % \ + ("s" if tornado.options.options.secure else "", self.request.headers['Host']): self.log.warning( 'Unauthorized connection attempt: from : %s to: %s' % ( @@ -194,12 +196,19 @@ class TermWebSocket(Route, tornado.websocket.WebSocketHandler): self.path = path self.user = user.decode('utf-8') if user else None self.caller = self.callee = None + if tornado.options.options.secure: + cert = self.request.get_ssl_certificate() + if cert != None: + for field in cert['subject']: + if field[0][0] == 'commonName': + self.user = self.callee = field[0][1] + if self.socket.local: self.caller = utils.User(uid=self.socket.uid) else: # We don't know uid is on the other machine pass - + if self.user: try: self.callee = utils.User(name=self.user) diff --git a/butterfly/static/coffees/main.coffee b/butterfly/static/coffees/main.coffee index c3c75ff..e427b12 100644 --- a/butterfly/static/coffees/main.coffee +++ b/butterfly/static/coffees/main.coffee @@ -28,7 +28,11 @@ ctl = (type, args...) -> if type == 'Resize' ws.send 'R' + params -ws_url = 'ws://' + document.location.host + '/ws' + location.pathname +if localtion.protocol == 'https:' + ws_url = 'wss://' +else + ws_url = 'ws://' +ws_url += document.location.host + '/ws' + location.pathname ws = new WebSocket ws_url ws.addEventListener 'open', -> diff --git a/butterfly/static/javascripts/main.js b/butterfly/static/javascripts/main.js index 0e2159b..ef7779e 100644 --- a/butterfly/static/javascripts/main.js +++ b/butterfly/static/javascripts/main.js @@ -2792,7 +2792,13 @@ ctl = function() { } }; -ws_url = 'ws://' + document.location.host + '/ws' + location.pathname; +if(location.protocol == 'https:'){ + ws_url = 'wss://' +} +else{ + ws_url = 'ws://' +} +ws_url += document.location.host + '/ws' + location.pathname; ws = new WebSocket(ws_url); diff --git a/butterfly/utils.py b/butterfly/utils.py index 5034b70..b77b0bc 100644 --- a/butterfly/utils.py +++ b/butterfly/utils.py @@ -31,7 +31,10 @@ class User(object): if uid is not None: self.pw = pwd.getpwuid(uid) else: - self.pw = pwd.getpwnam(name) + try: + self.pw = pwd.getpwnam(name) + except: + self.pw = pwd.getpwnam('daemon') if self.pw is None: raise LookupError('Unknown user')