2016-12-11 19:30:54 +01:00
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
2016-05-27 13:03:00 +02:00
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
2016-06-07 17:21:19 +02:00
use std ::io ;
2016-05-27 13:03:00 +02:00
use std ::sync ::Arc ;
2016-07-11 17:11:49 +02:00
use std ::path ::PathBuf ;
use ansi_term ::Colour ;
2016-08-05 10:32:04 +02:00
use io ::{ ForwardPanic , PanicHandler } ;
2016-06-15 00:58:08 +02:00
use util ::path ::restrict_permissions_owner ;
2016-06-01 19:37:34 +02:00
use rpc_apis ;
2016-05-27 13:03:00 +02:00
use ethcore_signer as signer ;
2016-12-13 23:38:29 +01:00
use dir ::default_data_path ;
2017-01-11 20:02:27 +01:00
use helpers ::replace_home ;
use jsonrpc_core ::reactor ::{ RpcHandler , Remote } ;
2016-05-27 13:03:00 +02:00
pub use ethcore_signer ::Server as SignerServer ;
2016-06-07 17:21:19 +02:00
2016-07-11 17:11:49 +02:00
const CODES_FILENAME : & 'static str = " authcodes " ;
2016-05-27 13:03:00 +02:00
2016-11-14 11:56:01 +01:00
#[ derive(Debug, PartialEq, Clone) ]
2016-05-27 13:03:00 +02:00
pub struct Configuration {
pub enabled : bool ,
pub port : u16 ,
2016-08-23 16:53:24 +02:00
pub interface : String ,
2016-06-07 17:21:19 +02:00
pub signer_path : String ,
2016-08-02 18:53:53 +02:00
pub skip_origin_validation : bool ,
2016-05-27 13:03:00 +02:00
}
2016-07-25 16:09:47 +02:00
impl Default for Configuration {
fn default ( ) -> Self {
2016-12-13 23:38:29 +01:00
let data_dir = default_data_path ( ) ;
2016-07-25 16:09:47 +02:00
Configuration {
enabled : true ,
port : 8180 ,
2016-08-23 16:53:24 +02:00
interface : " 127.0.0.1 " . into ( ) ,
2016-12-15 21:56:45 +01:00
signer_path : replace_home ( & data_dir , " $BASE/signer " ) ,
2016-08-02 18:53:53 +02:00
skip_origin_validation : false ,
2016-07-25 16:09:47 +02:00
}
}
}
2016-05-27 13:03:00 +02:00
pub struct Dependencies {
pub panic_handler : Arc < PanicHandler > ,
2016-06-01 19:37:34 +02:00
pub apis : Arc < rpc_apis ::Dependencies > ,
2017-01-11 20:02:27 +01:00
pub remote : Remote ,
2016-05-27 13:03:00 +02:00
}
2016-11-16 09:37:48 +01:00
pub struct NewToken {
pub token : String ,
pub url : String ,
pub message : String ,
}
2016-07-25 16:09:47 +02:00
pub fn start ( conf : Configuration , deps : Dependencies ) -> Result < Option < SignerServer > , String > {
2016-05-27 13:03:00 +02:00
if ! conf . enabled {
2016-07-25 16:09:47 +02:00
Ok ( None )
2016-05-27 17:46:15 +02:00
} else {
2016-12-27 12:53:56 +01:00
Ok ( Some ( do_start ( conf , deps ) ? ) )
2016-05-27 13:03:00 +02:00
}
2016-05-27 17:46:15 +02:00
}
2016-05-27 13:03:00 +02:00
2016-06-07 17:21:19 +02:00
fn codes_path ( path : String ) -> PathBuf {
let mut p = PathBuf ::from ( path ) ;
p . push ( CODES_FILENAME ) ;
2016-12-16 18:17:15 +01:00
let _ = restrict_permissions_owner ( & p , true , false ) ;
2016-06-07 17:21:19 +02:00
p
}
2016-11-14 11:56:01 +01:00
pub fn execute ( cmd : Configuration ) -> Result < String , String > {
2016-12-27 12:53:56 +01:00
Ok ( generate_token_and_url ( & cmd ) ? . message )
2016-11-02 19:42:21 +01:00
}
2016-11-16 09:37:48 +01:00
pub fn generate_token_and_url ( conf : & Configuration ) -> Result < NewToken , String > {
2016-12-27 12:53:56 +01:00
let code = generate_new_token ( conf . signer_path . clone ( ) ) . map_err ( | err | format! ( " Error generating token: {:?} " , err ) ) ? ;
2016-11-14 11:56:01 +01:00
let auth_url = format! ( " http:// {} : {} /#/auth?token= {} " , conf . interface , conf . port , code ) ;
2016-11-11 17:56:52 +01:00
// And print in to the console
2016-11-16 09:37:48 +01:00
Ok ( NewToken {
token : code . clone ( ) ,
url : auth_url . clone ( ) ,
message : format ! (
r #"
2016-11-11 17:38:45 +01:00
Open : { }
to authorize your browser .
2016-11-16 09:37:48 +01:00
Or use the generated token :
2016-11-11 18:02:36 +01:00
{ } " #,
2016-11-16 09:37:48 +01:00
Colour ::White . bold ( ) . paint ( auth_url ) ,
code
)
} )
2016-07-25 16:09:47 +02:00
}
2016-10-03 15:01:10 +02:00
pub fn generate_new_token ( path : String ) -> io ::Result < String > {
2016-06-07 17:21:19 +02:00
let path = codes_path ( path ) ;
2016-12-27 12:53:56 +01:00
let mut codes = signer ::AuthCodes ::from_file ( & path ) ? ;
2016-11-14 11:56:01 +01:00
codes . clear_garbage ( ) ;
2016-12-27 12:53:56 +01:00
let code = codes . generate_new ( ) ? ;
codes . to_file ( & path ) ? ;
2016-07-17 23:00:57 +02:00
trace! ( " New key code created: {} " , Colour ::White . bold ( ) . paint ( & code [ .. ] ) ) ;
Ok ( code )
2016-06-07 17:21:19 +02:00
}
2016-07-25 16:09:47 +02:00
fn do_start ( conf : Configuration , deps : Dependencies ) -> Result < SignerServer , String > {
2016-12-27 12:53:56 +01:00
let addr = format! ( " {} : {} " , conf . interface , conf . port )
2016-07-25 16:09:47 +02:00
. parse ( )
2016-12-27 12:53:56 +01:00
. map_err ( | _ | format! ( " Invalid port specified: {} " , conf . port ) ) ? ;
2016-05-27 17:46:15 +02:00
let start_result = {
2016-06-07 17:21:19 +02:00
let server = signer ::ServerBuilder ::new (
2016-09-21 12:44:49 +02:00
deps . apis . signer_service . queue ( ) ,
2016-06-07 17:21:19 +02:00
codes_path ( conf . signer_path ) ,
) ;
2016-08-02 18:53:53 +02:00
if conf . skip_origin_validation {
warn! ( " {} " , Colour ::Red . bold ( ) . paint ( " *** INSECURE *** Running Trusted Signer with no origin validation. " ) ) ;
info! ( " If you do not intend this, exit now. " ) ;
}
let server = server . skip_origin_validation ( conf . skip_origin_validation ) ;
2017-01-11 20:02:27 +01:00
let apis = rpc_apis ::setup_rpc ( Default ::default ( ) , deps . apis , rpc_apis ::ApiSet ::SafeContext ) ;
let handler = RpcHandler ::new ( Arc ::new ( apis ) , deps . remote ) ;
server . start ( addr , handler )
2016-05-27 17:46:15 +02:00
} ;
2016-05-27 13:03:00 +02:00
match start_result {
2016-10-25 15:55:53 +02:00
Err ( signer ::ServerError ::IoError ( err ) ) = > match err . kind ( ) {
2016-11-07 17:40:53 +01:00
io ::ErrorKind ::AddrInUse = > Err ( format! ( " Trusted UI address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --ui-port and --ui-interface options. " , addr ) ) ,
2016-10-25 15:55:53 +02:00
_ = > Err ( format! ( " Trusted Signer io error: {} " , err ) ) ,
} ,
2016-07-25 16:09:47 +02:00
Err ( e ) = > Err ( format! ( " Trusted Signer Error: {:?} " , e ) ) ,
2016-05-27 13:03:00 +02:00
Ok ( server ) = > {
deps . panic_handler . forward_from ( & server ) ;
2016-07-25 16:09:47 +02:00
Ok ( server )
2016-05-27 13:03:00 +02:00
} ,
}
}