aboutsummaryrefslogtreecommitdiff
path: root/src/transaction/auth.rs
blob: 1b3a100d4bf64b7bb5ea9ca1b47b3d60a043da16 (plain)
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
use crate::encoding::{
    headers::{Authorization, WWWAuthenticate},
    method::Method,
    request::Request,
    response::Response,
    uri::Uri,
};
use anyhow::Result;

impl Authorization {
    pub fn construct(
        request: &Request,
        failed_response: &Response,
        username: &str,
        password: &str,
    ) -> Result<Authorization> {
        let challenge = failed_response.headers.get_res::<WWWAuthenticate>()?;

        Ok(Authorization {
            response: response_digest(
                username.to_string(),
                challenge.realm.clone(),
                password.to_string(),
                request.method,
                challenge.nonce.clone(),
                request.uri.clone(),
            ),
            nonce: challenge.nonce,
            realm: challenge.realm,
            uri: request.uri.content.clone(),
            username: username.to_string(),
        })
    }
}

fn response_digest(
    username: String,
    realm: String,
    password: String,
    method: Method,
    nonce: String,
    uri: Uri,
) -> String {
    let h = |s: String| hex::encode(md5::compute(s.as_bytes()).0);
    let kd = |secret, data| h(format!("{secret}:{data}"));

    let a1 = format!("{username}:{realm}:{password}");
    let a2 = format!("{method}:{uri}");
    let response_digest = kd(h(a1), format!("{nonce}:{}", h(a2)));
    return response_digest;
}