Fix pass Git config and lazy OTP commits
This commit is contained in:
@@ -11,6 +11,7 @@ use zeroize::Zeroize as _;
|
||||
use crate::{
|
||||
command::{OtpAppendRequest, OtpInputSource, OtpInsertRequest},
|
||||
crypto::{CryptoError, KeyStore, SecretProvider},
|
||||
git::{AutomaticEntryCommitter, GitError, GitIdentity},
|
||||
recipient::{RecipientPolicyError, RecipientPolicyManager, SigningPolicy},
|
||||
repository::{EncryptedEntry, EntryPath, Repository, RepositoryError, SecretBytes},
|
||||
write::{EntryAction, EntryCommit, EntryCommitError, EntryCommitter, OverwriteDecision},
|
||||
@@ -613,12 +614,80 @@ impl<'a> OtpService<'a> {
|
||||
provider: &mut impl SecretProvider,
|
||||
committer: &mut impl EntryCommitter,
|
||||
) -> Result<OtpCodeOutcome, OtpError> {
|
||||
let (path, original, plaintext, range, uri) = self.load_code_entry(entry, provider)?;
|
||||
self.finish_code(
|
||||
path,
|
||||
original,
|
||||
plaintext,
|
||||
range,
|
||||
uri,
|
||||
unix_seconds,
|
||||
signing,
|
||||
committer,
|
||||
)
|
||||
}
|
||||
|
||||
/// Generate a code with storage-owned lazy Git selection. TOTP is
|
||||
/// read-only and never opens Git; HOTP opens the innermost repository only
|
||||
/// after the token has been decrypted and identified as counter based.
|
||||
pub fn code_automatic(
|
||||
&self,
|
||||
entry: &str,
|
||||
unix_seconds: u64,
|
||||
signing: Option<&SigningPolicy>,
|
||||
provider: &mut impl SecretProvider,
|
||||
) -> Result<OtpCodeOutcome, OtpError> {
|
||||
let (path, original, plaintext, range, uri) = self.load_code_entry(entry, provider)?;
|
||||
if uri.kind() == OtpKind::Totp {
|
||||
return Ok(OtpCodeOutcome {
|
||||
code: uri.code_at(unix_seconds)?,
|
||||
counter: None,
|
||||
});
|
||||
}
|
||||
let entry = path.to_string();
|
||||
let mut committer = AutomaticEntryCommitter::for_entry(
|
||||
self.repository,
|
||||
&entry,
|
||||
GitIdentity::ironstorage(),
|
||||
)?;
|
||||
self.finish_code(
|
||||
path,
|
||||
original,
|
||||
plaintext,
|
||||
range,
|
||||
uri,
|
||||
unix_seconds,
|
||||
signing,
|
||||
&mut committer,
|
||||
)
|
||||
}
|
||||
|
||||
fn load_code_entry(
|
||||
&self,
|
||||
entry: &str,
|
||||
provider: &mut impl SecretProvider,
|
||||
) -> Result<(EntryPath, EncryptedEntry, SecretBytes, Range<usize>, OtpUri), OtpError> {
|
||||
let path = parse_entry(entry)?;
|
||||
let original = self.repository.read_entry(&path)?;
|
||||
let plaintext = self.keys.decrypt(&original, provider)?;
|
||||
let (range, uri) = find_uri(&plaintext, &path)?.ok_or_else(|| OtpError::MissingUri {
|
||||
entry: path.clone(),
|
||||
})?;
|
||||
Ok((path, original, plaintext, range, uri))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn finish_code(
|
||||
&self,
|
||||
path: EntryPath,
|
||||
original: EncryptedEntry,
|
||||
plaintext: SecretBytes,
|
||||
range: Range<usize>,
|
||||
uri: OtpUri,
|
||||
unix_seconds: u64,
|
||||
signing: Option<&SigningPolicy>,
|
||||
committer: &mut impl EntryCommitter,
|
||||
) -> Result<OtpCodeOutcome, OtpError> {
|
||||
match uri.kind() {
|
||||
OtpKind::Totp => Ok(OtpCodeOutcome {
|
||||
code: uri.code_at(unix_seconds)?,
|
||||
@@ -722,6 +791,7 @@ pub enum OtpError {
|
||||
Repository(RepositoryError),
|
||||
Crypto(CryptoError),
|
||||
RecipientPolicy(RecipientPolicyError),
|
||||
Git(GitError),
|
||||
InvalidUri,
|
||||
InvalidScheme,
|
||||
UnsupportedType,
|
||||
@@ -771,6 +841,7 @@ impl fmt::Display for OtpError {
|
||||
Self::Repository(error) => error.fmt(formatter),
|
||||
Self::Crypto(error) => error.fmt(formatter),
|
||||
Self::RecipientPolicy(error) => error.fmt(formatter),
|
||||
Self::Git(error) => error.fmt(formatter),
|
||||
Self::InvalidUri => formatter.write_str("OTP key URI is not valid UTF-8 URI text"),
|
||||
Self::InvalidScheme => formatter.write_str("OTP key URI must use the otpauth scheme"),
|
||||
Self::UnsupportedType => formatter.write_str("OTP key URI type must be totp or hotp"),
|
||||
@@ -848,6 +919,12 @@ impl From<RecipientPolicyError> for OtpError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GitError> for OtpError {
|
||||
fn from(error: GitError) -> Self {
|
||||
Self::Git(error)
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_input(input: &[u8]) -> Result<(), OtpError> {
|
||||
if input.is_empty() {
|
||||
Err(OtpError::EmptyInput)
|
||||
|
||||
Reference in New Issue
Block a user