Merge pull request #5992 from paritytech/csp-fix
Add missing CSP for web3.site
This commit is contained in:
commit
02f2c611d4
@ -25,6 +25,7 @@ use util::sha3::sha3;
|
|||||||
use page::{LocalPageEndpoint, PageCache};
|
use page::{LocalPageEndpoint, PageCache};
|
||||||
use handlers::{ContentValidator, ValidatorResponse};
|
use handlers::{ContentValidator, ValidatorResponse};
|
||||||
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest};
|
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest};
|
||||||
|
use Embeddable;
|
||||||
|
|
||||||
type OnDone = Box<Fn(Option<LocalPageEndpoint>) + Send>;
|
type OnDone = Box<Fn(Option<LocalPageEndpoint>) + Send>;
|
||||||
|
|
||||||
@ -116,16 +117,16 @@ pub struct Dapp {
|
|||||||
id: String,
|
id: String,
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
on_done: OnDone,
|
on_done: OnDone,
|
||||||
embeddable_on: Option<(String, u16)>,
|
embeddable_on: Embeddable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dapp {
|
impl Dapp {
|
||||||
pub fn new(id: String, dapps_path: PathBuf, on_done: OnDone, embeddable_on: Option<(String, u16)>) -> Self {
|
pub fn new(id: String, dapps_path: PathBuf, on_done: OnDone, embeddable_on: Embeddable) -> Self {
|
||||||
Dapp {
|
Dapp {
|
||||||
id: id,
|
id,
|
||||||
dapps_path: dapps_path,
|
dapps_path,
|
||||||
on_done: on_done,
|
on_done,
|
||||||
embeddable_on: embeddable_on,
|
embeddable_on,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ use parity_reactor::Remote;
|
|||||||
use hyper;
|
use hyper;
|
||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
|
|
||||||
use {SyncStatus, random_filename};
|
use {Embeddable, SyncStatus, random_filename};
|
||||||
use util::Mutex;
|
use util::Mutex;
|
||||||
use page::LocalPageEndpoint;
|
use page::LocalPageEndpoint;
|
||||||
use handlers::{ContentHandler, ContentFetcherHandler};
|
use handlers::{ContentHandler, ContentFetcherHandler};
|
||||||
@ -52,7 +52,7 @@ pub struct ContentFetcher<F: Fetch = FetchClient, R: URLHint + 'static = URLHint
|
|||||||
resolver: R,
|
resolver: R,
|
||||||
cache: Arc<Mutex<ContentCache>>,
|
cache: Arc<Mutex<ContentCache>>,
|
||||||
sync: Arc<SyncStatus>,
|
sync: Arc<SyncStatus>,
|
||||||
embeddable_on: Option<(String, u16)>,
|
embeddable_on: Embeddable,
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
only_content: bool,
|
only_content: bool,
|
||||||
@ -93,22 +93,22 @@ impl<R: URLHint + 'static, F: Fetch> ContentFetcher<F, R> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn embeddable_on(mut self, embeddable_on: Option<(String, u16)>) -> Self {
|
pub fn embeddable_on(mut self, embeddable_on: Embeddable) -> Self {
|
||||||
self.embeddable_on = embeddable_on;
|
self.embeddable_on = embeddable_on;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn still_syncing(address: Option<(String, u16)>) -> Box<Handler> {
|
fn still_syncing(embeddable: Embeddable) -> Box<Handler> {
|
||||||
Box::new(ContentHandler::error(
|
Box::new(ContentHandler::error(
|
||||||
StatusCode::ServiceUnavailable,
|
StatusCode::ServiceUnavailable,
|
||||||
"Sync In Progress",
|
"Sync In Progress",
|
||||||
"Your node is still syncing. We cannot resolve any content before it's fully synced.",
|
"Your node is still syncing. We cannot resolve any content before it's fully synced.",
|
||||||
Some("<a href=\"javascript:window.location.reload()\">Refresh</a>"),
|
Some("<a href=\"javascript:window.location.reload()\">Refresh</a>"),
|
||||||
address,
|
embeddable,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dapps_disabled(address: Option<(String, u16)>) -> Box<Handler> {
|
fn dapps_disabled(address: Embeddable) -> Box<Handler> {
|
||||||
Box::new(ContentHandler::error(
|
Box::new(ContentHandler::error(
|
||||||
StatusCode::ServiceUnavailable,
|
StatusCode::ServiceUnavailable,
|
||||||
"Network Dapps Not Available",
|
"Network Dapps Not Available",
|
||||||
|
@ -22,6 +22,7 @@ use std::path::{Path, PathBuf};
|
|||||||
use page::{LocalPageEndpoint, PageCache};
|
use page::{LocalPageEndpoint, PageCache};
|
||||||
use endpoint::{Endpoint, EndpointInfo};
|
use endpoint::{Endpoint, EndpointInfo};
|
||||||
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest};
|
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest};
|
||||||
|
use Embeddable;
|
||||||
|
|
||||||
struct LocalDapp {
|
struct LocalDapp {
|
||||||
id: String,
|
id: String,
|
||||||
@ -60,14 +61,14 @@ fn read_manifest(name: &str, mut path: PathBuf) -> EndpointInfo {
|
|||||||
/// Returns Dapp Id and Local Dapp Endpoint for given filesystem path.
|
/// Returns Dapp Id and Local Dapp Endpoint for given filesystem path.
|
||||||
/// Parses the path to extract last component (for name).
|
/// Parses the path to extract last component (for name).
|
||||||
/// `None` is returned when path is invalid or non-existent.
|
/// `None` is returned when path is invalid or non-existent.
|
||||||
pub fn local_endpoint<P: AsRef<Path>>(path: P, signer_address: Option<(String, u16)>) -> Option<(String, Box<LocalPageEndpoint>)> {
|
pub fn local_endpoint<P: AsRef<Path>>(path: P, embeddable: Embeddable) -> Option<(String, Box<LocalPageEndpoint>)> {
|
||||||
let path = path.as_ref().to_owned();
|
let path = path.as_ref().to_owned();
|
||||||
path.canonicalize().ok().and_then(|path| {
|
path.canonicalize().ok().and_then(|path| {
|
||||||
let name = path.file_name().and_then(|name| name.to_str());
|
let name = path.file_name().and_then(|name| name.to_str());
|
||||||
name.map(|name| {
|
name.map(|name| {
|
||||||
let dapp = local_dapp(name.into(), path.clone());
|
let dapp = local_dapp(name.into(), path.clone());
|
||||||
(dapp.id, Box::new(LocalPageEndpoint::new(
|
(dapp.id, Box::new(LocalPageEndpoint::new(
|
||||||
dapp.path, dapp.info, PageCache::Disabled, signer_address.clone())
|
dapp.path, dapp.info, PageCache::Disabled, embeddable.clone())
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -86,12 +87,12 @@ fn local_dapp(name: String, path: PathBuf) -> LocalDapp {
|
|||||||
|
|
||||||
/// Returns endpoints for Local Dapps found for given filesystem path.
|
/// Returns endpoints for Local Dapps found for given filesystem path.
|
||||||
/// Scans the directory and collects `LocalPageEndpoints`.
|
/// Scans the directory and collects `LocalPageEndpoints`.
|
||||||
pub fn local_endpoints<P: AsRef<Path>>(dapps_path: P, signer_address: Option<(String, u16)>) -> BTreeMap<String, Box<Endpoint>> {
|
pub fn local_endpoints<P: AsRef<Path>>(dapps_path: P, embeddable: Embeddable) -> BTreeMap<String, Box<Endpoint>> {
|
||||||
let mut pages = BTreeMap::<String, Box<Endpoint>>::new();
|
let mut pages = BTreeMap::<String, Box<Endpoint>>::new();
|
||||||
for dapp in local_dapps(dapps_path.as_ref()) {
|
for dapp in local_dapps(dapps_path.as_ref()) {
|
||||||
pages.insert(
|
pages.insert(
|
||||||
dapp.id,
|
dapp.id,
|
||||||
Box::new(LocalPageEndpoint::new(dapp.path, dapp.info, PageCache::Disabled, signer_address.clone()))
|
Box::new(LocalPageEndpoint::new(dapp.path, dapp.info, PageCache::Disabled, embeddable.clone()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
pages
|
pages
|
||||||
|
@ -26,7 +26,7 @@ use fetch::Fetch;
|
|||||||
use parity_dapps::WebApp;
|
use parity_dapps::WebApp;
|
||||||
use parity_reactor::Remote;
|
use parity_reactor::Remote;
|
||||||
use parity_ui;
|
use parity_ui;
|
||||||
use {WebProxyTokens};
|
use {WebProxyTokens, ParentFrameSettings};
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod cache;
|
mod cache;
|
||||||
@ -52,23 +52,23 @@ pub fn ui() -> Box<Endpoint> {
|
|||||||
Box::new(PageEndpoint::with_fallback_to_index(parity_ui::App::default()))
|
Box::new(PageEndpoint::with_fallback_to_index(parity_ui::App::default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ui_redirection(ui_address: Option<(String, u16)>) -> Box<Endpoint> {
|
pub fn ui_redirection(embeddable: Option<ParentFrameSettings>) -> Box<Endpoint> {
|
||||||
Box::new(ui::Redirection::new(ui_address))
|
Box::new(ui::Redirection::new(embeddable))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn all_endpoints<F: Fetch>(
|
pub fn all_endpoints<F: Fetch>(
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
extra_dapps: Vec<PathBuf>,
|
extra_dapps: Vec<PathBuf>,
|
||||||
dapps_domain: String,
|
dapps_domain: &str,
|
||||||
ui_address: Option<(String, u16)>,
|
embeddable: Option<ParentFrameSettings>,
|
||||||
web_proxy_tokens: Arc<WebProxyTokens>,
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
) -> Endpoints {
|
) -> Endpoints {
|
||||||
// fetch fs dapps at first to avoid overwriting builtins
|
// fetch fs dapps at first to avoid overwriting builtins
|
||||||
let mut pages = fs::local_endpoints(dapps_path, ui_address.clone());
|
let mut pages = fs::local_endpoints(dapps_path, embeddable.clone());
|
||||||
for path in extra_dapps {
|
for path in extra_dapps {
|
||||||
if let Some((id, endpoint)) = fs::local_endpoint(path.clone(), ui_address.clone()) {
|
if let Some((id, endpoint)) = fs::local_endpoint(path.clone(), embeddable.clone()) {
|
||||||
pages.insert(id, endpoint);
|
pages.insert(id, endpoint);
|
||||||
} else {
|
} else {
|
||||||
warn!(target: "dapps", "Ignoring invalid dapp at {}", path.display());
|
warn!(target: "dapps", "Ignoring invalid dapp at {}", path.display());
|
||||||
@ -76,9 +76,9 @@ pub fn all_endpoints<F: Fetch>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE [ToDr] Dapps will be currently embeded on 8180
|
// NOTE [ToDr] Dapps will be currently embeded on 8180
|
||||||
insert::<parity_ui::App>(&mut pages, "ui", Embeddable::Yes(ui_address.clone()));
|
insert::<parity_ui::App>(&mut pages, "ui", Embeddable::Yes(embeddable.clone()));
|
||||||
pages.insert("proxy".into(), ProxyPac::boxed(ui_address.clone(), dapps_domain));
|
pages.insert("proxy".into(), ProxyPac::boxed(embeddable.clone(), dapps_domain.to_owned()));
|
||||||
pages.insert(WEB_PATH.into(), Web::boxed(ui_address.clone(), web_proxy_tokens.clone(), remote.clone(), fetch.clone()));
|
pages.insert(WEB_PATH.into(), Web::boxed(embeddable.clone(), web_proxy_tokens.clone(), remote.clone(), fetch.clone()));
|
||||||
|
|
||||||
Arc::new(pages)
|
Arc::new(pages)
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ fn insert<T : WebApp + Default + 'static>(pages: &mut BTreeMap<String, Box<Endpo
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum Embeddable {
|
enum Embeddable {
|
||||||
Yes(Option<(String, u16)>),
|
Yes(Option<ParentFrameSettings>),
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
@ -19,28 +19,28 @@
|
|||||||
use hyper::{Control, StatusCode};
|
use hyper::{Control, StatusCode};
|
||||||
|
|
||||||
use endpoint::{Endpoint, Handler, EndpointPath};
|
use endpoint::{Endpoint, Handler, EndpointPath};
|
||||||
use {address, handlers};
|
use {handlers, Embeddable};
|
||||||
|
|
||||||
/// Redirection to UI server.
|
/// Redirection to UI server.
|
||||||
pub struct Redirection {
|
pub struct Redirection {
|
||||||
signer_address: Option<(String, u16)>,
|
embeddable_on: Embeddable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Redirection {
|
impl Redirection {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
signer_address: Option<(String, u16)>,
|
embeddable_on: Embeddable,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Redirection {
|
Redirection {
|
||||||
signer_address: signer_address,
|
embeddable_on,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Endpoint for Redirection {
|
impl Endpoint for Redirection {
|
||||||
fn to_async_handler(&self, _path: EndpointPath, _control: Control) -> Box<Handler> {
|
fn to_async_handler(&self, _path: EndpointPath, _control: Control) -> Box<Handler> {
|
||||||
if let Some(ref signer_address) = self.signer_address {
|
if let Some(ref frame) = self.embeddable_on {
|
||||||
trace!(target: "dapps", "Redirecting to signer interface.");
|
trace!(target: "dapps", "Redirecting to signer interface.");
|
||||||
handlers::Redirection::boxed(&format!("http://{}", address(signer_address)))
|
handlers::Redirection::boxed(&format!("http://{}:{}", &frame.host, frame.port))
|
||||||
} else {
|
} else {
|
||||||
trace!(target: "dapps", "Signer disabled, returning 404.");
|
trace!(target: "dapps", "Signer disabled, returning 404.");
|
||||||
Box::new(handlers::ContentHandler::error(
|
Box::new(handlers::ContentHandler::error(
|
||||||
@ -48,7 +48,7 @@ impl Endpoint for Redirection {
|
|||||||
"404 Not Found",
|
"404 Not Found",
|
||||||
"Your homepage is not available when Trusted Signer is disabled.",
|
"Your homepage is not available when Trusted Signer is disabled.",
|
||||||
Some("You can still access dapps by writing a correct address, though. Re-enable Signer to get your homepage back."),
|
Some("You can still access dapps by writing a correct address, though. Re-enable Signer to get your homepage back."),
|
||||||
self.signer_address.clone(),
|
None,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ use hyper::status::StatusCode;
|
|||||||
use util::version;
|
use util::version;
|
||||||
|
|
||||||
use handlers::add_security_headers;
|
use handlers::add_security_headers;
|
||||||
|
use Embeddable;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ContentHandler {
|
pub struct ContentHandler {
|
||||||
@ -31,7 +32,7 @@ pub struct ContentHandler {
|
|||||||
content: String,
|
content: String,
|
||||||
mimetype: Mime,
|
mimetype: Mime,
|
||||||
write_pos: usize,
|
write_pos: usize,
|
||||||
safe_to_embed_on: Option<(String, u16)>,
|
safe_to_embed_on: Embeddable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContentHandler {
|
impl ContentHandler {
|
||||||
@ -39,11 +40,17 @@ impl ContentHandler {
|
|||||||
Self::new(StatusCode::Ok, content, mimetype)
|
Self::new(StatusCode::Ok, content, mimetype)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn html(code: StatusCode, content: String, embeddable_on: Option<(String, u16)>) -> Self {
|
pub fn html(code: StatusCode, content: String, embeddable_on: Embeddable) -> Self {
|
||||||
Self::new_embeddable(code, content, mime!(Text/Html), embeddable_on)
|
Self::new_embeddable(code, content, mime!(Text/Html), embeddable_on)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(code: StatusCode, title: &str, message: &str, details: Option<&str>, embeddable_on: Option<(String, u16)>) -> Self {
|
pub fn error(
|
||||||
|
code: StatusCode,
|
||||||
|
title: &str,
|
||||||
|
message: &str,
|
||||||
|
details: Option<&str>,
|
||||||
|
embeddable_on: Embeddable,
|
||||||
|
) -> Self {
|
||||||
Self::html(code, format!(
|
Self::html(code, format!(
|
||||||
include_str!("../error_tpl.html"),
|
include_str!("../error_tpl.html"),
|
||||||
title=title,
|
title=title,
|
||||||
@ -57,13 +64,18 @@ impl ContentHandler {
|
|||||||
Self::new_embeddable(code, content, mimetype, None)
|
Self::new_embeddable(code, content, mimetype, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_embeddable(code: StatusCode, content: String, mimetype: Mime, embeddable_on: Option<(String, u16)>) -> Self {
|
pub fn new_embeddable(
|
||||||
|
code: StatusCode,
|
||||||
|
content: String,
|
||||||
|
mimetype: Mime,
|
||||||
|
safe_to_embed_on: Embeddable,
|
||||||
|
) -> Self {
|
||||||
ContentHandler {
|
ContentHandler {
|
||||||
code: code,
|
code,
|
||||||
content: content,
|
content,
|
||||||
mimetype: mimetype,
|
mimetype,
|
||||||
write_pos: 0,
|
write_pos: 0,
|
||||||
safe_to_embed_on: embeddable_on,
|
safe_to_embed_on,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,7 +92,7 @@ impl server::Handler<HttpStream> for ContentHandler {
|
|||||||
fn on_response(&mut self, res: &mut server::Response) -> Next {
|
fn on_response(&mut self, res: &mut server::Response) -> Next {
|
||||||
res.set_status(self.code);
|
res.set_status(self.code);
|
||||||
res.headers_mut().set(header::ContentType(self.mimetype.clone()));
|
res.headers_mut().set(header::ContentType(self.mimetype.clone()));
|
||||||
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.clone());
|
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.take());
|
||||||
Next::write()
|
Next::write()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ use hyper::status::StatusCode;
|
|||||||
use endpoint::EndpointPath;
|
use endpoint::EndpointPath;
|
||||||
use handlers::{ContentHandler, StreamingHandler};
|
use handlers::{ContentHandler, StreamingHandler};
|
||||||
use page::{LocalPageEndpoint, PageHandlerWaiting};
|
use page::{LocalPageEndpoint, PageHandlerWaiting};
|
||||||
|
use {Embeddable};
|
||||||
|
|
||||||
const FETCH_TIMEOUT: u64 = 300;
|
const FETCH_TIMEOUT: u64 = 300;
|
||||||
|
|
||||||
@ -179,7 +180,7 @@ impl server::Handler<HttpStream> for WaitingHandler {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Errors {
|
struct Errors {
|
||||||
embeddable_on: Option<(String, u16)>,
|
embeddable_on: Embeddable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Errors {
|
impl Errors {
|
||||||
@ -241,20 +242,20 @@ impl<H: ContentValidator, F: Fetch> ContentFetcherHandler<H, F> {
|
|||||||
path: EndpointPath,
|
path: EndpointPath,
|
||||||
control: Control,
|
control: Control,
|
||||||
installer: H,
|
installer: H,
|
||||||
embeddable_on: Option<(String, u16)>,
|
embeddable_on: Embeddable,
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ContentFetcherHandler {
|
ContentFetcherHandler {
|
||||||
fetch_control: FetchControl::default(),
|
fetch_control: FetchControl::default(),
|
||||||
control: control,
|
control,
|
||||||
remote: remote,
|
remote,
|
||||||
fetch: fetch,
|
fetch,
|
||||||
status: FetchState::NotStarted(url),
|
status: FetchState::NotStarted(url),
|
||||||
installer: Some(installer),
|
installer: Some(installer),
|
||||||
path: path,
|
path,
|
||||||
errors: Errors {
|
errors: Errors {
|
||||||
embeddable_on: embeddable_on,
|
embeddable_on,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,22 +30,20 @@ pub use self::fetch::{ContentFetcherHandler, ContentValidator, FetchControl, Val
|
|||||||
pub use self::redirect::Redirection;
|
pub use self::redirect::Redirection;
|
||||||
pub use self::streaming::StreamingHandler;
|
pub use self::streaming::StreamingHandler;
|
||||||
|
|
||||||
|
use std::iter;
|
||||||
|
use util::Itertools;
|
||||||
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use hyper::{server, header, net, uri};
|
use hyper::{server, header, net, uri};
|
||||||
use address;
|
use {apps, address, Embeddable};
|
||||||
|
|
||||||
/// Adds security-related headers to the Response.
|
/// Adds security-related headers to the Response.
|
||||||
pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Option<(String, u16)>) {
|
pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embeddable) {
|
||||||
headers.set_raw("X-XSS-Protection", vec![b"1; mode=block".to_vec()]);
|
headers.set_raw("X-XSS-Protection", vec![b"1; mode=block".to_vec()]);
|
||||||
headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]);
|
headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]);
|
||||||
|
|
||||||
// Embedding header:
|
// Embedding header:
|
||||||
if let Some(ref embeddable_on) = embeddable_on {
|
if let None = embeddable_on {
|
||||||
headers.set_raw("X-Frame-Options", vec![
|
|
||||||
format!("ALLOW-FROM http://{}", address(embeddable_on)).into_bytes()
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
// TODO [ToDr] Should we be more strict here (DENY?)?
|
|
||||||
headers.set_raw("X-Frame-Options", vec![b"SAMEORIGIN".to_vec()]);
|
headers.set_raw("X-Frame-Options", vec![b"SAMEORIGIN".to_vec()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +60,7 @@ pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Option
|
|||||||
b"child-src 'self' http: https:;".to_vec(),
|
b"child-src 'self' http: https:;".to_vec(),
|
||||||
// We allow data: blob: and HTTP(s) images.
|
// We allow data: blob: and HTTP(s) images.
|
||||||
// We could get rid of wildcarding HTTP and only allow RPC server URL.
|
// We could get rid of wildcarding HTTP and only allow RPC server URL.
|
||||||
// (http require for local dapps icons)
|
// (http required for local dapps icons)
|
||||||
b"img-src 'self' 'unsafe-inline' data: blob: http: https:;".to_vec(),
|
b"img-src 'self' 'unsafe-inline' data: blob: http: https:;".to_vec(),
|
||||||
// Allow style from data: blob: and HTTPS.
|
// Allow style from data: blob: and HTTPS.
|
||||||
b"style-src 'self' 'unsafe-inline' data: blob: https:;".to_vec(),
|
b"style-src 'self' 'unsafe-inline' data: blob: https:;".to_vec(),
|
||||||
@ -80,10 +78,27 @@ pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Option
|
|||||||
b"block-all-mixed-content;".to_vec(),
|
b"block-all-mixed-content;".to_vec(),
|
||||||
// Specify if the site can be embedded.
|
// Specify if the site can be embedded.
|
||||||
match embeddable_on {
|
match embeddable_on {
|
||||||
Some((ref host, ref port)) if host == "127.0.0.1" => {
|
Some(ref embed) => {
|
||||||
format!("frame-ancestors {} {};", address(&(host.to_owned(), *port)), address(&("localhost".to_owned(), *port)))
|
let std = address(&embed.host, embed.port);
|
||||||
|
let proxy = format!("{}.{}", apps::HOME_PAGE, embed.dapps_domain);
|
||||||
|
let domain = format!("*.{}:{}", embed.dapps_domain, embed.port);
|
||||||
|
|
||||||
|
let mut ancestors = vec![std, domain, proxy]
|
||||||
|
.into_iter()
|
||||||
|
.chain(embed.extra_embed_on
|
||||||
|
.iter()
|
||||||
|
.map(|&(ref host, port)| format!("{}:{}", host, port))
|
||||||
|
);
|
||||||
|
|
||||||
|
let ancestors = if embed.host == "127.0.0.1" {
|
||||||
|
let localhost = address("localhost", embed.port);
|
||||||
|
ancestors.chain(iter::once(localhost)).join(" ")
|
||||||
|
} else {
|
||||||
|
ancestors.join(" ")
|
||||||
|
};
|
||||||
|
|
||||||
|
format!("frame-ancestors {};", ancestors)
|
||||||
},
|
},
|
||||||
Some(ref embed) => format!("frame-ancestors {};", address(embed)),
|
|
||||||
None => format!("frame-ancestors 'self';"),
|
None => format!("frame-ancestors 'self';"),
|
||||||
}.into_bytes(),
|
}.into_bytes(),
|
||||||
]);
|
]);
|
||||||
|
@ -24,6 +24,7 @@ use hyper::mime::Mime;
|
|||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
|
|
||||||
use handlers::add_security_headers;
|
use handlers::add_security_headers;
|
||||||
|
use Embeddable;
|
||||||
|
|
||||||
const BUFFER_SIZE: usize = 1024;
|
const BUFFER_SIZE: usize = 1024;
|
||||||
|
|
||||||
@ -33,11 +34,11 @@ pub struct StreamingHandler<R: io::Read> {
|
|||||||
status: StatusCode,
|
status: StatusCode,
|
||||||
content: io::BufReader<R>,
|
content: io::BufReader<R>,
|
||||||
mimetype: Mime,
|
mimetype: Mime,
|
||||||
safe_to_embed_on: Option<(String, u16)>,
|
safe_to_embed_on: Embeddable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: io::Read> StreamingHandler<R> {
|
impl<R: io::Read> StreamingHandler<R> {
|
||||||
pub fn new(content: R, status: StatusCode, mimetype: Mime, embeddable_on: Option<(String, u16)>) -> Self {
|
pub fn new(content: R, status: StatusCode, mimetype: Mime, embeddable_on: Embeddable) -> Self {
|
||||||
StreamingHandler {
|
StreamingHandler {
|
||||||
buffer: [0; BUFFER_SIZE],
|
buffer: [0; BUFFER_SIZE],
|
||||||
buffer_leftover: 0,
|
buffer_leftover: 0,
|
||||||
@ -68,7 +69,7 @@ impl<R: io::Read> server::Handler<HttpStream> for StreamingHandler<R> {
|
|||||||
fn on_response(&mut self, res: &mut server::Response) -> Next {
|
fn on_response(&mut self, res: &mut server::Response) -> Next {
|
||||||
res.set_status(self.status);
|
res.set_status(self.status);
|
||||||
res.headers_mut().set(header::ContentType(self.mimetype.clone()));
|
res.headers_mut().set(header::ContentType(self.mimetype.clone()));
|
||||||
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.clone());
|
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.take());
|
||||||
Next::write()
|
Next::write()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +175,7 @@ impl Middleware {
|
|||||||
pool: CpuPool,
|
pool: CpuPool,
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
ui_address: Option<(String, u16)>,
|
ui_address: Option<(String, u16)>,
|
||||||
|
extra_embed_on: Vec<(String, u16)>,
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
extra_dapps: Vec<PathBuf>,
|
extra_dapps: Vec<PathBuf>,
|
||||||
dapps_domain: &str,
|
dapps_domain: &str,
|
||||||
@ -183,17 +184,18 @@ impl Middleware {
|
|||||||
web_proxy_tokens: Arc<WebProxyTokens>,
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let embeddable = as_embeddable(ui_address, extra_embed_on, dapps_domain);
|
||||||
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
|
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
|
||||||
hash_fetch::urlhint::URLHintContract::new(registrar),
|
hash_fetch::urlhint::URLHintContract::new(registrar),
|
||||||
sync_status.clone(),
|
sync_status.clone(),
|
||||||
remote.clone(),
|
remote.clone(),
|
||||||
fetch.clone(),
|
fetch.clone(),
|
||||||
).embeddable_on(ui_address.clone()).allow_dapps(true));
|
).embeddable_on(embeddable.clone()).allow_dapps(true));
|
||||||
let endpoints = apps::all_endpoints(
|
let endpoints = apps::all_endpoints(
|
||||||
dapps_path,
|
dapps_path,
|
||||||
extra_dapps,
|
extra_dapps,
|
||||||
dapps_domain.to_owned(),
|
dapps_domain,
|
||||||
ui_address.clone(),
|
embeddable.clone(),
|
||||||
web_proxy_tokens,
|
web_proxy_tokens,
|
||||||
remote.clone(),
|
remote.clone(),
|
||||||
fetch.clone(),
|
fetch.clone(),
|
||||||
@ -207,7 +209,10 @@ impl Middleware {
|
|||||||
remote.clone(),
|
remote.clone(),
|
||||||
sync_status,
|
sync_status,
|
||||||
);
|
);
|
||||||
special.insert(router::SpecialEndpoint::Home, Some(apps::ui_redirection(ui_address.clone())));
|
special.insert(
|
||||||
|
router::SpecialEndpoint::Home,
|
||||||
|
Some(apps::ui_redirection(embeddable.clone())),
|
||||||
|
);
|
||||||
special
|
special
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -215,7 +220,7 @@ impl Middleware {
|
|||||||
content_fetcher,
|
content_fetcher,
|
||||||
Some(endpoints.clone()),
|
Some(endpoints.clone()),
|
||||||
special,
|
special,
|
||||||
ui_address,
|
embeddable,
|
||||||
dapps_domain.to_owned(),
|
dapps_domain.to_owned(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -251,8 +256,21 @@ fn special_endpoints(
|
|||||||
special
|
special
|
||||||
}
|
}
|
||||||
|
|
||||||
fn address(address: &(String, u16)) -> String {
|
fn address(host: &str, port: u16) -> String {
|
||||||
format!("{}:{}", address.0, address.1)
|
format!("{}:{}", host, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_embeddable(
|
||||||
|
ui_address: Option<(String, u16)>,
|
||||||
|
extra_embed_on: Vec<(String, u16)>,
|
||||||
|
dapps_domain: &str,
|
||||||
|
) -> Option<ParentFrameSettings> {
|
||||||
|
ui_address.map(|(host, port)| ParentFrameSettings {
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
extra_embed_on,
|
||||||
|
dapps_domain: dapps_domain.to_owned(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Random filename
|
/// Random filename
|
||||||
@ -261,3 +279,18 @@ fn random_filename() -> String {
|
|||||||
let mut rng = ::rand::OsRng::new().unwrap();
|
let mut rng = ::rand::OsRng::new().unwrap();
|
||||||
rng.gen_ascii_chars().take(12).collect()
|
rng.gen_ascii_chars().take(12).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Embeddable = Option<ParentFrameSettings>;
|
||||||
|
|
||||||
|
/// Parent frame host and port allowed to embed the content.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ParentFrameSettings {
|
||||||
|
/// Hostname
|
||||||
|
pub host: String,
|
||||||
|
/// Port
|
||||||
|
pub port: u16,
|
||||||
|
/// Additional pages the pages can be embedded on.
|
||||||
|
pub extra_embed_on: Vec<(String, u16)>,
|
||||||
|
/// Dapps Domain (web3.site)
|
||||||
|
pub dapps_domain: String,
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@ use page::{handler, PageCache};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler};
|
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler};
|
||||||
use parity_dapps::{WebApp, File, Info};
|
use parity_dapps::{WebApp, File, Info};
|
||||||
|
use Embeddable;
|
||||||
|
|
||||||
pub struct PageEndpoint<T : WebApp + 'static> {
|
pub struct PageEndpoint<T : WebApp + 'static> {
|
||||||
/// Content of the files
|
/// Content of the files
|
||||||
@ -25,7 +26,7 @@ pub struct PageEndpoint<T : WebApp + 'static> {
|
|||||||
/// Prefix to strip from the path (when `None` deducted from `app_id`)
|
/// Prefix to strip from the path (when `None` deducted from `app_id`)
|
||||||
pub prefix: Option<String>,
|
pub prefix: Option<String>,
|
||||||
/// Safe to be loaded in frame by other origin. (use wisely!)
|
/// Safe to be loaded in frame by other origin. (use wisely!)
|
||||||
safe_to_embed_on: Option<(String, u16)>,
|
safe_to_embed_on: Embeddable,
|
||||||
info: EndpointInfo,
|
info: EndpointInfo,
|
||||||
fallback_to_index_html: bool,
|
fallback_to_index_html: bool,
|
||||||
}
|
}
|
||||||
@ -73,7 +74,7 @@ impl<T: WebApp + 'static> PageEndpoint<T> {
|
|||||||
/// Creates new `PageEndpoint` which can be safely used in iframe
|
/// Creates new `PageEndpoint` which can be safely used in iframe
|
||||||
/// even from different origin. It might be dangerous (clickjacking).
|
/// even from different origin. It might be dangerous (clickjacking).
|
||||||
/// Use wisely!
|
/// Use wisely!
|
||||||
pub fn new_safe_to_embed(app: T, address: Option<(String, u16)>) -> Self {
|
pub fn new_safe_to_embed(app: T, address: Embeddable) -> Self {
|
||||||
let info = app.info();
|
let info = app.info();
|
||||||
PageEndpoint {
|
PageEndpoint {
|
||||||
app: Arc::new(app),
|
app: Arc::new(app),
|
||||||
|
@ -24,6 +24,7 @@ use hyper::status::StatusCode;
|
|||||||
use hyper::{Decoder, Encoder, Next};
|
use hyper::{Decoder, Encoder, Next};
|
||||||
use endpoint::EndpointPath;
|
use endpoint::EndpointPath;
|
||||||
use handlers::{ContentHandler, add_security_headers};
|
use handlers::{ContentHandler, add_security_headers};
|
||||||
|
use {Embeddable};
|
||||||
|
|
||||||
/// Represents a file that can be sent to client.
|
/// Represents a file that can be sent to client.
|
||||||
/// Implementation should keep track of bytes already sent internally.
|
/// Implementation should keep track of bytes already sent internally.
|
||||||
@ -59,7 +60,7 @@ pub enum ServedFile<T: Dapp> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Dapp> ServedFile<T> {
|
impl<T: Dapp> ServedFile<T> {
|
||||||
pub fn new(embeddable_on: Option<(String, u16)>) -> Self {
|
pub fn new(embeddable_on: Embeddable) -> Self {
|
||||||
ServedFile::Error(ContentHandler::error(
|
ServedFile::Error(ContentHandler::error(
|
||||||
StatusCode::NotFound,
|
StatusCode::NotFound,
|
||||||
"404 Not Found",
|
"404 Not Found",
|
||||||
@ -102,7 +103,7 @@ pub struct PageHandler<T: Dapp> {
|
|||||||
/// Requested path.
|
/// Requested path.
|
||||||
pub path: EndpointPath,
|
pub path: EndpointPath,
|
||||||
/// Flag indicating if the file can be safely embeded (put in iframe).
|
/// Flag indicating if the file can be safely embeded (put in iframe).
|
||||||
pub safe_to_embed_on: Option<(String, u16)>,
|
pub safe_to_embed_on: Embeddable,
|
||||||
/// Cache settings for this page.
|
/// Cache settings for this page.
|
||||||
pub cache: PageCache,
|
pub cache: PageCache,
|
||||||
}
|
}
|
||||||
@ -174,7 +175,7 @@ impl<T: Dapp> server::Handler<HttpStream> for PageHandler<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Security headers:
|
// Security headers:
|
||||||
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.clone());
|
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.take());
|
||||||
Next::write()
|
Next::write()
|
||||||
},
|
},
|
||||||
ServedFile::Error(ref mut handler) => {
|
ServedFile::Error(ref mut handler) => {
|
||||||
|
@ -21,6 +21,7 @@ use std::path::{Path, PathBuf};
|
|||||||
use page::handler::{self, PageCache, PageHandlerWaiting};
|
use page::handler::{self, PageCache, PageHandlerWaiting};
|
||||||
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler};
|
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler};
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
|
use Embeddable;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LocalPageEndpoint {
|
pub struct LocalPageEndpoint {
|
||||||
@ -28,11 +29,11 @@ pub struct LocalPageEndpoint {
|
|||||||
mime: Option<Mime>,
|
mime: Option<Mime>,
|
||||||
info: Option<EndpointInfo>,
|
info: Option<EndpointInfo>,
|
||||||
cache: PageCache,
|
cache: PageCache,
|
||||||
embeddable_on: Option<(String, u16)>,
|
embeddable_on: Embeddable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalPageEndpoint {
|
impl LocalPageEndpoint {
|
||||||
pub fn new(path: PathBuf, info: EndpointInfo, cache: PageCache, embeddable_on: Option<(String, u16)>) -> Self {
|
pub fn new(path: PathBuf, info: EndpointInfo, cache: PageCache, embeddable_on: Embeddable) -> Self {
|
||||||
LocalPageEndpoint {
|
LocalPageEndpoint {
|
||||||
path: path,
|
path: path,
|
||||||
mime: None,
|
mime: None,
|
||||||
|
@ -19,27 +19,24 @@
|
|||||||
use endpoint::{Endpoint, Handler, EndpointPath};
|
use endpoint::{Endpoint, Handler, EndpointPath};
|
||||||
use handlers::ContentHandler;
|
use handlers::ContentHandler;
|
||||||
use apps::HOME_PAGE;
|
use apps::HOME_PAGE;
|
||||||
use address;
|
use {address, Embeddable};
|
||||||
|
|
||||||
pub struct ProxyPac {
|
pub struct ProxyPac {
|
||||||
signer_address: Option<(String, u16)>,
|
embeddable: Embeddable,
|
||||||
dapps_domain: String,
|
dapps_domain: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProxyPac {
|
impl ProxyPac {
|
||||||
pub fn boxed(signer_address: Option<(String, u16)>, dapps_domain: String) -> Box<Endpoint> {
|
pub fn boxed(embeddable: Embeddable, dapps_domain: String) -> Box<Endpoint> {
|
||||||
Box::new(ProxyPac {
|
Box::new(ProxyPac { embeddable, dapps_domain })
|
||||||
signer_address: signer_address,
|
|
||||||
dapps_domain: dapps_domain,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Endpoint for ProxyPac {
|
impl Endpoint for ProxyPac {
|
||||||
fn to_handler(&self, path: EndpointPath) -> Box<Handler> {
|
fn to_handler(&self, path: EndpointPath) -> Box<Handler> {
|
||||||
let signer = self.signer_address
|
let ui = self.embeddable
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(address)
|
.map(|ref parent| address(&parent.host, parent.port))
|
||||||
.unwrap_or_else(|| format!("{}:{}", path.host, path.port));
|
.unwrap_or_else(|| format!("{}:{}", path.host, path.port));
|
||||||
|
|
||||||
let content = format!(
|
let content = format!(
|
||||||
@ -58,7 +55,7 @@ function FindProxyForURL(url, host) {{
|
|||||||
return "DIRECT";
|
return "DIRECT";
|
||||||
}}
|
}}
|
||||||
"#,
|
"#,
|
||||||
HOME_PAGE, self.dapps_domain, path.host, path.port, signer);
|
HOME_PAGE, self.dapps_domain, path.host, path.port, ui);
|
||||||
|
|
||||||
Box::new(ContentHandler::ok(content, mime!(Application/Javascript)))
|
Box::new(ContentHandler::ok(content, mime!(Application/Javascript)))
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ use apps;
|
|||||||
use apps::fetcher::Fetcher;
|
use apps::fetcher::Fetcher;
|
||||||
use endpoint::{Endpoint, Endpoints, EndpointPath, Handler};
|
use endpoint::{Endpoint, Endpoints, EndpointPath, Handler};
|
||||||
use handlers;
|
use handlers;
|
||||||
|
use Embeddable;
|
||||||
|
|
||||||
/// Special endpoints are accessible on every domain (every dapp)
|
/// Special endpoints are accessible on every domain (every dapp)
|
||||||
#[derive(Debug, PartialEq, Hash, Eq)]
|
#[derive(Debug, PartialEq, Hash, Eq)]
|
||||||
@ -45,7 +46,7 @@ pub struct Router {
|
|||||||
endpoints: Option<Endpoints>,
|
endpoints: Option<Endpoints>,
|
||||||
fetch: Arc<Fetcher>,
|
fetch: Arc<Fetcher>,
|
||||||
special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>,
|
special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>,
|
||||||
embeddable_on: Option<(String, u16)>,
|
embeddable_on: Embeddable,
|
||||||
dapps_domain: String,
|
dapps_domain: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +149,7 @@ impl Router {
|
|||||||
content_fetcher: Arc<Fetcher>,
|
content_fetcher: Arc<Fetcher>,
|
||||||
endpoints: Option<Endpoints>,
|
endpoints: Option<Endpoints>,
|
||||||
special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>,
|
special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>,
|
||||||
embeddable_on: Option<(String, u16)>,
|
embeddable_on: Embeddable,
|
||||||
dapps_domain: String,
|
dapps_domain: String,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Router {
|
Router {
|
||||||
|
@ -259,6 +259,7 @@ impl Server {
|
|||||||
CpuPool::new(4),
|
CpuPool::new(4),
|
||||||
remote,
|
remote,
|
||||||
signer_address,
|
signer_address,
|
||||||
|
vec![],
|
||||||
dapps_path,
|
dapps_path,
|
||||||
extra_dapps,
|
extra_dapps,
|
||||||
DAPPS_DOMAIN.into(),
|
DAPPS_DOMAIN.into(),
|
||||||
|
@ -31,9 +31,7 @@ use handlers::{
|
|||||||
StreamingHandler, extract_url,
|
StreamingHandler, extract_url,
|
||||||
};
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use WebProxyTokens;
|
use {Embeddable, WebProxyTokens};
|
||||||
|
|
||||||
pub type Embeddable = Option<(String, u16)>;
|
|
||||||
|
|
||||||
pub struct Web<F> {
|
pub struct Web<F> {
|
||||||
embeddable_on: Embeddable,
|
embeddable_on: Embeddable,
|
||||||
@ -43,12 +41,17 @@ pub struct Web<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Fetch> Web<F> {
|
impl<F: Fetch> Web<F> {
|
||||||
pub fn boxed(embeddable_on: Embeddable, web_proxy_tokens: Arc<WebProxyTokens>, remote: Remote, fetch: F) -> Box<Endpoint> {
|
pub fn boxed(
|
||||||
|
embeddable_on: Embeddable,
|
||||||
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||||
|
remote: Remote,
|
||||||
|
fetch: F,
|
||||||
|
) -> Box<Endpoint> {
|
||||||
Box::new(Web {
|
Box::new(Web {
|
||||||
embeddable_on: embeddable_on,
|
embeddable_on,
|
||||||
web_proxy_tokens: web_proxy_tokens,
|
web_proxy_tokens,
|
||||||
remote: remote,
|
remote,
|
||||||
fetch: fetch,
|
fetch,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,12 +102,7 @@ pub fn request(address: &SocketAddr, request: &str) -> Response {
|
|||||||
|
|
||||||
/// Check if all required security headers are present
|
/// Check if all required security headers are present
|
||||||
pub fn assert_security_headers_present(headers: &[String], port: Option<u16>) {
|
pub fn assert_security_headers_present(headers: &[String], port: Option<u16>) {
|
||||||
if let Some(port) = port {
|
if let None = port {
|
||||||
assert!(
|
|
||||||
headers.iter().find(|header| header.as_str() == &format!("X-Frame-Options: ALLOW-FROM http://127.0.0.1:{}", port)).is_some(),
|
|
||||||
"X-Frame-Options: ALLOW-FROM missing: {:?}", headers
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
assert!(
|
assert!(
|
||||||
headers.iter().find(|header| header.as_str() == "X-Frame-Options: SAMEORIGIN").is_some(),
|
headers.iter().find(|header| header.as_str() == "X-Frame-Options: SAMEORIGIN").is_some(),
|
||||||
"X-Frame-Options: SAMEORIGIN missing: {:?}", headers
|
"X-Frame-Options: SAMEORIGIN missing: {:?}", headers
|
||||||
|
@ -573,6 +573,11 @@ impl Configuration {
|
|||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
},
|
},
|
||||||
|
extra_embed_on: if self.args.flag_ui_no_validation {
|
||||||
|
vec![("localhost".to_owned(), 3000)]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -778,15 +783,11 @@ impl Configuration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ws_hosts(&self) -> Option<Vec<String>> {
|
fn ws_hosts(&self) -> Option<Vec<String>> {
|
||||||
if self.args.flag_ui_no_validation {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.hosts(&self.args.flag_ws_hosts, &self.ws_interface())
|
self.hosts(&self.args.flag_ws_hosts, &self.ws_interface())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ws_origins(&self) -> Option<Vec<String>> {
|
fn ws_origins(&self) -> Option<Vec<String>> {
|
||||||
if self.args.flag_unsafe_expose {
|
if self.args.flag_unsafe_expose || self.args.flag_ui_no_validation {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1522,7 +1523,8 @@ mod tests {
|
|||||||
port: 8180,
|
port: 8180,
|
||||||
hosts: Some(vec![]),
|
hosts: Some(vec![]),
|
||||||
});
|
});
|
||||||
assert_eq!(conf1.ws_config().unwrap().hosts, None);
|
assert_eq!(conf1.dapps_config().extra_embed_on, vec![("localhost".to_owned(), 3000)]);
|
||||||
|
assert_eq!(conf1.ws_config().unwrap().origins, None);
|
||||||
assert_eq!(conf2.directories().signer, "signer".to_owned());
|
assert_eq!(conf2.directories().signer, "signer".to_owned());
|
||||||
assert_eq!(conf2.ui_config(), UiConfiguration {
|
assert_eq!(conf2.ui_config(), UiConfiguration {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -39,6 +39,7 @@ pub struct Configuration {
|
|||||||
pub ntp_server: String,
|
pub ntp_server: String,
|
||||||
pub dapps_path: PathBuf,
|
pub dapps_path: PathBuf,
|
||||||
pub extra_dapps: Vec<PathBuf>,
|
pub extra_dapps: Vec<PathBuf>,
|
||||||
|
pub extra_embed_on: Vec<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Configuration {
|
impl Default for Configuration {
|
||||||
@ -49,6 +50,7 @@ impl Default for Configuration {
|
|||||||
ntp_server: "pool.ntp.org:123".into(),
|
ntp_server: "pool.ntp.org:123".into(),
|
||||||
dapps_path: replace_home(&data_dir, "$BASE/dapps").into(),
|
dapps_path: replace_home(&data_dir, "$BASE/dapps").into(),
|
||||||
extra_dapps: vec![],
|
extra_dapps: vec![],
|
||||||
|
extra_embed_on: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,6 +162,7 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<Mi
|
|||||||
configuration.dapps_path,
|
configuration.dapps_path,
|
||||||
configuration.extra_dapps,
|
configuration.extra_dapps,
|
||||||
rpc::DAPPS_DOMAIN,
|
rpc::DAPPS_DOMAIN,
|
||||||
|
configuration.extra_embed_on,
|
||||||
).map(Some)
|
).map(Some)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,6 +205,7 @@ mod server {
|
|||||||
_dapps_path: PathBuf,
|
_dapps_path: PathBuf,
|
||||||
_extra_dapps: Vec<PathBuf>,
|
_extra_dapps: Vec<PathBuf>,
|
||||||
_dapps_domain: &str,
|
_dapps_domain: &str,
|
||||||
|
_extra_embed_on: Vec<(String, u16)>,
|
||||||
) -> Result<Middleware, String> {
|
) -> Result<Middleware, String> {
|
||||||
Err("Your Parity version has been compiled without WebApps support.".into())
|
Err("Your Parity version has been compiled without WebApps support.".into())
|
||||||
}
|
}
|
||||||
@ -238,6 +242,7 @@ mod server {
|
|||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
extra_dapps: Vec<PathBuf>,
|
extra_dapps: Vec<PathBuf>,
|
||||||
dapps_domain: &str,
|
dapps_domain: &str,
|
||||||
|
extra_embed_on: Vec<(String, u16)>,
|
||||||
) -> Result<Middleware, String> {
|
) -> Result<Middleware, String> {
|
||||||
let signer = deps.signer;
|
let signer = deps.signer;
|
||||||
let parity_remote = parity_reactor::Remote::new(deps.remote.clone());
|
let parity_remote = parity_reactor::Remote::new(deps.remote.clone());
|
||||||
@ -248,6 +253,7 @@ mod server {
|
|||||||
deps.pool,
|
deps.pool,
|
||||||
parity_remote,
|
parity_remote,
|
||||||
deps.ui_address,
|
deps.ui_address,
|
||||||
|
extra_embed_on,
|
||||||
dapps_path,
|
dapps_path,
|
||||||
extra_dapps,
|
extra_dapps,
|
||||||
dapps_domain,
|
dapps_domain,
|
||||||
|
Loading…
Reference in New Issue
Block a user