Create owned data structure for improved authentication on generic data

This commit is contained in:
timvisee 2018-04-01 22:05:14 +02:00
parent a516f8929f
commit b62ba8b8fc
No known key found for this signature in database
GPG key ID: 109CBA0BF74036C2
3 changed files with 75 additions and 21 deletions

View file

@ -3,6 +3,10 @@
use reqwest::{Client, StatusCode}; use reqwest::{Client, StatusCode};
use reqwest::header::Authorization; use reqwest::header::Authorization;
use api::data::{
Error as DataError,
OwnedData,
};
use crypto::b64; use crypto::b64;
use crypto::key_set::KeySet; use crypto::key_set::KeySet;
use crypto::sig::signature_encoded; use crypto::sig::signature_encoded;
@ -56,8 +60,9 @@ impl<'a> Password<'a> {
// Derive a new authentication key // Derive a new authentication key
key.derive_auth_password(self.password, &self.file.download_url(true)); key.derive_auth_password(self.password, &self.file.download_url(true));
// Build the password data // Build the password data, wrap it as owned
let data = PasswordData::from(self.file, &key)?; let data = OwnedData::from(PasswordData::from(&key), &self.file)
.map_err(|err| -> PrepareError { err.into() })?;
// Send the request to change the password // Send the request to change the password
self.change_password(client, data, sig) self.change_password(client, data, sig)
@ -107,7 +112,7 @@ impl<'a> Password<'a> {
fn change_password( fn change_password(
&self, &self,
client: &Client, client: &Client,
data: PasswordData, data: OwnedData<PasswordData>,
sig: String, sig: String,
) -> Result<(), ChangeError> { ) -> Result<(), ChangeError> {
// Get the password URL, and send the change // Get the password URL, and send the change
@ -132,28 +137,18 @@ impl<'a> Password<'a> {
/// The data object to send to the password endpoint, /// The data object to send to the password endpoint,
/// which sets the file password. /// which sets the file password.
#[derive(Debug, Serialize)] #[derive(Debug, Serialize, Deserialize)]
struct PasswordData { struct PasswordData {
/// The file owner token
owner_token: String,
/// The authentication key /// The authentication key
auth: String, auth: String,
} }
impl PasswordData { impl PasswordData {
/// Create the password data object from the given key set. /// Create the password data object from the given key set.
pub fn from(file: &RemoteFile, key: &KeySet) pub fn from(key: &KeySet) -> PasswordData {
-> Result<PasswordData, PrepareError> PasswordData {
{ auth: key.auth_key_encoded().unwrap(),
Ok( }
PasswordData {
owner_token: file.owner_token()
.ok_or(PrepareError::NoOwnerToken)?
.to_owned(),
auth: key.auth_key_encoded().unwrap(),
}
)
} }
} }
@ -202,9 +197,17 @@ pub enum PrepareError {
#[fail(display = "Failed to compute cryptographic signature")] #[fail(display = "Failed to compute cryptographic signature")]
ComputeSignature, ComputeSignature,
/// The owner token was missing from the file, and is required. /// Some error occurred while building the data that will be sent.
#[fail(display = "Missing owner token, must be specified")] /// The owner token might possibly be missing, the wrapped error will
NoOwnerToken, /// describe this further.
#[fail(display = "")]
Data(#[cause] DataError),
}
impl From<DataError> for PrepareError {
fn from(err: DataError) -> PrepareError {
PrepareError::Data(err)
}
} }
#[derive(Fail, Debug)] #[derive(Fail, Debug)]

50
api/src/api/data.rs Normal file
View file

@ -0,0 +1,50 @@
use serde::{Deserialize, Serialize};
use file::remote_file::RemoteFile;
/// An owned data structure, that wraps generic data.
/// This structure is used to send owned data to the Send server.
/// This owned data is authenticated using an `owner_token`,
/// wwhich this structure manages.
#[derive(Debug, Serialize, Deserialize)]
pub struct OwnedData<D> {
/// The owner token, used for request authentication purposes.
owner_token: String,
/// The wrapped data structure.
#[serde(flatten)]
inner: D,
}
impl<'a, D> OwnedData<D>
where
D: Serialize + Deserialize<'a>,
{
/// Constructor.
pub fn new(owner_token: String, inner: D) -> Self {
OwnedData {
owner_token,
inner,
}
}
/// Wrap the given data structure with this owned data structure.
/// A `file` must be given, having a set owner token.
pub fn from(inner: D, file: &RemoteFile) -> Result<Self, Error> {
Ok(
Self::new(
file.owner_token()
.ok_or(Error::NoOwnerToken)?
.to_owned(),
inner,
)
)
}
}
#[derive(Debug, Fail)]
pub enum Error {
/// Missing owner token, which is required.
#[fail(display = "Missing owner token, must be specified")]
NoOwnerToken,
}

1
api/src/api/mod.rs Normal file
View file

@ -0,0 +1 @@
pub mod data;