1use crate::acceptor::AcmeAcceptor;
2use crate::acme::{Account, AcmeError, Auth, AuthStatus, Directory, Identifier, Order, OrderStatus, ACME_TLS_ALPN_NAME};
3use crate::{any_ecdsa_type, crypto_provider, AcmeConfig, Incoming, ResolvesServerCertAcme, UseChallenge};
4use async_io::Timer;
5use chrono::{DateTime, TimeZone, Utc};
6use core::fmt;
7use futures::prelude::*;
8use futures::ready;
9use futures_rustls::pki_types::{CertificateDer as RustlsCertificate, PrivateKeyDer, PrivatePkcs8KeyDer};
10use futures_rustls::rustls::crypto::CryptoProvider;
11use futures_rustls::rustls::sign::CertifiedKey;
12use futures_rustls::rustls::ServerConfig;
13use rcgen::{CertificateParams, DistinguishedName, KeyPair, PKCS_ECDSA_P256_SHA256};
14use std::convert::Infallible;
15use std::fmt::Debug;
16use std::future::Future;
17use std::pin::Pin;
18use std::sync::Arc;
19use std::task::{Context, Poll};
20use std::time::Duration;
21use thiserror::Error;
22use x509_parser::parse_x509_certificate;
23
24#[allow(clippy::type_complexity)]
25pub struct AcmeState<EC: Debug = Infallible, EA: Debug = EC> {
26 config: Arc<AcmeConfig<EC, EA>>,
27 resolver: Arc<ResolvesServerCertAcme>,
28 account_key: Option<Vec<u8>>,
29
30 early_action: Option<Pin<Box<dyn Future<Output = Event<EC, EA>> + Send>>>,
31 load_cert: Option<Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>, EC>> + Send>>>,
32 load_account: Option<Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>, EA>> + Send>>>,
33 order: Option<Pin<Box<dyn Future<Output = Result<Vec<u8>, OrderError>> + Send>>>,
34 backoff_cnt: usize,
35 wait: Option<Timer>,
36}
37
38impl<EC: 'static + Debug, EA: 'static + Debug> fmt::Debug for AcmeState<EC, EA> {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 f.debug_struct("AcmeState").field("config", &self.config).finish_non_exhaustive()
41 }
42}
43
44pub type Event<EC, EA> = Result<EventOk, EventError<EC, EA>>;
45
46#[derive(Debug)]
47pub enum EventOk {
48 DeployedCachedCert,
49 DeployedNewCert,
50 CertCacheStore,
51 AccountCacheStore,
52}
53
54#[derive(Error, Debug)]
55pub enum EventError<EC: Debug, EA: Debug> {
56 #[error("cert cache load: {0}")]
57 CertCacheLoad(EC),
58 #[error("account cache load: {0}")]
59 AccountCacheLoad(EA),
60 #[error("cert cache store: {0}")]
61 CertCacheStore(EC),
62 #[error("account cache store: {0}")]
63 AccountCacheStore(EA),
64 #[error("cached cert parse: {0}")]
65 CachedCertParse(CertParseError),
66 #[error("order: {0}")]
67 Order(OrderError),
68 #[error("new cert parse: {0}")]
69 NewCertParse(CertParseError),
70}
71
72#[derive(Error, Debug)]
73pub enum OrderError {
74 #[error("acme error: {0}")]
75 Acme(#[from] AcmeError),
76 #[error("certificate generation error: {0}")]
77 Rcgen(#[from] rcgen::Error),
78 #[error("bad order object: {0:?}")]
79 BadOrder(Order),
80 #[error("bad auth object: {0:?}")]
81 BadAuth(Auth),
82 #[error("authorization for {0} failed too many times")]
83 TooManyAttemptsAuth(String),
84 #[error("order status stayed on processing too long")]
85 ProcessingTimeout(Order),
86}
87
88#[derive(Error, Debug)]
89pub enum CertParseError {
90 #[error("X509 parsing error: {0}")]
91 X509(#[from] x509_parser::nom::Err<x509_parser::error::X509Error>),
92 #[error("expected 2 or more pem, got: {0}")]
93 Pem(#[from] pem::PemError),
94 #[error("expected 2 or more pem, got: {0}")]
95 TooFewPem(usize),
96 #[error("unsupported private key type")]
97 InvalidPrivateKey,
98}
99
100impl<EC: 'static + Debug, EA: 'static + Debug> AcmeState<EC, EA> {
101 pub fn incoming<TCP: AsyncRead + AsyncWrite + Unpin, ETCP, ITCP: Stream<Item = Result<TCP, ETCP>> + Unpin>(
102 self,
103 tcp_incoming: ITCP,
104 alpn_protocols: Vec<Vec<u8>>,
105 ) -> Incoming<TCP, ETCP, ITCP, EC, EA> {
106 #[allow(deprecated)]
107 let acceptor = self.acceptor();
108 Incoming::new(tcp_incoming, self, acceptor, alpn_protocols)
109 }
110 #[deprecated(note = "please use high-level API via `AcmeState::incoming()` instead or refer to updated low-level API examples")]
111 #[allow(deprecated)]
112 pub fn acceptor(&self) -> AcmeAcceptor {
113 AcmeAcceptor::new(self.resolver())
114 }
115 #[cfg(feature = "tokio")]
116 pub fn tokio_incoming<
117 TokioTCP: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin,
118 ETCP,
119 TokioITCP: Stream<Item = Result<TokioTCP, ETCP>> + Unpin,
120 >(
121 self,
122 tcp_incoming: TokioITCP,
123 alpn_protocols: Vec<Vec<u8>>,
124 ) -> crate::tokio::TokioIncoming<
125 tokio_util::compat::Compat<TokioTCP>,
126 ETCP,
127 crate::tokio::TokioIncomingTcpWrapper<TokioTCP, ETCP, TokioITCP>,
128 EC,
129 EA,
130 > {
131 let tcp_incoming = crate::tokio::TokioIncomingTcpWrapper::from(tcp_incoming);
132 crate::tokio::TokioIncoming::from(self.incoming(tcp_incoming, alpn_protocols))
133 }
134 #[cfg(feature = "axum")]
135 pub fn axum_acceptor(&self, rustls_config: Arc<ServerConfig>) -> crate::axum::AxumAcceptor {
136 #[allow(deprecated)]
137 crate::axum::AxumAcceptor::new(self.acceptor(), rustls_config)
138 }
139
140 #[cfg(feature = "tower")]
141 pub fn http01_challenge_tower_service(&self) -> crate::tower::TowerHttp01ChallengeService {
142 crate::tower::TowerHttp01ChallengeService(self.resolver.clone())
143 }
144
145 pub fn resolver(&self) -> Arc<ResolvesServerCertAcme> {
146 self.resolver.clone()
147 }
148 #[cfg(any(feature = "ring", feature = "aws-lc-rs"))]
150 pub fn challenge_rustls_config(&self) -> Arc<ServerConfig> {
151 self.challenge_rustls_config_with_provider(crypto_provider().into())
152 }
153 pub fn challenge_rustls_config_with_provider(&self, provider: Arc<CryptoProvider>) -> Arc<ServerConfig> {
155 let mut rustls_config = ServerConfig::builder_with_provider(provider)
156 .with_safe_default_protocol_versions()
157 .unwrap()
158 .with_no_client_auth()
159 .with_cert_resolver(self.resolver());
160 rustls_config.alpn_protocols.push(ACME_TLS_ALPN_NAME.to_vec());
161 Arc::new(rustls_config)
162 }
163 #[cfg(any(feature = "ring", feature = "aws-lc-rs"))]
167 pub fn default_rustls_config(&self) -> Arc<ServerConfig> {
168 self.default_rustls_config_with_provider(crypto_provider().into())
169 }
170 pub fn default_rustls_config_with_provider(&self, provider: Arc<CryptoProvider>) -> Arc<ServerConfig> {
172 let rustls_config = ServerConfig::builder_with_provider(provider)
173 .with_safe_default_protocol_versions()
174 .unwrap()
175 .with_no_client_auth()
176 .with_cert_resolver(self.resolver());
177 Arc::new(rustls_config)
178 }
179 pub fn new(config: AcmeConfig<EC, EA>) -> Self {
180 let config = Arc::new(config);
181 Self {
182 config: config.clone(),
183 resolver: ResolvesServerCertAcme::new(),
184 account_key: None,
185 early_action: None,
186 load_cert: Some(Box::pin({
187 let config = config.clone();
188 async move { config.cache.load_cert(&config.domains, &config.directory_url).await }
189 })),
190 load_account: Some(Box::pin({
191 let config = config.clone();
192 async move { config.cache.load_account(&config.contact, &config.directory_url).await }
193 })),
194 order: None,
195 backoff_cnt: 0,
196 wait: None,
197 }
198 }
199 fn parse_cert(pem: &[u8]) -> Result<(CertifiedKey, [DateTime<Utc>; 2]), CertParseError> {
200 let mut pems = pem::parse_many(pem)?;
201 if pems.len() < 2 {
202 return Err(CertParseError::TooFewPem(pems.len()));
203 }
204 let pk = match any_ecdsa_type(&PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(pems.remove(0).contents()))) {
205 Ok(pk) => pk,
206 Err(_) => return Err(CertParseError::InvalidPrivateKey),
207 };
208 let cert_chain: Vec<RustlsCertificate> = pems.into_iter().map(|p| RustlsCertificate::from(p.into_contents())).collect();
209 let validity = match parse_x509_certificate(&cert_chain[0]) {
210 Ok((_, cert)) => {
211 let validity = cert.validity();
212 [validity.not_before, validity.not_after].map(|t| Utc.timestamp_opt(t.timestamp(), 0).earliest().unwrap())
213 }
214 Err(err) => return Err(CertParseError::X509(err)),
215 };
216 let cert = CertifiedKey::new(cert_chain, pk);
217 Ok((cert, validity))
218 }
219
220 #[allow(clippy::result_large_err)]
221 fn process_cert(&mut self, pem: Vec<u8>, cached: bool) -> Event<EC, EA> {
222 let (cert, validity) = match (Self::parse_cert(&pem), cached) {
223 (Ok(r), _) => r,
224 (Err(err), cached) => {
225 return match cached {
226 true => Err(EventError::CachedCertParse(err)),
227 false => Err(EventError::NewCertParse(err)),
228 }
229 }
230 };
231 self.resolver.set_cert(Arc::new(cert));
232 let wait_duration = (validity[1] - (validity[1] - validity[0]) / 3 - Utc::now())
233 .max(chrono::Duration::zero())
234 .to_std()
235 .unwrap_or_default();
236 self.wait = Some(Timer::after(wait_duration));
237 if cached {
238 return Ok(EventOk::DeployedCachedCert);
239 }
240 let config = self.config.clone();
241 self.early_action = Some(Box::pin(async move {
242 match config.cache.store_cert(&config.domains, &config.directory_url, &pem).await {
243 Ok(()) => Ok(EventOk::CertCacheStore),
244 Err(err) => Err(EventError::CertCacheStore(err)),
245 }
246 }));
247 Event::Ok(EventOk::DeployedNewCert)
248 }
249 async fn order(config: Arc<AcmeConfig<EC, EA>>, resolver: Arc<ResolvesServerCertAcme>, key_pair: Vec<u8>) -> Result<Vec<u8>, OrderError> {
250 let directory = Directory::discover(&config.client_config, &config.directory_url).await?;
251 let account = Account::create_with_keypair(&config.client_config, directory, &config.contact, &key_pair).await?;
252
253 let mut params = CertificateParams::new(config.domains.clone())?;
254 params.distinguished_name = DistinguishedName::new();
255 let key_pair = KeyPair::generate_for(&PKCS_ECDSA_P256_SHA256)?;
256 let csr = params.serialize_request(&key_pair)?;
257
258 let (order_url, mut order) = account.new_order(&config.client_config, config.domains.clone()).await?;
259 loop {
260 match order.status {
261 OrderStatus::Pending => {
262 for url in order.authorizations.iter() {
264 Self::authorize(&config, &resolver, &account, url).await?
265 }
266 log::info!("completed all authorizations");
267 order = account.order(&config.client_config, &order_url).await?;
268 }
269 OrderStatus::Processing => {
270 for i in 0u64..10 {
271 log::info!("order processing");
272 Timer::after(Duration::from_secs(1u64 << i)).await;
273 order = account.order(&config.client_config, &order_url).await?;
274 if order.status != OrderStatus::Processing {
275 break;
276 }
277 }
278 if order.status == OrderStatus::Processing {
279 return Err(OrderError::ProcessingTimeout(order));
280 }
281 }
282 OrderStatus::Ready => {
283 log::info!("sending csr");
284 order = account.finalize(&config.client_config, order.finalize, csr.der()).await?
285 }
286 OrderStatus::Valid { certificate } => {
287 log::info!("download certificate");
288 let pem = [
289 &key_pair.serialize_pem(),
290 "\n",
291 &account.certificate(&config.client_config, certificate).await?,
292 ]
293 .concat();
294 return Ok(pem.into_bytes());
295 }
296 OrderStatus::Invalid => return Err(OrderError::BadOrder(order)),
297 }
298 }
299 }
300 async fn authorize(config: &AcmeConfig<EC, EA>, resolver: &ResolvesServerCertAcme, account: &Account, url: &String) -> Result<(), OrderError> {
301 let auth = account.auth(&config.client_config, url).await?;
302 let (domain, challenge_url) = match auth.status {
303 AuthStatus::Pending => {
304 let Identifier::Dns(domain) = auth.identifier;
305 log::info!("trigger challenge for {}", &domain);
306 let challenge = match config.challenge_type {
307 UseChallenge::Http01 => {
308 let (challenge, key_auth) = account.http_01(&auth.challenges)?;
309 resolver.set_http_01_challenge_data(challenge.token.clone(), key_auth);
310 challenge
311 }
312 UseChallenge::TlsAlpn01 => {
313 let (challenge, auth_key) = account.tls_alpn_01(&auth.challenges, domain.clone())?;
314 resolver.set_tls_alpn_01_challenge_data(domain.clone(), Arc::new(auth_key));
315 challenge
316 }
317 };
318 account.challenge(&config.client_config, &challenge.url).await?;
319 (domain, challenge.url.clone())
320 }
321 AuthStatus::Valid => {
322 resolver.clear_challenge_data();
324 return Ok(());
325 }
326 _ => {
327 resolver.clear_challenge_data();
329 return Err(OrderError::BadAuth(auth));
330 }
331 };
332 for i in 0u64..5 {
333 Timer::after(Duration::from_secs(1u64 << i)).await;
334 let auth = account.auth(&config.client_config, url).await?;
335 match auth.status {
336 AuthStatus::Pending => {
337 log::info!("authorization for {} still pending", &domain);
338 account.challenge(&config.client_config, &challenge_url).await?
339 }
340 AuthStatus::Valid => {
341 resolver.clear_challenge_data();
343 return Ok(());
344 }
345 _ => {
346 resolver.clear_challenge_data();
348 return Err(OrderError::BadAuth(auth));
349 }
350 }
351 }
352 Err(OrderError::TooManyAttemptsAuth(domain))
353 }
354 fn poll_next_infinite(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Event<EC, EA>> {
355 loop {
356 if let Some(early_action) = &mut self.early_action {
358 let result = ready!(early_action.poll_unpin(cx));
359 self.early_action.take();
360 return Poll::Ready(result);
361 }
362
363 if let Some(timer) = &mut self.wait {
365 ready!(timer.poll_unpin(cx));
366 self.wait.take();
367 }
368
369 if let Some(load_cert) = &mut self.load_cert {
371 let result = ready!(load_cert.poll_unpin(cx));
372 self.load_cert.take();
373 match result {
374 Ok(Some(pem)) => {
375 return Poll::Ready(Self::process_cert(self.get_mut(), pem, true));
376 }
377 Ok(None) => {}
378 Err(err) => return Poll::Ready(Err(EventError::CertCacheLoad(err))),
379 }
380 }
381
382 if let Some(load_account) = &mut self.load_account {
384 let result = ready!(load_account.poll_unpin(cx));
385 self.load_account.take();
386 match result {
387 Ok(Some(key_pair)) => self.account_key = Some(key_pair),
388 Ok(None) => {}
389 Err(err) => return Poll::Ready(Err(EventError::AccountCacheLoad(err))),
390 }
391 }
392
393 if let Some(order) = &mut self.order {
395 let result = ready!(order.poll_unpin(cx));
396 self.order.take();
397 match result {
398 Ok(pem) => {
399 self.backoff_cnt = 0;
400 return Poll::Ready(Self::process_cert(self.get_mut(), pem, false));
401 }
402 Err(err) => {
403 self.wait = Some(Timer::after(Duration::from_secs(1 << self.backoff_cnt)));
405 self.backoff_cnt = (self.backoff_cnt + 1).min(16);
406 return Poll::Ready(Err(EventError::Order(err)));
407 }
408 }
409 }
410
411 let account_key = match &self.account_key {
413 None => {
414 let account_key = Account::generate_key_pair();
415 self.account_key = Some(account_key.clone());
416 let config = self.config.clone();
417 let account_key_clone = account_key.clone();
418 self.early_action = Some(Box::pin(async move {
419 match config
420 .cache
421 .store_account(&config.contact, &config.directory_url, &account_key_clone)
422 .await
423 {
424 Ok(()) => Ok(EventOk::AccountCacheStore),
425 Err(err) => Err(EventError::AccountCacheStore(err)),
426 }
427 }));
428 account_key
429 }
430 Some(account_key) => account_key.clone(),
431 };
432 let config = self.config.clone();
433 let resolver = self.resolver.clone();
434 self.order = Some(Box::pin(Self::order(config.clone(), resolver.clone(), account_key)));
435 }
436 }
437}
438
439impl<EC: 'static + Debug, EA: 'static + Debug> Stream for AcmeState<EC, EA> {
440 type Item = Event<EC, EA>;
441
442 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
443 Poll::Ready(Some(ready!(self.poll_next_infinite(cx))))
444 }
445}