Allow IP addresses via WebSocket API (#1819)

* Allow IP addresses via WebSocket API

* Switch to socket. Add host
This commit is contained in:
Andrew Morgan 2018-12-18 14:36:14 +01:00 committed by ZeroNet
parent fb3c5eaafa
commit ca549cf081
2 changed files with 41 additions and 4 deletions

View file

@ -4,6 +4,7 @@ import os
import mimetypes import mimetypes
import json import json
import cgi import cgi
import socket
import gevent import gevent
@ -48,10 +49,45 @@ class UiRequest(object):
self.user = None self.user = None
self.script_nonce = None # Nonce for script tags in wrapper html self.script_nonce = None # Nonce for script tags in wrapper html
# Test if a string is a valid IP address
def isIp(self, host, strip_port=False):
if strip_port:
# Remove the port from the IP address
host = ":".join(host.split(":")[:-1])
try:
# This function will return an exception on a non-valid IP
# address
socket.inet_aton(host)
return True
except socket.error:
# Try for a IPv6 address
try:
socket.inet_pton(socket.AF_INET6, host)
return True
except socket.error:
if not strip_port:
# Try stripping the port and re-checking
return self.isIp(host, strip_port=True)
return False
def learnHost(self, host):
self.server.allowed_hosts.add(host)
self.server.log.info("Added %s as allowed host" % host)
def isHostAllowed(self, host): def isHostAllowed(self, host):
if host in self.server.allowed_hosts: if host in self.server.allowed_hosts:
return True return True
# Allow any IP address as they are not affected by DNS rebinding
# attacks
if self.isIp(host):
self.learnHost(host)
return True
if self.isProxyRequest(): # Support for chrome extension proxy if self.isProxyRequest(): # Support for chrome extension proxy
if self.server.site_manager.isDomain(host): if self.server.site_manager.isDomain(host):
return True return True
@ -61,8 +97,7 @@ class UiRequest(object):
if self.server.learn_allowed_host: if self.server.learn_allowed_host:
# Learn the first request's host as allowed one # Learn the first request's host as allowed one
self.server.learn_allowed_host = False self.server.learn_allowed_host = False
self.server.allowed_hosts.add(host) self.learnHost(host)
self.server.log.info("Added %s as allowed host" % host)
return True return True
return False return False

View file

@ -62,7 +62,9 @@ class UiServer:
self.allowed_hosts = set(config.ui_host) self.allowed_hosts = set(config.ui_host)
self.learn_allowed_host = False self.learn_allowed_host = False
elif config.ui_ip == "127.0.0.1": elif config.ui_ip == "127.0.0.1":
self.allowed_hosts = set(["zero", "localhost:%s" % config.ui_port, "127.0.0.1:%s" % config.ui_port]) # IP Addresses are inherently allowed as they are immune to DNS
# rebinding attacks.
self.allowed_hosts = set(["zero", "localhost:%s" % config.ui_port])
# "URI producers and normalizers should omit the port component and # "URI producers and normalizers should omit the port component and
# its ':' delimiter if port is empty or if its value would be the # its ':' delimiter if port is empty or if its value would be the
# same as that of the scheme's default." # same as that of the scheme's default."
@ -70,7 +72,7 @@ class UiServer:
# As a result, we need to support portless hosts if port 80 is in # As a result, we need to support portless hosts if port 80 is in
# use. # use.
if config.ui_port == 80: if config.ui_port == 80:
self.allowed_hosts.update(["localhost", "127.0.0.1"]) self.allowed_hosts.update(["localhost"])
self.learn_allowed_host = False self.learn_allowed_host = False
else: else:
self.allowed_hosts = set([]) self.allowed_hosts = set([])