diff --git a/src/acme/handlers/directory.rs b/src/acme/handlers/directory.rs index 11af5dd..a6aa27f 100644 --- a/src/acme/handlers/directory.rs +++ b/src/acme/handlers/directory.rs @@ -1,4 +1,4 @@ -use super::{uri_to_url, HandlerState, ServiceState}; +use super::{uri_to_url, HandlerState, ServiceState, REPLAY_NONCE_HEADER}; use ratpack::prelude::*; use serde::{Deserialize, Serialize}; @@ -58,14 +58,15 @@ pub(crate) async fn directory( new_authz: url.join("./authz")?, revoke_cert: url.join("./revoke")?, key_change: url.join("./key")?, - meta: Some(DirectoryMeta::default()), + meta: None, }; Ok(( req, Some( - state - .decorate_response(url, Response::builder())? + Response::builder() + .header("content-type", "application/json") + .header(REPLAY_NONCE_HEADER, state.nonce.clone().unwrap()) .status(StatusCode::OK) .body(Body::from(serde_json::to_string(&dir)?)) .unwrap(), @@ -77,7 +78,7 @@ pub(crate) async fn directory( mod tests { #[tokio::test(flavor = "multi_thread")] async fn test_basic_directory() { - use super::{super::*, Directory, DirectoryMeta}; + use super::{super::*, Directory}; use crate::test::PGTest; use ratpack::app::TestApp; use spectral::prelude::*; @@ -111,7 +112,7 @@ mod tests { new_authz: "http://example.com/authz".parse().unwrap(), revoke_cert: "http://example.com/revoke".parse().unwrap(), key_change: "http://example.com/key".parse().unwrap(), - meta: Some(DirectoryMeta::default()), + meta: None, }); let mut app = App::with_state( @@ -140,7 +141,7 @@ mod tests { new_authz: "http://example.com/acme/authz".parse().unwrap(), revoke_cert: "http://example.com/acme/revoke".parse().unwrap(), key_change: "http://example.com/acme/key".parse().unwrap(), - meta: Some(DirectoryMeta::default()), + meta: None, }); } } diff --git a/src/acme/handlers/mod.rs b/src/acme/handlers/mod.rs index e2b6ed7..84d7d3a 100644 --- a/src/acme/handlers/mod.rs +++ b/src/acme/handlers/mod.rs @@ -28,7 +28,7 @@ pub(crate) mod nonce; pub(crate) mod order; const REPLAY_NONCE_HEADER: &str = "Replay-Nonce"; -const ACME_CONTENT_TYPE: &str = "application/jose+json"; +const ACME_CONTENT_TYPE: &str = "application/json"; /// ServiceState is the carried state globally for the application. It contains many items the /// handlers need to function. diff --git a/src/acme/handlers/order.rs b/src/acme/handlers/order.rs index eeb4d12..5f5d7f8 100644 --- a/src/acme/handlers/order.rs +++ b/src/acme/handlers/order.rs @@ -16,13 +16,14 @@ use crate::{ models::{order::Challenge, Record}, }; -use super::{uri_to_url, HandlerState, ServiceState}; +use super::{uri_to_url, HandlerState, ServiceState, REPLAY_NONCE_HEADER}; /// RFC8555 7.1.3. Detailed read. #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Order { #[serde(skip_serializing_if = "Option::is_none")] + #[serde(skip_deserializing)] pub status: Option, #[serde(skip_serializing_if = "Option::is_none")] pub expires: Option>, // required for pending and valid states @@ -34,10 +35,13 @@ pub struct Order { #[serde(skip_serializing_if = "Option::is_none")] pub error: Option, // read 7.1.3's missive on this + section 7.5 + #[serde(skip_deserializing)] #[serde(skip_serializing_if = "Option::is_none")] pub authorizations: Option>, + #[serde(skip_deserializing)] #[serde(skip_serializing_if = "Option::is_none")] pub finalize: Option, + #[serde(skip_deserializing)] #[serde(skip_serializing_if = "Option::is_none")] pub certificate: Option, } @@ -387,13 +391,12 @@ pub(crate) async fn get_certificate( let mut chain = cert.certificate; chain.append(&mut cacert); - let url = uri_to_url(appstate.baseurl.clone(), req.uri().clone()).await?; - return Ok(( req, Some( - state - .decorate_response(url, Response::builder())? + Response::builder() + .header("content-type", "application/pem-certificate-chain") + .header(REPLAY_NONCE_HEADER, state.nonce.clone().unwrap()) .status(StatusCode::OK) .body(Body::from(chain)) .unwrap(), diff --git a/src/acme/jose.rs b/src/acme/jose.rs index 40829b5..0b4069a 100644 --- a/src/acme/jose.rs +++ b/src/acme/jose.rs @@ -29,7 +29,7 @@ use lazy_static::lazy_static; const NID_ES256: Nid = Nid::X9_62_PRIME256V1; lazy_static! { - static ref EC_GROUP: EcGroup = EcGroup::from_curve_name(NID_ES256).unwrap(); + pub(crate) static ref EC_GROUP: EcGroup = EcGroup::from_curve_name(NID_ES256).unwrap(); } /// ACMEProtectedHeader identifies an ACME protected header per RFC8555. Typically this function is @@ -199,9 +199,10 @@ impl TryFrom<&mut JWK> for ACMEKey { type Error = JWSError; fn try_from(jwk: &mut JWK) -> Result { + log::info!("{}", jwk.kty); match jwk.kty.as_str() { "RSA" => Ok(ACMEKey::RSA(jwk.into_rsa()?)), - "EC" => Ok(ACMEKey::ECDSA(jwk.into_ec()?)), + "EC" | "ECDSA" => Ok(ACMEKey::ECDSA(jwk.into_ec()?)), _ => Err(JWSError::InvalidPublicKey), } } @@ -212,7 +213,7 @@ impl TryInto for JWK { fn try_into(self) -> Result { match self.kty.as_str() { "RSA" => Ok(ACMEKey::RSA(self.into_rsa()?)), - "EC" => Ok(ACMEKey::ECDSA(self.into_ec()?)), + "EC" | "ECDSA" => Ok(ACMEKey::ECDSA(self.into_ec()?)), _ => Err(JWSError::InvalidPublicKey), } }