pub mod ca;
pub mod challenge;
pub mod dns;
pub mod handlers;
pub mod jose;
use std::{collections::HashSet, convert::TryFrom, sync::Arc};
use hyper::Body;
use tokio::sync::Mutex;
use async_trait::async_trait;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use crate::{
errors::{
db::{LoadError, SaveError},
ACMEValidationError,
},
models::{nonce::Nonce, Postgres, Record},
util::make_nonce,
};
use self::dns::DNSName;
lazy_static! {
pub static ref ACME_EXPECTED_ALGS: [String; 2] = ["ES256".to_string(), "RS256".to_string()];
}
#[must_use]
pub enum ACMEResult {
Ok(hyper::Response<Body>),
Err(crate::errors::Error),
}
impl Into<Result<hyper::Response<Body>, serde_json::Error>> for ACMEResult {
fn into(self) -> Result<hyper::Response<Body>, serde_json::Error> {
match self {
ACMEResult::Ok(res) => Ok(res),
ACMEResult::Err(e) => {
return Ok(hyper::Response::builder()
.status(500)
.header("content-type", "application/json")
.body(Body::from(serde_json::to_string(&e)?))
.unwrap())
}
}
}
}
impl From<crate::errors::Error> for ACMEResult {
fn from(e: crate::errors::Error) -> Self {
return ACMEResult::Err(e);
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")] #[serde(tag = "type", content = "value")]
pub enum ACMEIdentifier {
DNS(dns::DNSName), }
impl TryFrom<String> for ACMEIdentifier {
type Error = LoadError;
fn try_from(value: String) -> Result<Self, Self::Error> {
match DNSName::from_str(&value) {
Ok(x) => Ok(ACMEIdentifier::DNS(x)),
Err(e) => Err(LoadError::Generic(e.to_string())),
}
}
}
impl ACMEIdentifier {
pub fn to_string(self) -> String {
match self {
ACMEIdentifier::DNS(name) => name.to_string(),
}
}
}
#[async_trait]
pub trait NonceValidator {
async fn validate(&self, nonce: &str) -> Result<(), ACMEValidationError>;
async fn make(&self) -> Result<String, SaveError>;
}
#[derive(Debug, Clone)]
pub struct SetValidator(Arc<Mutex<HashSet<String>>>);
impl Default for SetValidator {
fn default() -> Self {
SetValidator(Arc::new(Mutex::new(HashSet::new())))
}
}
#[async_trait]
impl NonceValidator for SetValidator {
async fn validate(&self, nonce: &str) -> Result<(), ACMEValidationError> {
if self.0.lock().await.remove(nonce) {
Ok(())
} else {
Err(ACMEValidationError::NonceNotFound)
}
}
async fn make(&self) -> Result<String, SaveError> {
let nonce = make_nonce(None);
if !self.0.lock().await.insert(nonce.clone()) {
return Err(SaveError::Generic("could not persist nonce".to_string()));
}
Ok(nonce)
}
}
#[derive(Clone)]
pub struct PostgresNonceValidator(crate::models::Postgres);
impl PostgresNonceValidator {
pub fn new(pg: Postgres) -> Self {
Self(pg)
}
}
#[async_trait]
impl NonceValidator for PostgresNonceValidator {
async fn validate(&self, nonce: &str) -> Result<(), ACMEValidationError> {
let nonce = match Nonce::find(nonce.to_string(), self.0.clone()).await {
Ok(nonce) => nonce,
Err(_) => return Err(ACMEValidationError::NonceNotFound),
};
if let Err(_) = nonce.delete(self.0.clone()).await {
return Err(ACMEValidationError::NonceNotFound);
}
Ok(())
}
async fn make(&self) -> Result<String, SaveError> {
let mut nonce = Nonce::new();
nonce.create(self.0.clone()).await?;
Ok(nonce.id().unwrap().unwrap())
}
}