|
Thomas Spura |
5cbe496 |
diff --git a/IPython/frontend/html/notebook/handlers.py b/IPython/frontend/html/notebook/handlers.py
|
|
Thomas Spura |
4893a4d |
index 3542346..077dc97 100644
|
|
Thomas Spura |
5cbe496 |
--- a/IPython/frontend/html/notebook/handlers.py
|
|
Thomas Spura |
5cbe496 |
+++ b/IPython/frontend/html/notebook/handlers.py
|
|
Thomas Spura |
4893a4d |
@@ -16,6 +16,11 @@ Authors:
|
|
Thomas Spura |
4893a4d |
# Imports
|
|
Thomas Spura |
4893a4d |
#-----------------------------------------------------------------------------
|
|
Thomas Spura |
4893a4d |
|
|
Thomas Spura |
4893a4d |
+try:
|
|
Thomas Spura |
4893a4d |
+ from urllib.parse import urlparse # Py 3
|
|
Thomas Spura |
4893a4d |
+except ImportError:
|
|
Thomas Spura |
4893a4d |
+ from urlparse import urlparse # Py 2
|
|
Thomas Spura |
4893a4d |
+
|
|
Thomas Spura |
4893a4d |
import logging
|
|
Thomas Spura |
4893a4d |
import Cookie
|
|
Thomas Spura |
4893a4d |
import time
|
|
Thomas Spura |
4893a4d |
@@ -369,6 +374,30 @@ class KernelActionHandler(AuthenticatedHandler):
|
|
Thomas Spura |
5cbe496 |
|
|
Thomas Spura |
5cbe496 |
class ZMQStreamHandler(websocket.WebSocketHandler):
|
|
Thomas Spura |
5cbe496 |
|
|
Thomas Spura |
5cbe496 |
+ def same_origin(self):
|
|
Thomas Spura |
5cbe496 |
+ """Check to see that origin and host match in the headers."""
|
|
Thomas Spura |
5cbe496 |
+
|
|
Thomas Spura |
5cbe496 |
+ # The difference between version 8 and 13 is that in 8 the
|
|
Thomas Spura |
5cbe496 |
+ # client sends a "Sec-Websocket-Origin" header and in 13 it's
|
|
Thomas Spura |
5cbe496 |
+ # simply "Origin".
|
|
Thomas Spura |
5cbe496 |
+ if self.request.headers.get("Sec-WebSocket-Version") in ("7", "8"):
|
|
Thomas Spura |
5cbe496 |
+ origin_header = self.request.headers.get("Sec-Websocket-Origin")
|
|
Thomas Spura |
5cbe496 |
+ else:
|
|
Thomas Spura |
5cbe496 |
+ origin_header = self.request.headers.get("Origin")
|
|
Thomas Spura |
5cbe496 |
+
|
|
Thomas Spura |
5cbe496 |
+ host = self.request.headers.get("Host")
|
|
Thomas Spura |
5cbe496 |
+
|
|
Thomas Spura |
5cbe496 |
+ # If no header is provided, assume we can't verify origin
|
|
Thomas Spura |
5cbe496 |
+ if(origin_header is None or host is None):
|
|
Thomas Spura |
5cbe496 |
+ return False
|
|
Thomas Spura |
5cbe496 |
+
|
|
Thomas Spura |
5cbe496 |
+ parsed_origin = urlparse(origin_header)
|
|
Thomas Spura |
5cbe496 |
+ origin = parsed_origin.netloc
|
|
Thomas Spura |
5cbe496 |
+
|
|
Thomas Spura |
5cbe496 |
+ # Check to see that origin matches host directly, including ports
|
|
Thomas Spura |
5cbe496 |
+ return origin == host
|
|
Thomas Spura |
5cbe496 |
+
|
|
Thomas Spura |
5cbe496 |
+
|
|
Thomas Spura |
5cbe496 |
def _reserialize_reply(self, msg_list):
|
|
Thomas Spura |
5cbe496 |
"""Reserialize a reply message using JSON.
|
|
Thomas Spura |
5cbe496 |
|
|
Thomas Spura |
4893a4d |
@@ -410,6 +439,11 @@ class ZMQStreamHandler(websocket.WebSocketHandler):
|
|
Thomas Spura |
5cbe496 |
class AuthenticatedZMQStreamHandler(ZMQStreamHandler):
|
|
Thomas Spura |
5cbe496 |
|
|
Thomas Spura |
5cbe496 |
def open(self, kernel_id):
|
|
Thomas Spura |
5cbe496 |
+ # Check to see that origin matches host directly, including ports
|
|
Thomas Spura |
5cbe496 |
+ if not self.same_origin():
|
|
Thomas Spura |
5cbe496 |
+ self.log.warn("Cross Origin WebSocket Attempt.")
|
|
Thomas Spura |
5cbe496 |
+ raise web.HTTPError(404)
|
|
Thomas Spura |
5cbe496 |
+
|
|
Thomas Spura |
5cbe496 |
self.kernel_id = kernel_id.decode('ascii')
|
|
Thomas Spura |
5cbe496 |
try:
|
|
Thomas Spura |
5cbe496 |
cfg = self.application.ipython_app.config
|