1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use reqwest::{Client, Response};
use reqwest::header::{HeaderName, WWW_AUTHENTICATE};
use url::Url;
use crate::api::request::{ensure_success, ResponseError};
use crate::crypto::b64;
const HEADER_NONCE: HeaderName = WWW_AUTHENTICATE;
pub fn request_nonce(client: &Client, url: Url) -> Result<Vec<u8>, NonceError> {
let response = client.get(url).send().map_err(|_| NonceError::Request)?;
ensure_success(&response)?;
header_nonce(&response)
}
pub fn header_nonce(response: &Response) -> Result<Vec<u8>, NonceError> {
b64::decode(
response
.headers()
.get(HEADER_NONCE)
.ok_or(NonceError::NoNonceHeader)?
.to_str()
.map_err(|_| NonceError::MalformedNonce)?
.split_terminator(' ')
.nth(1)
.ok_or(NonceError::MalformedNonce)?,
)
.map_err(|_| NonceError::MalformedNonce)
}
#[derive(Fail, Debug)]
pub enum NonceError {
#[fail(display = "the file has expired or did never exist")]
Expired,
#[fail(display = "failed to request encryption nonce")]
Request,
#[fail(display = "bad response from server while requesting encryption nonce")]
Response(#[cause] ResponseError),
#[fail(display = "missing nonce in server response")]
NoNonceHeader,
#[fail(display = "received malformed nonce")]
MalformedNonce,
}
impl From<ResponseError> for NonceError {
fn from(err: ResponseError) -> Self {
match err {
ResponseError::Expired => NonceError::Expired,
err => NonceError::Response(err),
}
}
}