Skip to main content

VaultSession

Struct VaultSession 

Source
pub(crate) struct VaultSession {
    client: VaultClient,
    email: String,
    state: RwLock<SessionState>,
    unlock_gate: Mutex<()>,
    refresh_gate: Mutex<()>,
    updates: UpdateFanout,
    idle_minutes: Option<u64>,
    last_used: Mutex<Option<SystemTime>>,
    lock_generation: AtomicU64,
    audit: Option<VaultAudit>,
}
Expand description

One process-wide Vaultwarden session.

Fields§

§client: VaultClient§email: String§state: RwLock<SessionState>§unlock_gate: Mutex<()>

Serializes unlocks, so two parked cards that both carry a password cannot race: the first wins and the second reads an unlocked session.

§refresh_gate: Mutex<()>

Serializes refreshes. A rotating refresh token is spent once, so two concurrent 401s must not both redeem it; the second reads the token the first stored.

§updates: UpdateFanout

Where a rotation is announced: the enrolment blobs hold the old token and the client that owns one rewrites it from this.

§idle_minutes: Option<u64>

The configured idle bound in minutes, or None for no idle lock.

§last_used: Mutex<Option<SystemTime>>

When the session was last used, for the idle clock. Wall clock, not Instant: a monotonic clock stops while the machine sleeps, so an overnight lid-close would never reach the bound.

§lock_generation: AtomicU64

Bumped by every lock, so an unlock whose network work was overtaken by a lock does not install its keys under it.

§audit: Option<VaultAudit>

Implementations§

Source§

impl VaultSession

Source

pub(crate) fn with_client( config: &VaultConfig, app_support: Option<&Path>, config_dir: &Path, client: VaultClient, updates: UpdateFanout, ) -> Result<Self, VaultError>

Build the session’s audit around a client the workspace built. The audit path is <app-support>/vault/audit-<config-dir-store-key>.jsonl; a missing app-support dir leaves the session usable and the audit off.

Source

pub(crate) fn idle_minutes(&self) -> Option<u64>

The idle bound the config set, for the settings card.

Source

pub(crate) fn is_locked(&self) -> bool

Whether the derived keys are absent. A session that has never unlocked, one whose refresh failed and one past its idle bound all read locked.

Source

fn lock_if_idle(&self)

Lock a session that has gone unused past its configured bound. The clock is read here rather than kept by a timer, so the lock lands on the first touch after the bound - and a session nothing touches is never read unlocked by anyone.

Source

fn touch(&self)

Stamp a use of the session, for the idle clock.

Source

pub(crate) fn keys(&self) -> Result<Arc<Unlocked>, VaultError>

The unlocked keys. A caller that needs crypto reads these; a locked session returns its own error rather than an option a caller forgets.

Source

pub(crate) fn enrolment_material(&self) -> Option<VaultReleased>

The material a client wraps to enrol this device: the current refresh token and the account’s user key, base64 - or None when the session holds no tokens or keys, and when it holds no refresh token, because a blob built on material that cannot refresh is a shortcut to nothing.

Source

fn announce_rotation(&self, refresh_token: String)

Tell every view the refresh token rotated. The token is a secret: it rides the live socket for the client that owns an enrolment to rewrite its blob, and no store keeps it.

Source

pub(crate) async fn unlock( &self, password: &str, two_factor: Option<&str>, ) -> Result<(), VaultError>

Derive the master key and unlock the account, storing the tokens and the user/private/organization keys. Idempotent: a session another card already unlocked is left alone.

Source

pub(crate) async fn unlock_released( &self, refresh_token: &str, user_key: &str, ) -> Result<(), VaultError>

Unlock from material a client released through its platform authenticator: the enrolment’s refresh token and the account’s user key.

The destination is the password unlock’s - a token, a sync and the held keys - without the master password crossing on this start. The server cannot prove the released user key (client-side enforcement is the design); a wrong one fails when the private key will not unwrap. Idempotent like Self::unlock: a session another card unlocked is left alone.

Source

fn access_token(&self) -> Result<Zeroizing<String>, VaultError>

The current access token, or Locked when there is none. The clone is zeroized when the caller drops it.

Source

pub(crate) async fn refresh( &self, spent: &str, ) -> Result<Zeroizing<String>, VaultError>

Refresh the access token. A missing or rejected refresh token clears the keys and tokens, which is what makes the next held call ask for the master password; a session with no refresh token must lock too, or the card would never ask and every call would repeat the 401.

spent is the token that got the 401. Another call may have refreshed while this one waited on the gate; its token is then current and the refresh token was already spent, so that answer is handed back instead of redeeming the same refresh token twice.

Source

pub(crate) fn lock(&self)

Drop the tokens and the derived keys. The key types zeroize on drop. A lock that found a session open announces it, so every view’s vault card redraws - the settings page’s own among them.

Source

pub(crate) fn note_decrypt_failure( &self, caller: &SessionSlot, item: Option<&str>, )

A decryption failure under a key that has not changed means the account rotated its keys: drop them, so the next held call asks for the master password rather than repeating a failure against stale keys.

Source

pub(crate) async fn ensure_keys_current( &self, caller: &SessionSlot, item: Option<&str>, ) -> Result<SyncData, VaultError>

A write must not run against keys the account rotated while the session stayed open: its ciphertext would be unreadable after the next unlock. The wrapped user key’s fingerprint from unlock is compared with the one a fresh sync carries. The sync comes back so a write can stamp the account id from the same read that verified the key.

Source

pub(crate) fn note_key_unverifiable( &self, caller: &SessionSlot, item: Option<&str>, )

Drop the keys when a sync cannot prove which user key the account holds, so the next call asks for the master password instead of writing under an unverified unlock.

Source

pub(crate) fn note_key_rotation(&self, caller: &SessionSlot, item: Option<&str>)

Drop the keys after an account rotation; re-entering the master password is the only thing that fixes it.

Source

pub(crate) async fn sync(&self) -> Result<SyncData, VaultError>

GET /api/sync, through the refresh path.

Source

pub(crate) async fn get_cipher(&self, id: &str) -> Result<Value, VaultError>

Source

pub(crate) async fn create_cipher( &self, body: &Value, ) -> Result<Value, VaultError>

Source

pub(crate) async fn update_cipher( &self, id: &str, body: &Value, ) -> Result<Value, VaultError>

Source

pub(crate) async fn trash_cipher(&self, id: &str) -> Result<Value, VaultError>

Source

pub(crate) async fn restore_cipher(&self, id: &str) -> Result<Value, VaultError>

Source

pub(crate) async fn list_folders(&self) -> Result<Vec<Folder>, VaultError>

Source

pub(crate) async fn create_folder( &self, name: &str, ) -> Result<Value, VaultError>

Source

pub(crate) async fn update_folder( &self, id: &str, name: &str, ) -> Result<Value, VaultError>

Source

pub(crate) async fn delete_folder(&self, id: &str) -> Result<Value, VaultError>

Source

pub(crate) async fn create_attachment_slot( &self, cipher_id: &str, body: &Value, ) -> Result<Value, VaultError>

Source

pub(crate) async fn upload_attachment( &self, cipher_id: &str, attachment_id: &str, data: &[u8], ) -> Result<Value, VaultError>

Source

pub(crate) async fn get_attachment_meta( &self, cipher_id: &str, attachment_id: &str, ) -> Result<AttachmentMeta, VaultError>

Source

pub(crate) async fn download_attachment( &self, url: &str, max_bytes: u64, ) -> Result<Vec<u8>, VaultError>

Source

pub(crate) async fn delete_attachment( &self, cipher_id: &str, attachment_id: &str, ) -> Result<Value, VaultError>

Source

pub(crate) fn audit( &self, caller: &SessionSlot, tool: VaultTool, item_id: Option<&str>, item_name: Option<&str>, field: Option<&str>, decision: &str, result: &str, )

One audit line: who, which tool, which item and field, what was decided, and what the operation did. Never a secret value.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Any for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

§

fn type_name(&self) -> &'static str

§

impl<T> AnySync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send> ⓘ

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<S> FromSample<S> for S

§

fn from_sample_(s: S) -> S

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more