Implement iPhone and Apple Watch preferences (#53)
This commit is contained in:
1 parent
81886756a2
commit
affdb55519
15 files changed
+1409
-60
No files matched your search
@@ -134,7 +134,7 @@ struct LeaseState {
|
||||
|
||||
struct Shared<B: SecretStoreBackend, C: AuthenticationClock> {
|
||||
store: SecretStore<B>,
|
||||
timeout: AuthenticationTimeout,
|
||||
timeout: Mutex<AuthenticationTimeout>,
|
||||
clock: C,
|
||||
/// Serializes access checks with relock, eliminating check-then-use races.
|
||||
operation: Mutex<()>,
|
||||
@@ -168,9 +168,14 @@ impl<B: SecretStoreBackend, C: AuthenticationClock> Clone for AuthenticationSess
|
||||
|
||||
impl<B: SecretStoreBackend, C: AuthenticationClock> fmt::Debug for AuthenticationSession<B, C> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let timeout = self
|
||||
.shared
|
||||
.timeout
|
||||
.lock()
|
||||
.map_or_else(|poisoned| *poisoned.into_inner(), |timeout| *timeout);
|
||||
formatter
|
||||
.debug_struct("AuthenticationSession")
|
||||
.field("timeout", &self.shared.timeout)
|
||||
.field("timeout", &timeout)
|
||||
.field("unlock_material", &"[REDACTED]")
|
||||
.finish()
|
||||
}
|
||||
@@ -203,7 +208,7 @@ impl<B: SecretStoreBackend, C: AuthenticationClock> AuthenticationSession<B, C>
|
||||
// The lease is the only cache. This prevents a second lifetime
|
||||
// policy in SecretStore from retaining duplicate records.
|
||||
store: SecretStore::new(backend, SecretCachePolicy::Disabled, protections),
|
||||
timeout,
|
||||
timeout: Mutex::new(timeout),
|
||||
clock,
|
||||
operation: Mutex::new(()),
|
||||
state: Mutex::new(LeaseState {
|
||||
@@ -308,6 +313,23 @@ impl<B: SecretStoreBackend, C: AuthenticationClock> AuthenticationSession<B, C>
|
||||
let _operation = self.shared.operation()?;
|
||||
self.shared.revoke(RevocationReason::Cancelled)
|
||||
}
|
||||
|
||||
/// Apply a new shared inactivity timeout to this process and any active lease.
|
||||
pub fn set_timeout(&self, timeout: AuthenticationTimeout) -> Result<(), AuthenticationError> {
|
||||
let _operation = self.shared.operation()?;
|
||||
self.shared.expire_if_needed()?;
|
||||
let deadline = self
|
||||
.shared
|
||||
.clock
|
||||
.now()
|
||||
.checked_add(timeout.duration())
|
||||
.ok_or(AuthenticationError::ClockOverflow)?;
|
||||
*self.shared.timeout()? = timeout;
|
||||
if let Some(active) = self.shared.state()?.active.as_mut() {
|
||||
active.deadline = deadline;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Generation-bound secret access. Clones are revoked together.
|
||||
@@ -351,7 +373,7 @@ impl<B: SecretStoreBackend, C: AuthenticationClock> AuthenticationHandle<B, C> {
|
||||
self.shared.expire_if_needed()?;
|
||||
let now = self.shared.clock.now();
|
||||
let deadline = now
|
||||
.checked_add(self.shared.timeout.duration())
|
||||
.checked_add(self.shared.timeout()?.duration())
|
||||
.ok_or(AuthenticationError::ClockOverflow)?;
|
||||
self.shared
|
||||
.with_active(self.generation, |active| active.deadline = deadline)
|
||||
@@ -432,10 +454,18 @@ impl<B: SecretStoreBackend, C: AuthenticationClock> Shared<B, C> {
|
||||
.map_err(|_| AuthenticationError::SecretStore(SecretStoreError::Unavailable))
|
||||
}
|
||||
|
||||
fn timeout(
|
||||
&self,
|
||||
) -> Result<std::sync::MutexGuard<'_, AuthenticationTimeout>, AuthenticationError> {
|
||||
self.timeout
|
||||
.lock()
|
||||
.map_err(|_| AuthenticationError::SecretStore(SecretStoreError::Unavailable))
|
||||
}
|
||||
|
||||
fn begin_lease(&self) -> Result<u64, AuthenticationError> {
|
||||
let now = self.clock.now();
|
||||
let deadline = now
|
||||
.checked_add(self.timeout.duration())
|
||||
.checked_add(self.timeout()?.duration())
|
||||
.ok_or(AuthenticationError::ClockOverflow)?;
|
||||
let (generation, was_active) = {
|
||||
let mut state = self.state()?;
|
||||
|
||||
Reference in new issue
Block a user