diff options
| author | benj <benj@rse8.com> | 2023-06-19 17:18:21 -0700 |
|---|---|---|
| committer | benj <benj@rse8.com> | 2023-06-19 17:18:21 -0700 |
| commit | ab6d5cefbea1e8ddf41f385dd85918f651958287 (patch) | |
| tree | ac3a6b45b1a0e6a833a627307d07e94a95ba3c23 /crates/secd/src/auth/n.rs | |
| parent | 3406b370fe290559ff2445097a380d6f48d0f9af (diff) | |
| download | secdiam-ab6d5cefbea1e8ddf41f385dd85918f651958287.tar secdiam-ab6d5cefbea1e8ddf41f385dd85918f651958287.tar.gz secdiam-ab6d5cefbea1e8ddf41f385dd85918f651958287.tar.bz2 secdiam-ab6d5cefbea1e8ddf41f385dd85918f651958287.tar.lz secdiam-ab6d5cefbea1e8ddf41f385dd85918f651958287.tar.xz secdiam-ab6d5cefbea1e8ddf41f385dd85918f651958287.tar.zst secdiam-ab6d5cefbea1e8ddf41f385dd85918f651958287.zip | |
hack to allow impersonator to impersonate target
Diffstat (limited to '')
| -rw-r--r-- | crates/secd/src/auth/n.rs | 91 |
1 files changed, 86 insertions, 5 deletions
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<Credential, SecdError> { + pub async fn validate_credential(&self, t: &CredentialType) -> Result<Credential, SecdError> { 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<Credential, SecdError> { + 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) + } } |
