Allowing connections only from chrome-extension and self-hosted client

This commit is contained in:
Tomasz Drwięga 2016-06-06 12:01:59 +02:00
parent 9572f6e5fc
commit 302126ebcf
3 changed files with 41 additions and 4 deletions

2
Cargo.lock generated
View File

@ -1448,7 +1448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "ws" name = "ws"
version = "0.4.6" version = "0.4.6"
source = "git+https://github.com/ethcore/ws-rs.git#c0c2a3fc30dc77c4e6d4d90756f8bc3b5cfbc311" source = "git+https://github.com/ethcore/ws-rs.git#5b28de58421b017b01f4565b2c35a46679707789"
dependencies = [ dependencies = [
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -95,7 +95,8 @@ impl Server {
}; };
// Create WebSocket // Create WebSocket
let ws = try!(ws::Builder::new().with_settings(config).build(session::Factory::new(handler))); let origin = format!("{}", addr);
let ws = try!(ws::Builder::new().with_settings(config).build(session::Factory::new(handler, origin)));
let panic_handler = PanicHandler::new_in_arc(); let panic_handler = PanicHandler::new_in_arc();
let ph = panic_handler.clone(); let ph = panic_handler.clone();

View File

@ -21,13 +21,46 @@ use sysui;
use std::sync::Arc; use std::sync::Arc;
use jsonrpc_core::IoHandler; use jsonrpc_core::IoHandler;
fn origin_is_allowed(self_origin: &str, header: Option<&Vec<u8>>) -> bool {
match header {
None => false,
Some(h) => {
let v = String::from_utf8(h.clone()).ok();
match v {
Some(ref origin) if origin.starts_with("chrome-extension://") => true,
Some(ref origin) if origin.starts_with(self_origin) => true,
Some(ref origin) if origin.starts_with(&format!("http://{}", self_origin)) => true,
_ => false
}
}
}
}
fn auth_is_valid(_header: Option<&Vec<u8>>) -> bool {
true
}
pub struct Session { pub struct Session {
out: ws::Sender, out: ws::Sender,
self_origin: String,
handler: Arc<IoHandler>, handler: Arc<IoHandler>,
} }
impl ws::Handler for Session { impl ws::Handler for Session {
fn on_request(&mut self, req: &ws::Request) -> ws::Result<(ws::Response)> { fn on_request(&mut self, req: &ws::Request) -> ws::Result<(ws::Response)> {
let origin = req.header("origin").or_else(|| req.header("Origin"));
let host = req.header("host").or_else(|| req.header("Host"));
// Check request origin and host header.
if !origin_is_allowed(&self.self_origin, origin) && !origin_is_allowed(&self.self_origin, host) {
return Ok(ws::Response::forbidden("You are not allowed to access system ui.".into()));
}
// Check authorization
if !auth_is_valid(req.header("authorization")) {
return Ok(ws::Response::forbidden("You are not authorized.".into()));
}
// Detect if it's a websocket request. // Detect if it's a websocket request.
if req.header("sec-websocket-key").is_some() { if req.header("sec-websocket-key").is_some() {
return ws::Response::from_request(req); return ws::Response::from_request(req);
@ -37,7 +70,7 @@ impl ws::Handler for Session {
sysui::handle(req.resource()) sysui::handle(req.resource())
.map_or_else( .map_or_else(
// return error // return error
|| ws::Response::from_request(req), || Ok(ws::Response::not_found("Page not found".into())),
// or serve the file // or serve the file
|f| { |f| {
let content_len = format!("{}", f.content.as_bytes().len()); let content_len = format!("{}", f.content.as_bytes().len());
@ -67,12 +100,14 @@ impl ws::Handler for Session {
pub struct Factory { pub struct Factory {
handler: Arc<IoHandler>, handler: Arc<IoHandler>,
self_origin: String,
} }
impl Factory { impl Factory {
pub fn new(handler: Arc<IoHandler>) -> Self { pub fn new(handler: Arc<IoHandler>, self_origin: String) -> Self {
Factory { Factory {
handler: handler, handler: handler,
self_origin: self_origin,
} }
} }
} }
@ -83,6 +118,7 @@ impl ws::Factory for Factory {
fn connection_made(&mut self, sender: ws::Sender) -> Self::Handler { fn connection_made(&mut self, sender: ws::Sender) -> Self::Handler {
Session { Session {
out: sender, out: sender,
self_origin: self.self_origin.clone(),
handler: self.handler.clone(), handler: self.handler.clone(),
} }
} }