diff options
author | Daniel Mueller <deso@posteo.net> | 2019-01-19 18:37:21 -0800 |
---|---|---|
committer | Daniel Mueller <deso@posteo.net> | 2019-01-19 18:37:21 -0800 |
commit | ac2bfc709f57094bac54b299f0a307b765e9b674 (patch) | |
tree | 8e8e040559ca05883445b772bbcbd042cbb510ee | |
parent | caa78070f52841191576c4704ebcafd55af0224f (diff) | |
download | nitrocli-ac2bfc709f57094bac54b299f0a307b765e9b674.tar.gz nitrocli-ac2bfc709f57094bac54b299f0a307b765e9b674.tar.bz2 |
Introduce SecretEntry trait
Now that we have introduced the notion of a secret abstracting over
whether something is a PIN or a password in terms of terminology, we
need to define what makes a secret in code. From the pinentry module's
perspective, the commonality between the two is that they both can be
entered through a dialog containing a prompt and a description, and they
can be cached.
This change introduces a trait, SecretEntry, that defines methods
representing those properties. Right now only the existing PinEntry
struct implements this trait.
-rw-r--r-- | nitrocli/src/pinentry.rs | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/nitrocli/src/pinentry.rs b/nitrocli/src/pinentry.rs index 94218c4..f7a400c 100644 --- a/nitrocli/src/pinentry.rs +++ b/nitrocli/src/pinentry.rs @@ -17,6 +17,7 @@ // * along with this program. If not, see <http://www.gnu.org/licenses/>. * // ************************************************************************* +use std::fmt; use std::process; use std::str; @@ -31,6 +32,16 @@ Enum! {PinType, [ User => "user" ]} +/// A trait representing a secret to be entered by the user. +pub trait SecretEntry: fmt::Debug { + /// The cache ID to use for this secret. + fn cache_id(&self) -> String; + /// The prompt to display when asking for the secret. + fn prompt(&self) -> &'static str; + /// The description to display when asking for the secret. + fn description(&self, mode: Mode) -> String; +} + #[derive(Debug)] pub struct PinEntry { pin_type: PinType, @@ -52,6 +63,12 @@ impl PinEntry { }) } + pub fn pin_type(&self) -> PinType { + self.pin_type + } +} + +impl SecretEntry for PinEntry { fn cache_id(&self) -> String { let model = self.model.to_string().to_lowercase(); let suffix = format!("{}:{}", model, self.serial); @@ -88,10 +105,6 @@ impl PinEntry { self.serial, ) } - - pub fn pin_type(&self) -> PinType { - self.pin_type - } } /// Secret entry mode for pinentry. @@ -116,7 +129,7 @@ impl Mode { } } -fn parse_pinentry_pin<R>(response: R) -> Result<String, Error> +fn parse_pinentry_pin<R>(response: R) -> crate::Result<String> where R: AsRef<str>, { @@ -150,7 +163,10 @@ where /// the entry dialog. The mode describes the context of the pinentry /// dialog. It is used to choose an appropriate description and to /// decide whether a quality bar is shown in the dialog. -pub fn inquire(entry: &PinEntry, mode: Mode, error_msg: Option<&str>) -> crate::Result<String> { +pub fn inquire<E>(entry: &E, mode: Mode, error_msg: Option<&str>) -> crate::Result<String> +where + E: SecretEntry, +{ let cache_id = entry.cache_id(); let error_msg = error_msg .map(|msg| msg.replace(" ", "+")) @@ -205,7 +221,7 @@ pub fn choose(entry: &PinEntry) -> crate::Result<String> { } } -fn parse_pinentry_response<R>(response: R) -> Result<(), Error> +fn parse_pinentry_response<R>(response: R) -> crate::Result<()> where R: AsRef<str>, { @@ -220,7 +236,10 @@ where } /// Clear the cached secret represented by the given entry. -pub fn clear(entry: &PinEntry) -> Result<(), Error> { +pub fn clear<E>(entry: &E) -> crate::Result<()> +where + E: SecretEntry, +{ let command = format!("CLEAR_PASSPHRASE {}", entry.cache_id()); let output = process::Command::new("gpg-connect-agent") .arg(command) |