From 1a4a985bff47e9258b68345980909b6a99a096fb Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 4 May 2021 21:15:33 +0100 Subject: [PATCH] asseturl: Break out this module from bundles Signed-off-by: Ian Jackson --- src/asseturl.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ src/bundles.rs | 84 ------------------------------------ src/lib.rs | 1 + src/prelude.rs | 2 +- 4 files changed, 112 insertions(+), 85 deletions(-) create mode 100644 src/asseturl.rs diff --git a/src/asseturl.rs b/src/asseturl.rs new file mode 100644 index 00000000..321dfe12 --- /dev/null +++ b/src/asseturl.rs @@ -0,0 +1,110 @@ +// Copyright 2020-2021 Ian Jackson and contributors to Otter +// SPDX-License-Identifier: AGPL-3.0-or-later +// There is NO WARRANTY. + +use crate::prelude::*; + +use bundles::{DigestWrite, Digester}; + +//---------- public types ---------- + +#[derive(Clone,Serialize,Deserialize)] +pub enum AssetUrlKey { + Dummy, + Y(AssetUrlKeyRaw), +} + +#[derive(Error,Debug,Copy,Clone,Serialize)] +pub struct BadAssetUrlToken; +display_as_debug!{BadAssetUrlToken} + +#[derive(Clone)] +pub struct AssetUrlToken(AssetUrlTokenRaw); + +//---------- private types ---------- + +type AssetUrlKeyRaw = [u8; 32]; + +//---------- primary functionality ---------- + +impl AssetUrlKey { + pub fn token(&self, what: &str, v: V) -> AssetUrlToken + where V: Serialize { + let k = match self { + AssetUrlKey::Y(k) => k, + _ => panic!("dummy AssetUrlKey being used!"), + }; + let mut dw = DigestWrite::sink(); + write!(dw, "{}\0", what).unwrap(); + dw.write(&k[..]).unwrap(); + rmp_serde::encode::write(&mut dw, &v).expect("serialize failed!"); + AssetUrlToken(dw.finish().0) + } + + #[throws(BadAssetUrlToken)] + pub fn check(&self, what: &str, v: &V, got: &AssetUrlToken) + -> Authorisation + where V: Serialize { + let exp = self.token(what, v); + if ! bool::from(ConstantTimeEq::ct_eq( + &exp.0[..], + &got.0[..], + )) { throw!(BadAssetUrlToken) } + else { Authorisation::authorised(v) } + } +} + +//---------- AssetUrlKey impl's ---------- + +impl Debug for AssetUrlKey { + #[throws(fmt::Error)] + fn fmt(&self, f: &mut Formatter) { + use AssetUrlKey::*; + match self { + Y(_) => write!(f, "AssetUrlKey::Y{{..}}")?, + Dummy => write!(f, "AssetUrlKey::Dummy")?, + } + } +} + +impl Default for AssetUrlKey { fn default() -> Self { Self::Dummy } } + +impl AssetUrlKey { + #[throws(IE)] + pub fn new_random() -> AssetUrlKey { + let mut buf: AssetUrlKeyRaw = default(); + let mut rng: rand::rngs::ThreadRng = thread_rng(); + rand::RngCore::try_fill_bytes(&mut rng, &mut buf) + .context("generate new AssetUrlKey")?; + AssetUrlKey::Y(buf) + } +} + +//---------- AssetUrlToken impl's ---------- + +type AssetUrlTokenRaw = digest::Output; + +impl Debug for AssetUrlToken { + #[throws(fmt::Error)] + fn fmt(&self, f: &mut Formatter) { write!(f, "AssetUrlToken{{..}}")?; } +} + +impl Display for AssetUrlToken { + #[throws(fmt::Error)] + fn fmt(&self, f: &mut Formatter) { + f.write_str(&base64::encode_config(&self.0, base64::URL_SAFE_NO_PAD))? + } +} +impl FromStr for AssetUrlToken { + type Err = BadAssetUrlToken; + #[throws(BadAssetUrlToken)] + fn from_str(s: &str) -> Self { + let mut buf: AssetUrlTokenRaw = default(); + let l = base64::decode_config_slice( + s.as_bytes(), base64::URL_SAFE_NO_PAD, &mut buf) + .map_err(|_| BadAssetUrlToken)?; + if l != buf.len() { throw!(BadAssetUrlToken) } + AssetUrlToken(buf) + } +} +hformat_as_display!{AssetUrlToken} diff --git a/src/bundles.rs b/src/bundles.rs index f84e85d0..131e69a9 100644 --- a/src/bundles.rs +++ b/src/bundles.rs @@ -45,90 +45,6 @@ hformat_as_display!{Id} const BUNDLES_MAX: Index = Index(64); -#[derive(Clone,Serialize,Deserialize)] -pub enum AssetUrlKey { - Dummy, - Y(AssetUrlKeyRaw), -} -type AssetUrlKeyRaw = [u8; 32]; -impl Debug for AssetUrlKey { - #[throws(fmt::Error)] - fn fmt(&self, f: &mut Formatter) { - use AssetUrlKey::*; - match self { - Y(_) => write!(f, "AssetUrlKey::Y{{..}}")?, - Dummy => write!(f, "AssetUrlKey::Dummy")?, - } - } -} -impl Default for AssetUrlKey { fn default() -> Self { Self::Dummy } } -impl AssetUrlKey { - #[throws(IE)] - pub fn new_random() -> AssetUrlKey { - let mut buf: AssetUrlKeyRaw = default(); - let mut rng: rand::rngs::ThreadRng = thread_rng(); - rand::RngCore::try_fill_bytes(&mut rng, &mut buf) - .context("generate new AssetUrlKey")?; - AssetUrlKey::Y(buf) - } -} -type AssetUrlTokenRaw = digest::Output; -#[derive(Clone)] -pub struct AssetUrlToken(AssetUrlTokenRaw); -impl Debug for AssetUrlToken { - #[throws(fmt::Error)] - fn fmt(&self, f: &mut Formatter) { write!(f, "AssetUrlToken{{..}}")?; } -} -impl AssetUrlKey { - pub fn token(&self, what: &str, v: V) -> AssetUrlToken - where V: Serialize { - let k = match self { - AssetUrlKey::Y(k) => k, - _ => panic!("dummy AssetUrlKey being used!"), - }; - let mut dw = DigestWrite::sink(); - write!(dw, "{}\0", what).unwrap(); - dw.write(&k[..]).unwrap(); - rmp_serde::encode::write(&mut dw, &v).expect("serialize failed!"); - AssetUrlToken(dw.finish().0) - } - - #[throws(BadAssetUrlToken)] - pub fn check(&self, what: &str, v: &V, got: &AssetUrlToken) - -> Authorisation - where V: Serialize { - let exp = self.token(what, v); - if ! bool::from(ConstantTimeEq::ct_eq( - &exp.0[..], - &got.0[..], - )) { throw!(BadAssetUrlToken) } - else { Authorisation::authorised(v) } - } -} -impl Display for AssetUrlToken { - #[throws(fmt::Error)] - fn fmt(&self, f: &mut Formatter) { - f.write_str(&base64::encode_config(&self.0, base64::URL_SAFE_NO_PAD))? - } -} -impl FromStr for AssetUrlToken { - type Err = BadAssetUrlToken; - #[throws(BadAssetUrlToken)] - fn from_str(s: &str) -> Self { - let mut buf: AssetUrlTokenRaw = default(); - let l = base64::decode_config_slice( - s.as_bytes(), base64::URL_SAFE_NO_PAD, &mut buf) - .map_err(|_| BadAssetUrlToken)?; - if l != buf.len() { throw!(BadAssetUrlToken) } - AssetUrlToken(buf) - } -} -hformat_as_display!{AssetUrlToken} - -#[derive(Error,Debug,Copy,Clone,Serialize)] -pub struct BadAssetUrlToken; -display_as_debug!{BadAssetUrlToken} - #[derive(Copy,Clone,Debug,Hash,PartialEq,Eq,Ord,PartialOrd)] #[derive(Serialize,Deserialize)] pub struct Id { pub index: Index, pub kind: Kind, } diff --git a/src/lib.rs b/src/lib.rs index 6369a5c6..64ac7e94 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ pub mod imports; pub mod prelude; pub mod accounts; +pub mod asseturl; pub mod authproofs; pub mod bundles; pub mod clock; diff --git a/src/prelude.rs b/src/prelude.rs index 4b5538f5..0881e9db 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -125,8 +125,8 @@ pub use crate::accounts::loaded_acl::{self, EffectiveACL, LoadedAcl, PermSet}; pub use crate::accounts::*; pub use crate::authproofs::{self, Authorisation, Unauthorised}; pub use crate::authproofs::AuthorisationSuperuser; +pub use crate::asseturl::*; pub use crate::bundles::{self, InstanceBundles, MgmtBundleListExt}; -pub use crate::bundles::{AssetUrlKey, AssetUrlToken, BadAssetUrlToken}; pub use crate::commands::{AccessTokenInfo, AccessTokenReport, MgmtError}; pub use crate::commands::{MgmtCommand, MgmtResponse}; pub use crate::commands::{MgmtGameInstruction, MgmtGameResponse}; -- 2.30.2