Add type for passwords. (#8920)
* Add type for passwords. * Fix test. * Simplify `Drop` impls of `Password` and `Memzero`. * Spaces to tabs. * Custom `Drop` impl for `Password`.
This commit is contained in:
@@ -85,7 +85,7 @@ fn secret_store(dir: Box<RootDiskDirectory>, iterations: Option<u32>) -> Result<
|
||||
}
|
||||
|
||||
fn new(n: NewAccount) -> Result<String, String> {
|
||||
let password: String = match n.password_file {
|
||||
let password = match n.password_file {
|
||||
Some(file) => password_from_file(file)?,
|
||||
None => password_prompt()?,
|
||||
};
|
||||
|
||||
@@ -30,6 +30,7 @@ use upgrade::{upgrade, upgrade_data_paths};
|
||||
use sync::{validate_node_url, self};
|
||||
use db::migrate;
|
||||
use path;
|
||||
use ethkey::Password;
|
||||
|
||||
pub fn to_duration(s: &str) -> Result<Duration, String> {
|
||||
to_seconds(s).map(Duration::from_secs)
|
||||
@@ -277,7 +278,7 @@ pub fn execute_upgrades(
|
||||
}
|
||||
|
||||
/// Prompts user asking for password.
|
||||
pub fn password_prompt() -> Result<String, String> {
|
||||
pub fn password_prompt() -> Result<Password, String> {
|
||||
use rpassword::read_password;
|
||||
const STDIN_ERROR: &'static str = "Unable to ask for password on non-interactive terminal.";
|
||||
|
||||
@@ -285,12 +286,12 @@ pub fn password_prompt() -> Result<String, String> {
|
||||
print!("Type password: ");
|
||||
flush_stdout();
|
||||
|
||||
let password = read_password().map_err(|_| STDIN_ERROR.to_owned())?;
|
||||
let password = read_password().map_err(|_| STDIN_ERROR.to_owned())?.into();
|
||||
|
||||
print!("Repeat password: ");
|
||||
flush_stdout();
|
||||
|
||||
let password_repeat = read_password().map_err(|_| STDIN_ERROR.to_owned())?;
|
||||
let password_repeat = read_password().map_err(|_| STDIN_ERROR.to_owned())?.into();
|
||||
|
||||
if password != password_repeat {
|
||||
return Err("Passwords do not match!".into());
|
||||
@@ -300,24 +301,24 @@ pub fn password_prompt() -> Result<String, String> {
|
||||
}
|
||||
|
||||
/// Read a password from password file.
|
||||
pub fn password_from_file(path: String) -> Result<String, String> {
|
||||
pub fn password_from_file(path: String) -> Result<Password, String> {
|
||||
let passwords = passwords_from_files(&[path])?;
|
||||
// use only first password from the file
|
||||
passwords.get(0).map(String::to_owned)
|
||||
passwords.get(0).map(Password::clone)
|
||||
.ok_or_else(|| "Password file seems to be empty.".to_owned())
|
||||
}
|
||||
|
||||
/// Reads passwords from files. Treats each line as a separate password.
|
||||
pub fn passwords_from_files(files: &[String]) -> Result<Vec<String>, String> {
|
||||
pub fn passwords_from_files(files: &[String]) -> Result<Vec<Password>, String> {
|
||||
let passwords = files.iter().map(|filename| {
|
||||
let file = File::open(filename).map_err(|_| format!("{} Unable to read password file. Ensure it exists and permissions are correct.", filename))?;
|
||||
let reader = BufReader::new(&file);
|
||||
let lines = reader.lines()
|
||||
.filter_map(|l| l.ok())
|
||||
.map(|pwd| pwd.trim().to_owned())
|
||||
.collect::<Vec<String>>();
|
||||
.map(|pwd| pwd.trim().to_owned().into())
|
||||
.collect::<Vec<Password>>();
|
||||
Ok(lines)
|
||||
}).collect::<Result<Vec<Vec<String>>, String>>();
|
||||
}).collect::<Result<Vec<Vec<Password>>, String>>();
|
||||
Ok(passwords?.into_iter().flat_map(|x| x).collect())
|
||||
}
|
||||
|
||||
@@ -330,6 +331,7 @@ mod tests {
|
||||
use ethereum_types::U256;
|
||||
use ethcore::client::{Mode, BlockId};
|
||||
use ethcore::miner::PendingSet;
|
||||
use ethkey::Password;
|
||||
use super::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_address, to_addresses, to_price, geth_ipc_path, to_bootnodes, password_from_file};
|
||||
|
||||
#[test]
|
||||
@@ -435,7 +437,7 @@ ignored
|
||||
but the first password is trimmed
|
||||
|
||||
"#).unwrap();
|
||||
assert_eq!(&password_from_file(path.to_str().unwrap().into()).unwrap(), "password with trailing whitespace");
|
||||
assert_eq!(password_from_file(path.to_str().unwrap().into()).unwrap(), Password::from("password with trailing whitespace"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -30,7 +30,7 @@ pub struct ImportWallet {
|
||||
}
|
||||
|
||||
pub fn execute(cmd: ImportWallet) -> Result<String, String> {
|
||||
let password: String = match cmd.password_file {
|
||||
let password = match cmd.password_file {
|
||||
Some(file) => password_from_file(file)?,
|
||||
None => password_prompt()?,
|
||||
};
|
||||
|
||||
@@ -63,6 +63,7 @@ use rpc_apis;
|
||||
use secretstore;
|
||||
use signer;
|
||||
use db;
|
||||
use ethkey::Password;
|
||||
|
||||
// how often to take periodic snapshots.
|
||||
const SNAPSHOT_PERIOD: u64 = 5000;
|
||||
@@ -1002,7 +1003,7 @@ fn print_running_environment(spec_name: &String, dirs: &Directories, db_dirs: &D
|
||||
info!("Path to dapps {}", Colour::White.bold().paint(dapps_conf.dapps_path.to_string_lossy().into_owned()));
|
||||
}
|
||||
|
||||
fn prepare_account_provider(spec: &SpecType, dirs: &Directories, data_dir: &str, cfg: AccountsConfig, passwords: &[String]) -> Result<AccountProvider, String> {
|
||||
fn prepare_account_provider(spec: &SpecType, dirs: &Directories, data_dir: &str, cfg: AccountsConfig, passwords: &[Password]) -> Result<AccountProvider, String> {
|
||||
use ethcore::ethstore::EthStore;
|
||||
use ethcore::ethstore::accounts_dir::RootDiskDirectory;
|
||||
|
||||
@@ -1058,7 +1059,7 @@ fn insert_dev_account(account_provider: &AccountProvider) {
|
||||
let secret: ethkey::Secret = "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7".into();
|
||||
let dev_account = ethkey::KeyPair::from_secret(secret.clone()).expect("Valid secret produces valid key;qed");
|
||||
if !account_provider.has_account(dev_account.address()) {
|
||||
match account_provider.insert_account(secret, "") {
|
||||
match account_provider.insert_account(secret, &Password::from(String::new())) {
|
||||
Err(e) => warn!("Unable to add development account: {}", e),
|
||||
Ok(address) => {
|
||||
let _ = account_provider.set_account_name(address.clone(), "Development Account".into());
|
||||
|
||||
@@ -95,7 +95,7 @@ pub struct Dependencies<'a> {
|
||||
/// Account provider.
|
||||
pub account_provider: Arc<AccountProvider>,
|
||||
/// Passed accounts passwords.
|
||||
pub accounts_passwords: &'a [String],
|
||||
pub accounts_passwords: &'a [Password],
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "secretstore"))]
|
||||
@@ -209,6 +209,7 @@ mod server {
|
||||
}
|
||||
|
||||
pub use self::server::KeyServer;
|
||||
use ethkey::Password;
|
||||
|
||||
impl Default for Configuration {
|
||||
fn default() -> Self {
|
||||
|
||||
Reference in New Issue
Block a user