aboutsummaryrefslogtreecommitdiffhomepage
path: root/share/tools/web_config/webconfig.py
diff options
context:
space:
mode:
authorGravatar David Adam <zanchey@ucc.gu.uwa.edu.au>2014-08-04 13:34:26 +0800
committerGravatar David Adam <zanchey@ucc.gu.uwa.edu.au>2014-08-04 13:34:26 +0800
commit4ae2753025311e9bcc9818dcc26b9e89f229b291 (patch)
tree85ee782510bd67065eba7ef79801361f8d72021c /share/tools/web_config/webconfig.py
parent8844f0c142ade7d6dfea20fc65432b4f97fb92c9 (diff)
Authenticate connections to web_config service
- Require all requests to use a session path. - Use a redirect file to avoid exposing the '/start' URL on the command line, as it contains the cookie value. Fix for CVE-2014-2914. Closes #1438.
Diffstat (limited to 'share/tools/web_config/webconfig.py')
-rwxr-xr-xshare/tools/web_config/webconfig.py69
1 files changed, 64 insertions, 5 deletions
diff --git a/share/tools/web_config/webconfig.py b/share/tools/web_config/webconfig.py
index c3daef5f..55ab372e 100755
--- a/share/tools/web_config/webconfig.py
+++ b/share/tools/web_config/webconfig.py
@@ -26,7 +26,7 @@ if term:
os.environ['TERM'] = term
import subprocess
-import re, socket, cgi, select, time, glob
+import re, socket, cgi, select, time, glob, random, string
try:
import json
except ImportError:
@@ -693,9 +693,16 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
else: font_size = '18pt'
return font_size
-
def do_GET(self):
p = self.path
+
+ authpath = '/' + authkey
+ if p.startswith(authpath):
+ p = p[len(authpath):]
+ else:
+ return self.send_error(403)
+ self.path = p
+
if p == '/colors/':
output = self.do_get_colors()
elif p == '/functions/':
@@ -727,6 +734,14 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_POST(self):
p = self.path
+
+ authpath = '/' + authkey
+ if p.startswith(authpath):
+ p = p[len(authpath):]
+ else:
+ return self.send_error(403)
+ self.path = p
+
if IS_PY2:
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
else: # Python 3
@@ -788,6 +803,18 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
""" Disable request logging """
pass
+redirect_template_html = """
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="refresh" content="0;URL='%s'" />
+ </head>
+ <body>
+ <p><a href="%s">Start the Fish Web config</a></p>
+ </body>
+</html>
+"""
+
# find fish
fish_bin_dir = os.environ.get('__fish_bin_dir')
fish_bin_path = None
@@ -823,6 +850,9 @@ initial_wd = os.getcwd()
where = os.path.dirname(sys.argv[0])
os.chdir(where)
+# Generate a 16-byte random key as a hexadecimal string
+authkey = hex(random.getrandbits(16*4))[2:]
+
# Try to find a suitable port
PORT = 8000
while PORT <= 9000:
@@ -852,9 +882,36 @@ if len(sys.argv) > 1:
initial_tab = '#' + tab
break
-url = 'http://localhost:%d/%s' % (PORT, initial_tab)
-print("Web config started at '%s'. Hit enter to stop." % url)
-webbrowser.open(url)
+url = 'http://localhost:%d/%s/%s' % (PORT, authkey, initial_tab)
+
+# Create temporary file to hold redirect to real server
+# This prevents exposing the URL containing the authentication key on the command line
+# (see CVE-2014-2914 or https://github.com/fish-shell/fish-shell/issues/1438)
+if 'XDG_CACHE_HOME' in os.environ:
+ dirname = os.path.expanduser(os.path.expandvars('$XDG_CACHE_HOME/fish/'))
+else:
+ dirname = os.path.expanduser('~/.cache/fish/')
+
+os.umask(0o0077)
+try:
+ os.makedirs(dirname, 0o0700)
+except OSError as e:
+ if e.errno == 17:
+ pass
+ else:
+ raise e
+
+randtoken = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
+filename = dirname + 'web_config-%s.html' % randtoken
+
+f = open(filename, 'w')
+f.write(redirect_template_html % (url, url))
+f.close()
+
+# Open temporary file as URL
+fileurl = 'file://' + filename
+print("Web config started at '%s'. Hit enter to stop." % fileurl)
+webbrowser.open(fileurl)
# Select on stdin and httpd
stdin_no = sys.stdin.fileno()
@@ -871,3 +928,5 @@ try:
except KeyboardInterrupt:
print("\nShutting down.")
+# Clean up temporary file
+os.remove(filename)