ffsend_api/api/
nonce.rs

1use reqwest::{
2    blocking::Response,
3    header::{HeaderName, WWW_AUTHENTICATE},
4};
5use thiserror::Error;
6use url::Url;
7
8use crate::api::request::{ensure_success, ResponseError};
9use crate::client::Client;
10use crate::crypto::b64;
11
12/// The name of the header the nonce is delivered in.
13const HEADER_NONCE: HeaderName = WWW_AUTHENTICATE;
14
15/// Do a new request, and extract the nonce from a header in the given
16/// response.
17pub fn request_nonce(client: &Client, url: Url) -> Result<Vec<u8>, NonceError> {
18    // Make the request
19    let response = client.get(url).send().map_err(|_| NonceError::Request)?;
20
21    // Ensure the response is successful
22    ensure_success(&response)?;
23
24    // Extract the nonce
25    header_nonce(&response)
26}
27
28/// Extract the nonce from a header in the given response.
29pub fn header_nonce(response: &Response) -> Result<Vec<u8>, NonceError> {
30    // Get the authentication nonce
31    b64::decode(
32        response
33            .headers()
34            .get(HEADER_NONCE)
35            .ok_or(NonceError::NoNonceHeader)?
36            .to_str()
37            .map_err(|_| NonceError::MalformedNonce)?
38            .split_terminator(' ')
39            .nth(1)
40            .ok_or(NonceError::MalformedNonce)?,
41    )
42    .map_err(|_| NonceError::MalformedNonce)
43}
44
45#[derive(Error, Debug)]
46pub enum NonceError {
47    /// Sending the request to fetch a nonce failed,
48    /// as the file has expired or did never exist.
49    #[error("the file has expired or did never exist")]
50    Expired,
51
52    /// Sending the request to fetch a nonce failed.
53    #[error("failed to request encryption nonce")]
54    Request,
55
56    /// The server responded with an error while requesting the encryption nonce,
57    /// required for some operations.
58    #[error("bad response from server while requesting encryption nonce")]
59    Response(#[from] ResponseError),
60
61    /// The nonce header was missing from the request.
62    #[error("missing nonce in server response")]
63    NoNonceHeader,
64
65    /// The received nonce could not be parsed, because it was malformed.
66    /// Maybe the server responded with a new format that isn't supported yet
67    /// by this client.
68    #[error("received malformed nonce")]
69    MalformedNonce,
70}