From ab6d5cefbea1e8ddf41f385dd85918f651958287 Mon Sep 17 00:00:00 2001 From: benj Date: Mon, 19 Jun 2023 17:18:21 -0700 Subject: hack to allow impersonator to impersonate target --- crates/secd/src/auth/n.rs | 91 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 5 deletions(-) (limited to 'crates/secd/src/auth/n.rs') diff --git a/crates/secd/src/auth/n.rs b/crates/secd/src/auth/n.rs index dde6e7d..12a5411 100644 --- a/crates/secd/src/auth/n.rs +++ b/crates/secd/src/auth/n.rs @@ -5,12 +5,13 @@ use crate::{ DEFAULT_SIGNUP_EMAIL, }, store::{ - AddressLens, AddressValidationLens, CredentialLens, IdentityLens, Storable, StoreError, + AddressLens, AddressValidationLens, CredentialLens, IdentityLens, ImpersonatorLens, + Storable, StoreError, }, }, util::{self, ErrorContext}, Address, AddressType, AddressValidation, AddressValidationId, AddressValidationMethod, - Credential, CredentialId, CredentialType, Identity, IdentityId, Secd, SecdError, + Credential, CredentialId, CredentialType, Identity, IdentityId, Impersonator, Secd, SecdError, ADDRESSS_VALIDATION_CODE_SIZE, ADDRESS_VALIDATION_ALLOWS_ATTEMPTS, ADDRESS_VALIDATION_IDENTITY_SURJECTION, EMAIL_VALIDATION_DURATION, }; @@ -19,6 +20,7 @@ use log::warn; use rand::Rng; use std::str::FromStr; use time::{Duration, OffsetDateTime}; +use tokio::join; use uuid::Uuid; impl Secd { @@ -363,13 +365,13 @@ impl Secd { Ok(identity) } - pub async fn validate_credential(&self, t: CredentialType) -> Result { + pub async fn validate_credential(&self, t: &CredentialType) -> Result { let mut retrieved = Credential::find( self.store.clone(), &CredentialLens { id: None, identity_id: None, - t: Some(&t), + t: Some(t), }, ) .await? @@ -396,7 +398,7 @@ impl Secd { retrieved.hash_compare(&t, &self.crypter)?; // Return the initially provided plaintext credential since it's valid - retrieved.t = t; + retrieved.t = t.clone(); Ok(retrieved) } @@ -503,4 +505,83 @@ impl Secd { credential.write(self.store.clone()).await?; Ok(()) } + + pub async fn impersonate( + &self, + impersonator_id: &IdentityId, + target_id: &IdentityId, + ) -> Result { + let impersonator_lens = IdentityLens { + id: Some(&impersonator_id), + address_type: None, + validated_address: None, + }; + let target_lens = IdentityLens { + id: Some(&target_id), + address_type: None, + validated_address: None, + }; + let (i, t) = join!( + Identity::find(self.store.clone(), &impersonator_lens,), + Identity::find(self.store.clone(), &target_lens,) + ); + + let (i, t) = ( + i.ctx("failed to retrieve impersonator identity")?, + t.ctx("failed to retrieve target identity")?, + ); + if i.is_empty() || t.is_empty() { + return Err(SecdError::IdentityNotFound) + .ctx("failed to retrieve impersonator or target identity for impersonation"); + } + + let existing_impersonation = Impersonator::find( + self.store.clone(), + &ImpersonatorLens { + impersonator_id: Some(impersonator_id), + target_id: Some(target_id), + }, + ) + .await + .ctx("failed to find existing impersonation")?; + + // TODO: We could expire the session chain, but I think we want to handle this more intelligently. + // For now, just revoke the credential manually...pita I know... + if !existing_impersonation.is_empty() { + return Err(SecdError::ImpersonatorAlreadyExists) + .ctx("Target already being impersonated by the provided impersonator identity"); + } + + let new_identity = self + .create_credential( + Credential::new_session(*target_id)?.t, + Some(*target_id), + OffsetDateTime::now_utc().checked_add(Duration::minutes(30)), + ) + .await + .ctx("failed to create new credential for target identity")?; + + let new_session = new_identity + .new_credentials + .iter() + .next() + .ok_or(SecdError::InvalidCredential) + .ctx("failed to retrieve new session from newly created target credential")? + .clone(); + + Impersonator { + impersonator: i + .into_iter() + .next() + .ok_or(SecdError::IdentityNotFound) + .ctx("failed to find impersonator identity")?, + target: new_identity, + created_at: OffsetDateTime::now_utc(), + } + .write(self.store.clone()) + .await + .ctx("failed to write new impersonator")?; + + Ok(new_session) + } } -- cgit v1.2.3