Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use super::jose::{Body, eab_sign, sign};
|
||||
use crate::network::acme::http::{get_header, https};
|
||||
use crate::network::acme::{AcmeError, AcmeResult, Directory};
|
||||
use aws_lc_rs::rand::SystemRandom;
|
||||
use aws_lc_rs::signature::{ECDSA_P256_SHA256_FIXED_SIGNING, EcdsaKeyPair, EcdsaSigningAlgorithm};
|
||||
use base64::Engine;
|
||||
use base64::engine::general_purpose::{self, URL_SAFE_NO_PAD};
|
||||
use registry::schema::structs::AcmeProvider;
|
||||
use reqwest::Method;
|
||||
use utils::sanitize_email;
|
||||
|
||||
static ALG: &EcdsaSigningAlgorithm = &ECDSA_P256_SHA256_FIXED_SIGNING;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EabSettings {
|
||||
pub kid: String,
|
||||
pub hmac_key: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
pub struct NewAccountPayload<'x> {
|
||||
#[serde(rename = "termsOfServiceAgreed")]
|
||||
tos_agreed: bool,
|
||||
contact: &'x [String],
|
||||
#[serde(rename = "externalAccountBinding")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
eab: Option<Body>,
|
||||
}
|
||||
|
||||
pub async fn acme_create_account(
|
||||
provider: &mut AcmeProvider,
|
||||
eab: Option<EabSettings>,
|
||||
) -> AcmeResult<()> {
|
||||
if provider.contact.is_empty() {
|
||||
return Err(AcmeError::Invalid(
|
||||
"At least one contact email is required".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
for contact in provider.contact.iter_mut() {
|
||||
let email = sanitize_email(contact.trim().strip_prefix("mailto:").unwrap_or(contact))
|
||||
.ok_or_else(|| AcmeError::Invalid(format!("Invalid contact email: {}", contact)))?;
|
||||
*contact = format!("mailto:{}", email);
|
||||
}
|
||||
|
||||
let directory = Directory::discover(&provider.directory, provider.max_retries as u32).await?;
|
||||
let account_key = EcdsaKeyPair::generate_pkcs8(ALG, &SystemRandom::new()).unwrap();
|
||||
let key_pair = EcdsaKeyPair::from_pkcs8(ALG, account_key.as_ref())
|
||||
.map_err(|err| AcmeError::Crypto(format!("Failed to create ECDSA key pair: {}", err)))?;
|
||||
let eab = if let Some(eab) = &eab {
|
||||
eab_sign(&key_pair, &eab.kid, &eab.hmac_key, &directory.new_account)?.into()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let payload = serde_json::to_string(&NewAccountPayload {
|
||||
tos_agreed: true,
|
||||
contact: provider.contact.as_slice(),
|
||||
eab,
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let body = sign(
|
||||
&key_pair,
|
||||
None,
|
||||
directory.nonce(provider.max_retries as u32).await?,
|
||||
&directory.new_account,
|
||||
&payload,
|
||||
)?;
|
||||
|
||||
provider.account_uri = get_header(
|
||||
&https(
|
||||
&directory.new_account,
|
||||
Method::POST,
|
||||
Some(body),
|
||||
provider.max_retries as u32,
|
||||
)
|
||||
.await?,
|
||||
"Location",
|
||||
)?;
|
||||
provider.account_key = URL_SAFE_NO_PAD.encode(account_key.as_ref());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl EabSettings {
|
||||
pub fn new(kid: impl Into<String>, hmac_key: impl AsRef<[u8]>) -> AcmeResult<Self> {
|
||||
let key = general_purpose::URL_SAFE_NO_PAD
|
||||
.decode(hmac_key.as_ref())
|
||||
.map_err(|err| AcmeError::Invalid(format!("Failed to decode EAB HMAC key: {}", err)))?;
|
||||
Ok(Self {
|
||||
kid: kid.into(),
|
||||
hmac_key: key,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user