2019-09-13 01:12:35 +00:00
|
|
|
use actix_web::http::{
|
|
|
|
header::{HeaderMap, InvalidHeaderValue, ToStrError},
|
|
|
|
uri::PathAndQuery,
|
|
|
|
Method,
|
2019-09-11 22:05:58 +00:00
|
|
|
};
|
2019-09-13 01:29:24 +00:00
|
|
|
use failure::Fail;
|
2019-09-13 22:55:51 +00:00
|
|
|
use futures::future::IntoFuture;
|
2019-09-13 01:29:24 +00:00
|
|
|
use std::{collections::BTreeMap, fmt::Display};
|
2019-09-11 22:05:58 +00:00
|
|
|
|
2019-09-13 01:12:35 +00:00
|
|
|
mod sign;
|
|
|
|
|
2019-09-11 23:49:18 +00:00
|
|
|
#[cfg(feature = "digest")]
|
2019-09-13 01:12:35 +00:00
|
|
|
pub mod digest;
|
2019-09-11 23:49:18 +00:00
|
|
|
|
2019-09-13 22:55:51 +00:00
|
|
|
pub mod create;
|
|
|
|
pub mod middleware;
|
2019-09-11 22:05:58 +00:00
|
|
|
pub mod prelude {
|
2019-09-13 22:55:51 +00:00
|
|
|
pub use crate::{
|
2019-09-13 23:27:04 +00:00
|
|
|
middleware::{SignatureVerified, VerifySignature},
|
|
|
|
verify::Unverified,
|
2019-09-13 23:33:54 +00:00
|
|
|
Config, Sign, SignatureVerify, VerifyError,
|
2019-09-13 22:55:51 +00:00
|
|
|
};
|
2019-09-11 22:05:58 +00:00
|
|
|
|
2019-09-11 23:49:18 +00:00
|
|
|
#[cfg(feature = "digest")]
|
2019-09-13 01:12:35 +00:00
|
|
|
pub use crate::digest::{
|
2019-09-13 23:27:04 +00:00
|
|
|
middleware::{DigestVerified, VerifyDigest},
|
|
|
|
DigestClient, DigestCreate, DigestPart, DigestVerify, SignExt,
|
2019-09-13 01:12:35 +00:00
|
|
|
};
|
2019-09-11 23:49:18 +00:00
|
|
|
|
2019-09-11 22:05:58 +00:00
|
|
|
pub use actix_web::http::header::{InvalidHeaderValue, ToStrError};
|
|
|
|
}
|
2019-09-13 23:33:54 +00:00
|
|
|
pub mod verify {
|
|
|
|
pub use http_signature_normalization::verify::{
|
|
|
|
Algorithm, DeprecatedAlgorithm, ParseSignatureError, ParsedHeader, Unvalidated, Unverified,
|
|
|
|
ValidateError,
|
|
|
|
};
|
|
|
|
}
|
2019-09-11 22:05:58 +00:00
|
|
|
|
2019-09-13 22:55:51 +00:00
|
|
|
use self::{
|
|
|
|
create::Unsigned,
|
|
|
|
verify::{Algorithm, Unverified},
|
|
|
|
};
|
2019-09-11 23:49:18 +00:00
|
|
|
|
2019-09-13 22:55:51 +00:00
|
|
|
pub trait SignatureVerify {
|
|
|
|
type Error: actix_web::ResponseError;
|
|
|
|
type Future: IntoFuture<Item = bool, Error = Self::Error>;
|
|
|
|
|
|
|
|
fn signature_verify(
|
|
|
|
&mut self,
|
|
|
|
algorithm: Option<Algorithm>,
|
|
|
|
key_id: &str,
|
|
|
|
signature: &str,
|
|
|
|
signing_string: &str,
|
|
|
|
) -> Self::Future;
|
|
|
|
}
|
|
|
|
|
2019-09-11 22:05:58 +00:00
|
|
|
pub trait Sign {
|
|
|
|
fn authorization_signature<F, E, K>(self, config: &Config, key_id: K, f: F) -> Result<Self, E>
|
|
|
|
where
|
2019-09-13 22:55:51 +00:00
|
|
|
F: FnOnce(&str) -> Result<String, E>,
|
2019-09-11 22:05:58 +00:00
|
|
|
E: From<ToStrError> + From<InvalidHeaderValue>,
|
|
|
|
K: Display,
|
|
|
|
Self: Sized;
|
|
|
|
|
|
|
|
fn signature<F, E, K>(self, config: &Config, key_id: K, f: F) -> Result<Self, E>
|
|
|
|
where
|
2019-09-13 22:55:51 +00:00
|
|
|
F: FnOnce(&str) -> Result<String, E>,
|
2019-09-11 22:05:58 +00:00
|
|
|
E: From<ToStrError> + From<InvalidHeaderValue>,
|
|
|
|
K: Display,
|
|
|
|
Self: Sized;
|
|
|
|
}
|
|
|
|
|
2019-09-13 22:55:51 +00:00
|
|
|
#[derive(Clone, Debug, Default)]
|
2019-09-11 22:05:58 +00:00
|
|
|
pub struct Config {
|
|
|
|
pub config: http_signature_normalization::Config,
|
|
|
|
}
|
|
|
|
|
2019-09-13 01:29:24 +00:00
|
|
|
#[derive(Debug, Fail)]
|
2019-09-11 22:05:58 +00:00
|
|
|
pub enum VerifyError {
|
2019-09-13 01:29:24 +00:00
|
|
|
#[fail(display = "Signature error, {}", _0)]
|
|
|
|
Sig(#[cause] http_signature_normalization::VerifyError),
|
|
|
|
|
|
|
|
#[fail(display = "Failed to read header, {}", _0)]
|
|
|
|
Header(#[cause] ToStrError),
|
2019-09-11 22:05:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Config {
|
|
|
|
pub fn begin_sign(
|
|
|
|
&self,
|
|
|
|
method: &Method,
|
|
|
|
path_and_query: Option<&PathAndQuery>,
|
|
|
|
headers: HeaderMap,
|
|
|
|
) -> Result<Unsigned, ToStrError> {
|
|
|
|
let headers = headers
|
|
|
|
.iter()
|
|
|
|
.map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string())))
|
|
|
|
.collect::<Result<BTreeMap<_, _>, ToStrError>>()?;
|
|
|
|
|
|
|
|
let path_and_query = path_and_query
|
|
|
|
.map(|p| p.to_string())
|
|
|
|
.unwrap_or(String::from("/"));
|
|
|
|
|
|
|
|
let unsigned = self
|
|
|
|
.config
|
|
|
|
.begin_sign(&method.to_string(), &path_and_query, headers);
|
|
|
|
|
|
|
|
Ok(Unsigned { unsigned })
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn begin_verify(
|
|
|
|
&self,
|
|
|
|
method: &Method,
|
|
|
|
path_and_query: Option<&PathAndQuery>,
|
|
|
|
headers: HeaderMap,
|
|
|
|
) -> Result<Unverified, VerifyError> {
|
|
|
|
let headers = headers
|
|
|
|
.iter()
|
|
|
|
.map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string())))
|
|
|
|
.collect::<Result<BTreeMap<_, _>, ToStrError>>()?;
|
|
|
|
|
|
|
|
let path_and_query = path_and_query
|
|
|
|
.map(|p| p.to_string())
|
|
|
|
.unwrap_or(String::from("/"));
|
|
|
|
|
|
|
|
let unverified = self
|
|
|
|
.config
|
|
|
|
.begin_verify(&method.to_string(), &path_and_query, headers)?;
|
|
|
|
|
|
|
|
Ok(unverified)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<http_signature_normalization::VerifyError> for VerifyError {
|
|
|
|
fn from(e: http_signature_normalization::VerifyError) -> Self {
|
|
|
|
VerifyError::Sig(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ToStrError> for VerifyError {
|
|
|
|
fn from(e: ToStrError) -> Self {
|
|
|
|
VerifyError::Header(e)
|
|
|
|
}
|
|
|
|
}
|