Avril 4 years ago
parent 89601f1c3c
commit 2b8a285d6c
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -294,3 +294,20 @@ impl<T> UnwrapErrInfallible<T> for Result<!, T>
} }
} }
} }
/// Declair a `submodule`.
///
/// Load the private module, and then re-export all its internals.
#[macro_export] macro_rules! submod {
(priv $name:path $(; $doc:literal)?) => {
$(#[doc=$doc])?
mod $name;
use $name::*;
};
($vis:vis $name:path $(; $doc:literal)?) => {
$(#[doc=$doc])?
mod $name;
$vis use $name::*;
};
($name:path $(; $doc:literal)) => ($crate::submod!(pub $name $(; $doc)?));
}

@ -90,186 +90,8 @@ pub enum MaybeEncrypted
Unencrypted(Data), Unencrypted(Data),
} }
#[non_exhaustive] submod!(encryption; "impl for `MaybeEncrypted`. \
#[derive(Debug)] Other `Data` encryption helpers");
enum EncryptedEntryErrorKind
{
KeyNeeded,
Decrypt(aes::Error),
Deserialize(serde_cbor::Error),
Encrypt(aes::Error),
Serialize(serde_cbor::Error),
}
/// Error type returned when performing encryption/decryption operations on `Data` through `MaybeEncrypted`.
#[non_exhaustive]
#[derive(Debug)]
pub struct EncryptedEntryError(Box<EncryptedEntryErrorKind>);
impl EncryptedEntryError
{
/// Consume into a nicely readable `eyre::Report`
pub fn report(self) -> eyre::Report
{
let (whe, sug) = match self.0.as_ref() {
EncryptedEntryErrorKind::Serialize(_) => ("Object serialisation", "Bad data?"),
EncryptedEntryErrorKind::Deserialize(_) => ("Object deserialisation", "Corrupted data?"),
EncryptedEntryErrorKind::Decrypt(_) => ("Data decryption", "Bad key?"),
EncryptedEntryErrorKind::Encrypt(_) => ("Data encryption" ,"Bad key?"),
EncryptedEntryErrorKind::KeyNeeded => return eyre::Report::from(self)
.with_suggestion(|| "Try providing a key"),
};
Err::<std::convert::Infallible, _>(self)
.with_section(|| whe.header("In operation"))
.with_warning(|| sug)
.unwrap_err()
}
}
impl error::Error for EncryptedEntryError
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(match self.0.as_ref() {
EncryptedEntryErrorKind::Decrypt(d) => d,
EncryptedEntryErrorKind::Deserialize(d) => d,
EncryptedEntryErrorKind::Encrypt(d) => d,
EncryptedEntryErrorKind::Serialize(d) => d,
_ => return None,
})
}
}
impl fmt::Display for EncryptedEntryError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self.0.as_ref() {
EncryptedEntryErrorKind::KeyNeeded => write!(f, "this entry needed a decryption key but none was provided"),
EncryptedEntryErrorKind::Decrypt(_) => write!(f, "decryption failed"),
EncryptedEntryErrorKind::Deserialize(_) => write!(f, "deserialisation failed"),
EncryptedEntryErrorKind::Encrypt(_) => write!(f, "encryption failed"),
EncryptedEntryErrorKind::Serialize(_) => write!(f, "serialisation failed"),
}
}
}
impl From<EncryptedEntryErrorKind> for EncryptedEntryError
{
#[inline] fn from(from: EncryptedEntryErrorKind) -> Self
{
Self(Box::new(from))
}
}
/// Encrypt a `Data` entry into this buffer
async fn encrypt_data_entry<T>(output: &mut T, data: &Data, key: &AesKey) -> Result<usize, EncryptedEntryError>
where T: ?Sized + AsyncWrite + Unpin
{
let bytes = serde_cbor::to_vec(data).map_err(EncryptedEntryErrorKind::Serialize)?;
Ok(aes::encrypt_stream(key, &mut &bytes[..], output).await.map_err(EncryptedEntryErrorKind::Encrypt)?)
}
/// Decrypt an encrypted `Data` entry
async fn decrypt_data_entry<T: ?Sized>(input: &mut T, key: &AesKey, init_buf: Option<Vec<u8>>) -> Result<Data, EncryptedEntryError>
where T: AsyncRead + Unpin
{
let mut output = init_buf.unwrap_or_default();
aes::decrypt_stream(key, input, &mut output).await.map_err(EncryptedEntryErrorKind::Decrypt)?;
Ok(serde_cbor::from_slice(&output[..]).map_err(EncryptedEntryErrorKind::Deserialize)?)
}
impl MaybeEncrypted
{
/// Create a new non-encrypted entry
#[inline(always)] pub const fn new_raw(data: Data) -> Self
{
Self::Unencrypted(data)
}
/// Create a new encrypted entry
#[inline] pub fn new_encrypted(data: Data, encrypt: &AesKey) -> Result<Self, EncryptedEntryError>
{
let mut buffer = Vec::new();
encrypt_data_entry(&mut buffer, &data, encrypt).now_or_never().unwrap()?;
Ok(Self::Encrypted(buffer))
}
/// Is this data entry encrypted
#[inline] pub fn is_encrypted(&self) -> bool
{
if let MaybeEncrypted::Encrypted(_) = &self {
true
} else {
false
}
}
/// Consume into a decrypted data instance
#[inline] pub fn into_unencrypted(self, key: Option<&AesKey>) -> Result<Self, EncryptedEntryError>
{
Ok(Self::Unencrypted(self.into_data(key)?))
}
/// Make this entry unencrypted
pub fn make_unencrypted(&mut self, key: Option<&AesKey>) -> Result<(), EncryptedEntryError>
{
match self {
MaybeEncrypted::Encrypted(bytes) => {
*self = MaybeEncrypted::Unencrypted(decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?);
},
_ => (),
}
Ok(())
}
/// Make this entry encrypted
pub fn make_encrypted(&mut self, key: Option<&AesKey>) -> Result<(), EncryptedEntryError>
{
match self {
MaybeEncrypted::Unencrypted(data) => {
let mut buffer = Vec::new();
encrypt_data_entry(&mut buffer, data, key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?).now_or_never().unwrap()?;
*self = Self::Encrypted(buffer);
},
_ => (),
}
Ok(())
}
/// Consume into an encrypted data instance
pub fn into_encrypted(self, key: Option<&AesKey>) -> Result<Self, EncryptedEntryError>
{
match self {
MaybeEncrypted::Unencrypted(data) => Self::new_encrypted(data, key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?),
_ => Ok(self),
}
}
/// Attempt to get the `Data`, decrypting it if needed.
pub fn get_data<'a>(&'a self, key: Option<&AesKey>) -> Result<Cow<'a, Data>, EncryptedEntryError>
{
Ok(match self {
Self::Unencrypted(data) => Cow::Borrowed(&data),
Self::Encrypted(bytes) => {
// decrypt
Cow::Owned(decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?)
},
})
}
/// Consume into the data object, decrypting it if needed.
pub fn into_data(self, key: Option<&AesKey>) -> Result<Data, EncryptedEntryError>
{
Ok(match self {
Self::Encrypted(bytes) => {
decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?
},
Self::Unencrypted(data) => data,
})
}
}
bitflags! { bitflags! {
/// And additional metadata for values /// And additional metadata for values

@ -0,0 +1,181 @@
use super::*;
#[non_exhaustive]
#[derive(Debug)]
pub(super) enum EncryptedEntryErrorKind
{
KeyNeeded,
Decrypt(aes::Error),
Deserialize(serde_cbor::Error),
Encrypt(aes::Error),
Serialize(serde_cbor::Error),
}
/// Error type returned when performing encryption/decryption operations on `Data` through `MaybeEncrypted`.
#[non_exhaustive]
#[derive(Debug)]
pub struct EncryptedEntryError(Box<EncryptedEntryErrorKind>);
impl EncryptedEntryError
{
/// Consume into a nicely readable `eyre::Report`
pub fn report(self) -> eyre::Report
{
let (whe, sug) = match self.0.as_ref() {
EncryptedEntryErrorKind::Serialize(_) => ("Object serialisation", "Bad data?"),
EncryptedEntryErrorKind::Deserialize(_) => ("Object deserialisation", "Corrupted data?"),
EncryptedEntryErrorKind::Decrypt(_) => ("Data decryption", "Bad key?"),
EncryptedEntryErrorKind::Encrypt(_) => ("Data encryption" ,"Bad key?"),
EncryptedEntryErrorKind::KeyNeeded => return eyre::Report::from(self)
.with_suggestion(|| "Try providing a key"),
};
Err::<std::convert::Infallible, _>(self)
.with_section(|| whe.header("In operation"))
.with_warning(|| sug)
.unwrap_err()
}
}
impl error::Error for EncryptedEntryError
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(match self.0.as_ref() {
EncryptedEntryErrorKind::Decrypt(d) => d,
EncryptedEntryErrorKind::Deserialize(d) => d,
EncryptedEntryErrorKind::Encrypt(d) => d,
EncryptedEntryErrorKind::Serialize(d) => d,
_ => return None,
})
}
}
impl fmt::Display for EncryptedEntryError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self.0.as_ref() {
EncryptedEntryErrorKind::KeyNeeded => write!(f, "this entry needed a decryption key but none was provided"),
EncryptedEntryErrorKind::Decrypt(_) => write!(f, "decryption failed"),
EncryptedEntryErrorKind::Deserialize(_) => write!(f, "deserialisation failed"),
EncryptedEntryErrorKind::Encrypt(_) => write!(f, "encryption failed"),
EncryptedEntryErrorKind::Serialize(_) => write!(f, "serialisation failed"),
}
}
}
impl From<EncryptedEntryErrorKind> for EncryptedEntryError
{
#[inline] fn from(from: EncryptedEntryErrorKind) -> Self
{
Self(Box::new(from))
}
}
/// Encrypt a `Data` entry into this buffer
pub(super) async fn encrypt_data_entry<T>(output: &mut T, data: &Data, key: &AesKey) -> Result<usize, EncryptedEntryError>
where T: ?Sized + AsyncWrite + Unpin
{
let bytes = serde_cbor::to_vec(data).map_err(EncryptedEntryErrorKind::Serialize)?;
Ok(aes::encrypt_stream(key, &mut &bytes[..], output).await.map_err(EncryptedEntryErrorKind::Encrypt)?)
}
/// Decrypt an encrypted `Data` entry
pub(super) async fn decrypt_data_entry<T: ?Sized>(input: &mut T, key: &AesKey, init_buf: Option<Vec<u8>>) -> Result<Data, EncryptedEntryError>
where T: AsyncRead + Unpin
{
let mut output = init_buf.unwrap_or_default();
aes::decrypt_stream(key, input, &mut output).await.map_err(EncryptedEntryErrorKind::Decrypt)?;
Ok(serde_cbor::from_slice(&output[..]).map_err(EncryptedEntryErrorKind::Deserialize)?)
}
impl MaybeEncrypted
{
/// Create a new non-encrypted entry
#[inline(always)] pub const fn new_raw(data: Data) -> Self
{
Self::Unencrypted(data)
}
/// Create a new encrypted entry
#[inline] pub fn new_encrypted(data: Data, encrypt: &AesKey) -> Result<Self, EncryptedEntryError>
{
let mut buffer = Vec::new();
encrypt_data_entry(&mut buffer, &data, encrypt).now_or_never().unwrap()?;
Ok(Self::Encrypted(buffer))
}
/// Is this data entry encrypted
#[inline] pub fn is_encrypted(&self) -> bool
{
if let MaybeEncrypted::Encrypted(_) = &self {
true
} else {
false
}
}
/// Consume into a decrypted data instance
#[inline] pub fn into_unencrypted(self, key: Option<&AesKey>) -> Result<Self, EncryptedEntryError>
{
Ok(Self::Unencrypted(self.into_data(key)?))
}
/// Make this entry unencrypted
pub fn make_unencrypted(&mut self, key: Option<&AesKey>) -> Result<(), EncryptedEntryError>
{
match self {
MaybeEncrypted::Encrypted(bytes) => {
*self = MaybeEncrypted::Unencrypted(decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?);
},
_ => (),
}
Ok(())
}
/// Make this entry encrypted
pub fn make_encrypted(&mut self, key: Option<&AesKey>) -> Result<(), EncryptedEntryError>
{
match self {
MaybeEncrypted::Unencrypted(data) => {
let mut buffer = Vec::new();
encrypt_data_entry(&mut buffer, data, key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?).now_or_never().unwrap()?;
*self = Self::Encrypted(buffer);
},
_ => (),
}
Ok(())
}
/// Consume into an encrypted data instance
pub fn into_encrypted(self, key: Option<&AesKey>) -> Result<Self, EncryptedEntryError>
{
match self {
MaybeEncrypted::Unencrypted(data) => Self::new_encrypted(data, key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?),
_ => Ok(self),
}
}
/// Attempt to get the `Data`, decrypting it if needed.
pub fn get_data<'a>(&'a self, key: Option<&AesKey>) -> Result<Cow<'a, Data>, EncryptedEntryError>
{
Ok(match self {
Self::Unencrypted(data) => Cow::Borrowed(&data),
Self::Encrypted(bytes) => {
// decrypt
Cow::Owned(decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?)
},
})
}
/// Consume into the data object, decrypting it if needed.
pub fn into_data(self, key: Option<&AesKey>) -> Result<Data, EncryptedEntryError>
{
Ok(match self {
Self::Encrypted(bytes) => {
decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?
},
Self::Unencrypted(data) => data,
})
}
}

@ -366,31 +366,4 @@ pub struct Userspace
groups: HashMap<GroupID, Group>, groups: HashMap<GroupID, Group>,
} }
impl Userspace submod!(userspace; "impl for `Userspace`");
{
/// Is this `User` or `Group` ID present in this space?
pub fn contains_id(&self, ent: &impl AsEntityId) -> bool
{
ent.entity_id().find_in_space(self).is_some()
}
/// Get a user reference from their ID
pub fn user_ref(&self, id: UserID) -> Option<UserRef<'_>>
{
if self.users.contains_key(&id) {
Some(UserRef(id, &self))
} else {
None
}
}
/// Get a group reference from their ID
pub fn group_ref(&self, id: GroupID) -> Option<GroupRef<'_>>
{
if self.groups.contains_key(&id) {
Some(GroupRef(id, &self))
} else {
None
}
}
}

@ -0,0 +1,30 @@
use super::*;
impl Userspace
{
/// Is this `User` or `Group` ID present in this space?
pub fn contains_id(&self, ent: &impl AsEntityId) -> bool
{
ent.entity_id().find_in_space(self).is_some()
}
/// Get a user reference from their ID
pub fn user_ref(&self, id: UserID) -> Option<UserRef<'_>>
{
if self.users.contains_key(&id) {
Some(UserRef(id, &self))
} else {
None
}
}
/// Get a group reference from their ID
pub fn group_ref(&self, id: GroupID) -> Option<GroupRef<'_>>
{
if self.groups.contains_key(&id) {
Some(GroupRef(id, &self))
} else {
None
}
}
}
Loading…
Cancel
Save