Use and send proper data in API password action

This commit is contained in:
timvisee 2018-03-28 23:45:41 +02:00
parent 70944f071d
commit b6b095978c
No known key found for this signature in database
GPG key ID: 109CBA0BF74036C2
2 changed files with 37 additions and 22 deletions

View file

@ -17,13 +17,11 @@ pub struct Password<'a> {
/// The uploaded file to change the password for.
file: &'a DownloadFile,
/// The new password.
/// The new password to use for the file.
password: &'a str,
/// The key set
key: &'a mut KeySet,
/// The file upload nonce
/// The authentication nonce.
/// May be an empty vector if the nonce is unknown.
nonce: Vec<u8>,
}
@ -32,31 +30,38 @@ impl<'a> Password<'a> {
pub fn new(
file: &'a DownloadFile,
password: &'a str,
key: &'a mut KeySet,
nonce: Vec<u8>,
nonce: Option<Vec<u8>>,
) -> Self {
Self {
file,
password,
key,
nonce,
nonce: nonce.unwrap_or(Vec::new()),
}
}
/// Invoke the password action.
pub fn invoke(mut self, client: &Client) -> Result<(), Error> {
// Create a key set for the file
let mut key = KeySet::from(self.file);
// Fetch the authentication nonce if not set yet
if self.nonce.is_empty() {
self.nonce = self.fetch_auth_nonce(client)?;
}
// Compute a signature
let sig = signature_encoded(self.key.auth_key().unwrap(), &self.nonce)
let sig = signature_encoded(key.auth_key().unwrap(), &self.nonce)
.map_err(|_| PrepareError::ComputeSignature)?;
// Derive a new authentication key
self.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
let password_data = PasswordData::from(self.file, &self.key);
let data = PasswordData::from(self.file, &key)?;
// Send the request to change the password
self.change_password(client, password_data, sig).map_err(|err| err.into())
self.change_password(client, data, sig)
.map_err(|err| err.into())
}
/// Fetch the authentication nonce for the file from the Send server.
@ -102,13 +107,13 @@ impl<'a> Password<'a> {
fn change_password(
&self,
client: &Client,
password_data: PasswordData,
data: PasswordData,
sig: String,
) -> Result<(), ChangeError> {
// Get the password URL, and send the change
let url = self.file.api_password_url();
let response = client.post(url)
.json(&password_data)
.json(&data)
.header(Authorization(
format!("send-v1 {}", sig)
))
@ -138,12 +143,17 @@ struct PasswordData {
impl PasswordData {
/// Create the password data object from the given key set.
pub fn from(file: &DownloadFile, key: &KeySet) -> PasswordData {
PasswordData {
// TODO: do not unwrap here
owner_token: file.owner_token().unwrap().to_owned(),
auth: key.auth_key_encoded().unwrap(),
}
pub fn from(file: &DownloadFile, key: &KeySet)
-> Result<PasswordData, PrepareError>
{
Ok(
PasswordData {
owner_token: file.owner_token()
.ok_or(PrepareError::NoOwnerToken)?
.to_owned(),
auth: key.auth_key_encoded().unwrap(),
}
)
}
}
@ -191,6 +201,10 @@ pub enum PrepareError {
/// An error occurred while computing the cryptographic signature.
#[fail(display = "Failed to compute cryptographic signature")]
ComputeSignature,
/// The owner token was missing from the file, and is required.
#[fail(display = "Missing owner token, must be specified")]
NoOwnerToken,
}
#[derive(Fail, Debug)]

View file

@ -30,11 +30,12 @@ impl<'a> Password<'a> {
// Parse the file based on the URL
// TODO: handle error here
// TODO: set the owner token
let file = DownloadFile::parse_url(url)
.expect("invalid share URL, could not parse file data");
// Execute an password action
ApiPassword::new(&file, &self.cmd.password()).invoke(&client)?;
ApiPassword::new(&file, &self.cmd.password(), None).invoke(&client)?;
// Print a success message
print_success("Password set");