Add 2 arguments to websockify.WSRequestHandler

This patch adds 2 arguments to websockify.WSRequestHandler for security:

* file_only: returns 404 response if non-file contents are requested.
             Required to disable directory listing.

* no_parent: returns 403 response if contents out of the web root are
             requested. Required to disable directory traversal.
This commit is contained in:
NTT Data OpenStackers 2013-06-24 06:09:01 -07:00
parent b7f255ce0b
commit 888e75a8fb
1 changed files with 16 additions and 3 deletions

View File

@ -92,7 +92,7 @@ Sec-WebSocket-Accept: %s\r
def __init__(self, listen_host='', listen_port=None, source_is_ipv6=False,
verbose=False, cert='', key='', ssl_only=None,
daemon=False, record='', web='',
daemon=False, record='', web='', file_only=False, no_parent=False,
run_once=False, timeout=0, idle_timeout=0):
# settings
@ -110,6 +110,9 @@ Sec-WebSocket-Accept: %s\r
self.ws_connection = False
self.handler_id = 1
self.file_only = file_only
self.no_parent = no_parent
# Make paths settings absolute
self.cert = os.path.abspath(cert)
self.key = self.web = self.record = ''
@ -620,7 +623,8 @@ Sec-WebSocket-Accept: %s\r
self.scheme = "ws"
stype = "Plain non-SSL (ws://)"
wsh = WSRequestHandler(retsock, address, not self.web)
wsh = WSRequestHandler(retsock, address, not self.web,
self.file_only, self.no_parent)
if wsh.last_code == 101:
# Continue on to handle WebSocket upgrade
pass
@ -859,11 +863,16 @@ Sec-WebSocket-Accept: %s\r
# HTTP handler with WebSocket upgrade support
class WSRequestHandler(SimpleHTTPRequestHandler):
def __init__(self, req, addr, only_upgrade=False):
def __init__(self, req, addr, only_upgrade=False, file_only=False,
no_parent=False):
self.only_upgrade = only_upgrade # only allow upgrades
self.webroot = os.path.realpath(".")
self.file_only = file_only
self.no_parent = no_parent
SimpleHTTPRequestHandler.__init__(self, req, addr, object())
def do_GET(self):
abspath = os.path.realpath("." + (self.path.split('?')[0]))
if (self.headers.get('upgrade') and
self.headers.get('upgrade').lower() == 'websocket'):
@ -874,6 +883,10 @@ class WSRequestHandler(SimpleHTTPRequestHandler):
# Normal web request responses are disabled
self.last_code = 405
self.last_message = "405 Method Not Allowed"
elif self.file_only and not os.path.isfile(abspath):
self.send_response(404, "No such file")
elif self.no_parent and not abspath.startswith(self.webroot):
self.send_response(403, "Hidden resources")
else:
SimpleHTTPRequestHandler.do_GET(self)