diff --git a/IPython/html/base/zmqhandlers.py b/IPython/html/base/zmqhandlers.py index 6af93f5..d1fb453 100644 --- a/IPython/html/base/zmqhandlers.py +++ b/IPython/html/base/zmqhandlers.py @@ -57,23 +57,33 @@ class ZMQStreamHandler(websocket.WebSocketHandler): host = self.request.headers.get("Host") # If no header is provided, assume we can't verify origin - if(origin is None or host is None): + if origin is None: + self.log.warn("Missing Origin header, rejecting WebSocket connection.") + return False + if host is None: + self.log.warn("Missing Host header, rejecting WebSocket connection.") return False - host_origin = "{0}://{1}".format(self.request.protocol, host) + origin = origin.lower() + origin_host = urlparse(origin).netloc # OK if origin matches host - if origin == host_origin: + if origin_host == host: return True # Check CORS headers if self.allow_origin: - return self.allow_origin == origin + allow = self.allow_origin == origin elif self.allow_origin_pat: - return bool(self.allow_origin_pat.match(origin)) + allow = bool(self.allow_origin_pat.match(origin)) else: # No CORS headers deny the request - return False + allow = False + if not allow: + self.log.warn("Blocking Cross Origin WebSocket Attempt. Origin: %s, Host: %s", + origin, host, + ) + return allow def clear_cookie(self, *args, **kwargs): """meaningless for websockets""" @@ -134,7 +144,6 @@ class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler): # Tornado 4 already does CORS checking if tornado.version_info[0] < 4: if not self.check_origin(self.get_origin()): - self.log.warn("Cross Origin WebSocket Attempt from %s", self.get_origin()) raise web.HTTPError(403) self.session = Session(config=self.config)