aboutsummaryrefslogtreecommitdiff
path: root/src/transaction/auth.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/transaction/auth.rs')
-rw-r--r--src/transaction/auth.rs51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/transaction/auth.rs b/src/transaction/auth.rs
new file mode 100644
index 0000000..f64bb4b
--- /dev/null
+++ b/src/transaction/auth.rs
@@ -0,0 +1,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::<WWWAuthenticate>().unwrap()?;
+
+ 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;
+}