diff --git a/Cargo.lock b/Cargo.lock index 4f86b1df4..dbc605dac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -706,7 +706,7 @@ dependencies = [ "ethcore-network 1.11.0", "ethereum-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", - "igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "igd 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.0", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -780,7 +780,7 @@ dependencies = [ "ethkey 0.3.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.0", "kvdb 0.1.0", "kvdb-rocksdb 0.1.0", @@ -793,6 +793,7 @@ dependencies = [ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1200,24 +1201,6 @@ name = "httparse" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "hyper" -version = "0.10.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "hyper" version = "0.11.24" @@ -1271,14 +1254,18 @@ dependencies = [ [[package]] name = "igd" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xmltree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1654,14 +1641,6 @@ dependencies = [ "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "mime" version = "0.3.4" @@ -3291,6 +3270,17 @@ dependencies = [ "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-retry" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-rustls" version = "0.4.0" @@ -3398,11 +3388,6 @@ dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "transaction-pool" version = "1.11.0" @@ -3450,11 +3435,6 @@ dependencies = [ "trie-standardmap 0.1.0", ] -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "uint" version = "0.2.0" @@ -3731,18 +3711,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "xml-rs" -version = "0.3.6" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "xmltree" -version = "0.3.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3831,11 +3811,10 @@ dependencies = [ "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)" = "" "checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07" -"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" "checksum hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)" = "df4dd5dae401458087396b6db7fabc4d6760aa456a5fa8e92bda549f39cae661" "checksum hyper-rustls 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d6cdc1751771a14b8175764394f025e309a28c825ed9eaf97fa62bb831dc8c5" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" -"checksum igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "356a0dc23a4fa0f8ce4777258085d00a01ea4923b2efd93538fc44bf5e1bda76" +"checksum igd 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a254e265e8810deb357a9de757f784787ec415d056ededf410c0aa460afee9e" "checksum integer-encoding 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a053c9c7dcb7db1f2aa012c37dc176c62e4cdf14898dee0eecc606de835b8acb" "checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" @@ -3870,7 +3849,6 @@ dependencies = [ "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e3d709ffbb330e1566dc2f2a3c9b58a5ad4a381f740b810cd305dc3f089bc160" "checksum mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a5e6679a0614e25adc14c6434ba84e41632b765a6d9cb2031a0cca682699ae" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" @@ -3996,6 +3974,7 @@ dependencies = [ "checksum tokio-named-pipes 0.1.0 (git+https://github.com/nikvolf/tokio-named-pipes)" = "" "checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3cedc8e5af5131dc3423ffa4f877cce78ad25259a9a62de0613735a13ebc64b" +"checksum tokio-retry 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f05746ae87dca83a2016b4f5dba5b237b897dd12fd324f60afe282112f16969a" "checksum tokio-rustls 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9263e472d976e4345e50c6cce4cfe6b17c71593ea593cce1df26f1efd36debb" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec9b094851aadd2caf83ba3ad8e8c4ce65a42104f7b94d9e6550023f0407853f" @@ -4005,10 +3984,8 @@ dependencies = [ "checksum tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "137bda266504893ac4774e0ec4c2108f7ccdbcb7ac8dced6305fe9e4e0b5041a" "checksum tokio-uds 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6116c71be48f8f1656551fd16458247fdd6c03201d7893ad81189055fcde03e8" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" -"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "715254c8f0811be1a79ad3ea5e6fa3c8eddec2b03d7f5ba78cf093e56d79c24f" "checksum trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)" = "" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum uint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6477b2716357758c176c36719023e1f9726974d762150e4fc0a9c8c75488c343" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" @@ -4038,6 +4015,6 @@ dependencies = [ "checksum ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)" = "" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61" -"checksum xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7ec6c39eaa68382c8e31e35239402c0a9489d4141a8ceb0c716099a0b515b562" -"checksum xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "472a9d37c7c53ab2391161df5b89b1f3bf76dab6ab150d7941ecbdd832282082" +"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" +"checksum xmltree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9cfb54ca6b8f17d2377219ce485b134d53561b77e1393c7ea416f543a527431" "checksum zip 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c0deac03fc7d43abcf19f2c2db6bd9289f9ea3d31f350e26eb0ed8b4117983c1" diff --git a/secret_store/Cargo.toml b/secret_store/Cargo.toml index fcd022f7d..91889d701 100644 --- a/secret_store/Cargo.toml +++ b/secret_store/Cargo.toml @@ -9,7 +9,7 @@ authors = ["Parity Technologies "] byteorder = "1.0" log = "0.3" parking_lot = "0.5" -hyper = { version = "0.10", default-features = false } +hyper = { version = "0.11", default-features = false } serde = "1.0" serde_json = "1.0" serde_derive = "1.0" @@ -17,8 +17,9 @@ futures = "0.1" futures-cpupool = "0.1" rustc-hex = "1.0" tiny-keccak = "1.3" -tokio-core = "0.1.6" -tokio-io = "0.1.0" +tokio = "0.1" +tokio-core = "0.1" +tokio-io = "0.1" tokio-service = "0.1" tokio-proto = "0.1" url = "1.0" diff --git a/secret_store/src/lib.rs b/secret_store/src/lib.rs index 9a7310b11..dc45f1af3 100644 --- a/secret_store/src/lib.rs +++ b/secret_store/src/lib.rs @@ -34,6 +34,7 @@ extern crate rustc_hex; extern crate serde; extern crate serde_json; extern crate tiny_keccak; +extern crate tokio; extern crate tokio_core; extern crate tokio_io; extern crate tokio_proto; diff --git a/secret_store/src/listener/http_listener.rs b/secret_store/src/listener/http_listener.rs index 1680201e1..7d4385ccc 100644 --- a/secret_store/src/listener/http_listener.rs +++ b/secret_store/src/listener/http_listener.rs @@ -15,16 +15,16 @@ // along with Parity. If not, see . use std::collections::BTreeSet; -use std::io::Read; use std::sync::{Arc, Weak}; -use hyper::header; -use hyper::uri::RequestUri; -use hyper::method::Method as HttpMethod; -use hyper::status::StatusCode as HttpStatusCode; -use hyper::server::{Server as HttpServer, Request as HttpRequest, Response as HttpResponse, Handler as HttpHandler, - Listening as HttpListening}; +use hyper::{self, header, Chunk, Uri, Request as HttpRequest, Response as HttpResponse, Method as HttpMethod, StatusCode as HttpStatusCode}; +use hyper::server::Http; use serde::Serialize; use serde_json; +use tokio::executor::current_thread; +use tokio::net::TcpListener; +use tokio::runtime::Runtime; +use tokio_service::Service; +use futures::{future, Future, Stream}; use url::percent_encoding::percent_decode; use traits::KeyServer; @@ -34,16 +34,16 @@ use types::all::{Error, Public, MessageHash, NodeAddress, RequestSignature, Serv /// Key server http-requests listener. Available requests: /// To generate server key: POST /shadow/{server_key_id}/{signature}/{threshold} -/// To store pregenerated encrypted document key: POST /shadow/{server_key_id}/{signature}/{common_point}/{encrypted_key} -/// To generate server && document key: POST /{server_key_id}/{signature}/{threshold} +/// To store pregenerated encrypted document key: POST /shadow/{server_key_id}/{signature}/{common_point}/{encrypted_key} +/// To generate server && document key: POST /{server_key_id}/{signature}/{threshold} /// To get document key: GET /{server_key_id}/{signature} -/// To get document key shadow: GET /shadow/{server_key_id}/{signature} +/// To get document key shadow: GET /shadow/{server_key_id}/{signature} /// To generate Schnorr signature with server key: GET /schnorr/{server_key_id}/{signature}/{message_hash} /// To generate ECDSA signature with server key: GET /ecdsa/{server_key_id}/{signature}/{message_hash} /// To change servers set: POST /admin/servers_set_change/{old_signature}/{new_signature} + BODY: json array of hex-encoded nodes ids pub struct KeyServerHttpListener { - http_server: HttpListening, + _runtime: Runtime, _handler: Arc, } @@ -71,6 +71,7 @@ enum Request { } /// Cloneable http handler +#[derive(Clone)] struct KeyServerHttpHandler { handler: Arc, } @@ -87,194 +88,212 @@ impl KeyServerHttpListener { key_server: key_server, }); - let listener_address = format!("{}:{}", listener_address.address, listener_address.port); - let http_server = HttpServer::http(&listener_address) - .and_then(|http_server| http_server.handle(KeyServerHttpHandler { - handler: shared_handler.clone(), - })).map_err(|err| Error::Hyper(format!("{}", err)))?; + let mut runtime = Runtime::new()?; + let listener_address = format!("{}:{}", listener_address.address, listener_address.port).parse()?; + let listener = TcpListener::bind(&listener_address)?; + + let shared_handler2 = shared_handler.clone(); + + let server = listener.incoming() + .map_err(|e| warn!("Key server listener error: {:?}", e)) + .for_each(move |socket| { + let http: Http = Http::new(); + let serve = http.serve_connection(socket, KeyServerHttpHandler { + handler: shared_handler2.clone(), + }).map(|_| ()).map_err(|e| { + warn!("Key server handler error: {:?}", e); + }); + + // TODO: Change this to tokio::spawn once hyper is Send. + current_thread::spawn(serve); + future::ok(()) + }); + + runtime.spawn(server); let listener = KeyServerHttpListener { - http_server: http_server, + _runtime: runtime, _handler: shared_handler, }; + Ok(listener) } } -impl Drop for KeyServerHttpListener { - fn drop(&mut self) { - // ignore error as we are dropping anyway - let _ = self.http_server.close(); - } -} - -impl HttpHandler for KeyServerHttpHandler { - fn handle(&self, mut req: HttpRequest, mut res: HttpResponse) { - if req.headers.has::() { - warn!(target: "secretstore", "Ignoring {}-request {} with Origin header", req.method, req.uri); - *res.status_mut() = HttpStatusCode::NotFound; - return; - } - - let mut req_body = Default::default(); - if let Err(error) = req.read_to_string(&mut req_body) { - warn!(target: "secretstore", "Error {} reading body of {}-request {}", error, req.method, req.uri); - *res.status_mut() = HttpStatusCode::BadRequest; - return; - } - - let req_method = req.method.clone(); - let req_uri = req.uri.clone(); - match &req_uri { - &RequestUri::AbsolutePath(ref path) => match parse_request(&req_method, &path, &req_body) { - Request::GenerateServerKey(document, signature, threshold) => { - return_server_public_key(req, res, self.handler.key_server.upgrade() - .map(|key_server| key_server.generate_key(&document, &signature.into(), threshold)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "GenerateServerKey request {} has failed with: {}", req_uri, err); - err - })); - }, - Request::StoreDocumentKey(document, signature, common_point, encrypted_document_key) => { - return_empty(req, res, self.handler.key_server.upgrade() - .map(|key_server| key_server.store_document_key(&document, &signature.into(), common_point, encrypted_document_key)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "StoreDocumentKey request {} has failed with: {}", req_uri, err); - err - })); - }, - Request::GenerateDocumentKey(document, signature, threshold) => { - return_document_key(req, res, self.handler.key_server.upgrade() - .map(|key_server| key_server.generate_document_key(&document, &signature.into(), threshold)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "GenerateDocumentKey request {} has failed with: {}", req_uri, err); - err - })); - }, - Request::GetDocumentKey(document, signature) => { - return_document_key(req, res, self.handler.key_server.upgrade() - .map(|key_server| key_server.restore_document_key(&document, &signature.into())) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "GetDocumentKey request {} has failed with: {}", req_uri, err); - err - })); - }, - Request::GetDocumentKeyShadow(document, signature) => { - return_document_key_shadow(req, res, self.handler.key_server.upgrade() - .map(|key_server| key_server.restore_document_key_shadow(&document, &signature.into())) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "GetDocumentKeyShadow request {} has failed with: {}", req_uri, err); - err - })); - }, - Request::SchnorrSignMessage(document, signature, message_hash) => { - return_message_signature(req, res, self.handler.key_server.upgrade() - .map(|key_server| key_server.sign_message_schnorr(&document, &signature.into(), message_hash)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "SchnorrSignMessage request {} has failed with: {}", req_uri, err); - err - })); - }, - Request::EcdsaSignMessage(document, signature, message_hash) => { - return_message_signature(req, res, self.handler.key_server.upgrade() - .map(|key_server| key_server.sign_message_ecdsa(&document, &signature.into(), message_hash)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "EcdsaSignMessage request {} has failed with: {}", req_uri, err); - err - })); - }, - Request::ChangeServersSet(old_set_signature, new_set_signature, new_servers_set) => { - return_empty(req, res, self.handler.key_server.upgrade() - .map(|key_server| key_server.change_servers_set(old_set_signature, new_set_signature, new_servers_set)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "ChangeServersSet request {} has failed with: {}", req_uri, err); - err - })); - }, - Request::Invalid => { - warn!(target: "secretstore", "Ignoring invalid {}-request {}", req_method, req_uri); - *res.status_mut() = HttpStatusCode::BadRequest; - }, +impl KeyServerHttpHandler { + fn process(self, req_method: HttpMethod, req_uri: Uri, path: &str, req_body: &[u8]) -> HttpResponse { + match parse_request(&req_method, &path, &req_body) { + Request::GenerateServerKey(document, signature, threshold) => { + return_server_public_key(&req_uri, self.handler.key_server.upgrade() + .map(|key_server| key_server.generate_key(&document, &signature.into(), threshold)) + .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) + .map_err(|err| { + warn!(target: "secretstore", "GenerateServerKey request {} has failed with: {}", req_uri, err); + err + })) }, - _ => { + Request::StoreDocumentKey(document, signature, common_point, encrypted_document_key) => { + return_empty(&req_uri, self.handler.key_server.upgrade() + .map(|key_server| key_server.store_document_key(&document, &signature.into(), common_point, encrypted_document_key)) + .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) + .map_err(|err| { + warn!(target: "secretstore", "StoreDocumentKey request {} has failed with: {}", req_uri, err); + err + })) + }, + Request::GenerateDocumentKey(document, signature, threshold) => { + return_document_key(&req_uri, self.handler.key_server.upgrade() + .map(|key_server| key_server.generate_document_key(&document, &signature.into(), threshold)) + .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) + .map_err(|err| { + warn!(target: "secretstore", "GenerateDocumentKey request {} has failed with: {}", req_uri, err); + err + })) + }, + Request::GetDocumentKey(document, signature) => { + return_document_key(&req_uri, self.handler.key_server.upgrade() + .map(|key_server| key_server.restore_document_key(&document, &signature.into())) + .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) + .map_err(|err| { + warn!(target: "secretstore", "GetDocumentKey request {} has failed with: {}", req_uri, err); + err + })) + }, + Request::GetDocumentKeyShadow(document, signature) => { + return_document_key_shadow(&req_uri, self.handler.key_server.upgrade() + .map(|key_server| key_server.restore_document_key_shadow(&document, &signature.into())) + .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) + .map_err(|err| { + warn!(target: "secretstore", "GetDocumentKeyShadow request {} has failed with: {}", req_uri, err); + err + })) + }, + Request::SchnorrSignMessage(document, signature, message_hash) => { + return_message_signature(&req_uri, self.handler.key_server.upgrade() + .map(|key_server| key_server.sign_message_schnorr(&document, &signature.into(), message_hash)) + .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) + .map_err(|err| { + warn!(target: "secretstore", "SchnorrSignMessage request {} has failed with: {}", req_uri, err); + err + })) + }, + Request::EcdsaSignMessage(document, signature, message_hash) => { + return_message_signature(&req_uri, self.handler.key_server.upgrade() + .map(|key_server| key_server.sign_message_ecdsa(&document, &signature.into(), message_hash)) + .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) + .map_err(|err| { + warn!(target: "secretstore", "EcdsaSignMessage request {} has failed with: {}", req_uri, err); + err + })) + }, + Request::ChangeServersSet(old_set_signature, new_set_signature, new_servers_set) => { + return_empty(&req_uri, self.handler.key_server.upgrade() + .map(|key_server| key_server.change_servers_set(old_set_signature, new_set_signature, new_servers_set)) + .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) + .map_err(|err| { + warn!(target: "secretstore", "ChangeServersSet request {} has failed with: {}", req_uri, err); + err + })) + }, + Request::Invalid => { warn!(target: "secretstore", "Ignoring invalid {}-request {}", req_method, req_uri); - *res.status_mut() = HttpStatusCode::NotFound; + HttpResponse::new().with_status(HttpStatusCode::BadRequest) }, - }; + } } } -fn return_empty(req: HttpRequest, res: HttpResponse, empty: Result<(), Error>) { - return_bytes::(req, res, empty.map(|_| None)) +impl Service for KeyServerHttpHandler { + type Request = HttpRequest; + type Response = HttpResponse; + type Error = hyper::Error; + type Future = Box>; + + fn call(&self, req: HttpRequest) -> Self::Future { + if req.headers().has::() { + warn!(target: "secretstore", "Ignoring {}-request {} with Origin header", req.method(), req.uri()); + return Box::new(future::ok(HttpResponse::new().with_status(HttpStatusCode::NotFound))); + } + + let req_method = req.method().clone(); + let req_uri = req.uri().clone(); + // We cannot consume Self because of the Service trait requirement. + let this = self.clone(); + + Box::new(req.body().concat2().map(move |body| { + let path = req_uri.path().to_string(); + if req_uri.is_absolute() { + this.process(req_method, req_uri, &path, &body) + } else { + warn!(target: "secretstore", "Ignoring invalid {}-request {}", req_method, req_uri); + HttpResponse::new().with_status(HttpStatusCode::NotFound) + } + })) + } } -fn return_server_public_key(req: HttpRequest, res: HttpResponse, server_public: Result) { - return_bytes(req, res, server_public.map(|k| Some(SerializablePublic(k)))) +fn return_empty(req_uri: &Uri, empty: Result<(), Error>) -> HttpResponse { + return_bytes::(req_uri, empty.map(|_| None)) } -fn return_message_signature(req: HttpRequest, res: HttpResponse, signature: Result) { - return_bytes(req, res, signature.map(|s| Some(SerializableBytes(s)))) +fn return_server_public_key(req_uri: &Uri, server_public: Result) -> HttpResponse { + return_bytes(req_uri, server_public.map(|k| Some(SerializablePublic(k)))) } -fn return_document_key(req: HttpRequest, res: HttpResponse, document_key: Result) { - return_bytes(req, res, document_key.map(|k| Some(SerializableBytes(k)))) +fn return_message_signature(req_uri: &Uri, signature: Result) -> HttpResponse { + return_bytes(req_uri, signature.map(|s| Some(SerializableBytes(s)))) } -fn return_document_key_shadow(req: HttpRequest, res: HttpResponse, document_key_shadow: Result) { - return_bytes(req, res, document_key_shadow.map(|k| Some(SerializableEncryptedDocumentKeyShadow { +fn return_document_key(req_uri: &Uri, document_key: Result) -> HttpResponse { + return_bytes(req_uri, document_key.map(|k| Some(SerializableBytes(k)))) +} + +fn return_document_key_shadow(req_uri: &Uri, document_key_shadow: Result) -> HttpResponse { + return_bytes(req_uri, document_key_shadow.map(|k| Some(SerializableEncryptedDocumentKeyShadow { decrypted_secret: k.decrypted_secret.into(), common_point: k.common_point.expect("always filled when requesting document_key_shadow; qed").into(), decrypt_shadows: k.decrypt_shadows.expect("always filled when requesting document_key_shadow; qed").into_iter().map(Into::into).collect(), }))) } -fn return_bytes(req: HttpRequest, mut res: HttpResponse, result: Result, Error>) { +fn return_bytes(req_uri: &Uri, result: Result, Error>) -> HttpResponse { match result { Ok(Some(result)) => match serde_json::to_vec(&result) { - Ok(result) => { - res.headers_mut().set(header::ContentType::json()); - if let Err(err) = res.send(&result) { - // nothing to do, but to log an error - warn!(target: "secretstore", "response to request {} has failed with: {}", req.uri, err); - } - }, + Ok(result) => HttpResponse::new() + .with_header(header::ContentType::json()) + .with_body(result), Err(err) => { - warn!(target: "secretstore", "response to request {} has failed with: {}", req.uri, err); + warn!(target: "secretstore", "response to request {} has failed with: {}", req_uri, err); + HttpResponse::new().with_status(HttpStatusCode::InternalServerError) } }, - Ok(None) => *res.status_mut() = HttpStatusCode::Ok, - Err(err) => return_error(res, err), + Ok(None) => HttpResponse::new().with_status(HttpStatusCode::Ok), + Err(err) => return_error(err), } } -fn return_error(mut res: HttpResponse, err: Error) { - match err { - Error::InsufficientRequesterData(_) => *res.status_mut() = HttpStatusCode::BadRequest, - Error::AccessDenied => *res.status_mut() = HttpStatusCode::Forbidden, - Error::DocumentNotFound => *res.status_mut() = HttpStatusCode::NotFound, - Error::Hyper(_) => *res.status_mut() = HttpStatusCode::BadRequest, - Error::Serde(_) => *res.status_mut() = HttpStatusCode::BadRequest, - Error::Database(_) => *res.status_mut() = HttpStatusCode::InternalServerError, - Error::Internal(_) => *res.status_mut() = HttpStatusCode::InternalServerError, - } +fn return_error(err: Error) -> HttpResponse { + let mut res = match err { + Error::InsufficientRequesterData(_) => HttpResponse::new().with_status(HttpStatusCode::BadRequest), + Error::AccessDenied => HttpResponse::new().with_status(HttpStatusCode::Forbidden), + Error::DocumentNotFound => HttpResponse::new().with_status(HttpStatusCode::NotFound), + Error::Hyper(_) => HttpResponse::new().with_status(HttpStatusCode::BadRequest), + Error::Serde(_) => HttpResponse::new().with_status(HttpStatusCode::BadRequest), + Error::Database(_) => HttpResponse::new().with_status(HttpStatusCode::InternalServerError), + Error::Internal(_) => HttpResponse::new().with_status(HttpStatusCode::InternalServerError), + }; // return error text. ignore errors when returning error let error_text = format!("\"{}\"", err); if let Ok(error_text) = serde_json::to_vec(&error_text) { res.headers_mut().set(header::ContentType::json()); - let _ = res.send(&error_text); + res.set_body(error_text); } + + res } -fn parse_request(method: &HttpMethod, uri_path: &str, body: &str) -> Request { +fn parse_request(method: &HttpMethod, uri_path: &str, body: &[u8]) -> Request { let uri_path = match percent_decode(uri_path.as_bytes()).decode_utf8() { Ok(path) => path, Err(_) => return Request::Invalid, @@ -328,7 +347,7 @@ fn parse_request(method: &HttpMethod, uri_path: &str, body: &str) -> Request { } } -fn parse_admin_request(method: &HttpMethod, path: Vec, body: &str) -> Request { +fn parse_admin_request(method: &HttpMethod, path: Vec, body: &[u8]) -> Request { let args_count = path.len(); if *method != HttpMethod::Post || args_count != 4 || path[1] != "servers_set_change" { return Request::Invalid; @@ -344,7 +363,7 @@ fn parse_admin_request(method: &HttpMethod, path: Vec, body: &str) -> Re _ => return Request::Invalid, }; - let new_servers_set: BTreeSet = match serde_json::from_str(body) { + let new_servers_set: BTreeSet = match serde_json::from_slice(body) { Ok(new_servers_set) => new_servers_set, _ => return Request::Invalid, }; @@ -356,7 +375,7 @@ fn parse_admin_request(method: &HttpMethod, path: Vec, body: &str) -> Re #[cfg(test)] mod tests { use std::sync::Arc; - use hyper::method::Method as HttpMethod; + use hyper::Method as HttpMethod; use ethkey::Public; use traits::KeyServer; use key_server::tests::DummyKeyServer; @@ -370,7 +389,7 @@ mod tests { let listener = KeyServerHttpListener::start(address, Arc::downgrade(&key_server)).unwrap(); drop(listener); } - + #[test] fn parse_request_successful() { // POST /shadow/{server_key_id}/{signature}/{threshold} => generate server key @@ -416,7 +435,7 @@ mod tests { let nodes = vec![node1, node2].into_iter().collect(); assert_eq!(parse_request(&HttpMethod::Post, "/admin/servers_set_change/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/b199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01", &r#"["0x843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91", - "0x07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3"]"#), + "0x07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3"]"#.as_bytes()), Request::ChangeServersSet( "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap(), "b199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap(), @@ -437,9 +456,9 @@ mod tests { assert_eq!(parse_request(&HttpMethod::Get, "/ecdsa/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/0000000000000000000000000000000000000000000000000000000000000002/0000000000000000000000000000000000000000000000000000000000000002", Default::default()), Request::Invalid); assert_eq!(parse_request(&HttpMethod::Post, "/admin/servers_set_change/xxx/yyy", &r#"["0x843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91", - "0x07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3"]"#), + "0x07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3"]"#.as_bytes()), Request::Invalid); - assert_eq!(parse_request(&HttpMethod::Post, "/admin/servers_set_change/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01", ""), + assert_eq!(parse_request(&HttpMethod::Post, "/admin/servers_set_change/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01", "".as_bytes()), Request::Invalid); } } diff --git a/secret_store/src/types/all.rs b/secret_store/src/types/all.rs index 356f1f1f0..5e28415b1 100644 --- a/secret_store/src/types/all.rs +++ b/secret_store/src/types/all.rs @@ -15,6 +15,8 @@ // along with Parity. If not, see . use std::fmt; +use std::io; +use std::net; use std::collections::BTreeMap; use serde_json; @@ -162,6 +164,18 @@ impl From for Error { } } +impl From for Error { + fn from(err: io::Error) -> Error { + Error::Internal(err.to_string()) + } +} + +impl From for Error { + fn from(err: net::AddrParseError) -> Error { + Error::Internal(err.to_string()) + } +} + impl From for Error { fn from(err: kvdb::Error) -> Self { Error::Database(err.to_string()) diff --git a/util/network-devp2p/Cargo.toml b/util/network-devp2p/Cargo.toml index f6718d6b5..74edf83ad 100644 --- a/util/network-devp2p/Cargo.toml +++ b/util/network-devp2p/Cargo.toml @@ -14,7 +14,7 @@ rand = "0.4" tiny-keccak = "1.3" rust-crypto = "0.2.34" slab = "0.2" -igd = "0.6" +igd = "0.7" libc = "0.2.7" parking_lot = "0.5" ansi_term = "0.10"