[pbs-devel] [PATCH proxmox 1/1] fix #6939: acme: support servers returning 204 for nonce requests

Christian Ebner c.ebner at proxmox.com
Wed Oct 29 08:23:05 CET 2025


Hi, thanks for the patches!

comments inline

On 10/28/25 8:34 PM, Samuel Rufinatscha wrote:
> Some ACME servers (notably custom or legacy implementations) respond
> to HEAD /newNonce with a 204 No Content instead of the
> RFC 8555-recommended 200 OK [1]. While this behavior is technically
> off-spec, it is functionally harmless. This issue was reported on our
> bug tracker [2].
> 
> The previous implementation treated any non-200 response as an error,
> causing account registration to fail against such servers. Relax the
> status-code check to accept both 200 and 204 responses (and potentially
> support other 2xx codes) to improve interoperability.
> 
> This aligns behavior with PVE’s more tolerant Perl ACME client and
> avoids regressions.
> 
> [1] https://datatracker.ietf.org/doc/html/rfc8555/#section-7.2
> [2] https://bugzilla.proxmox.com/show_bug.cgi?id=6939
> 
> Fixes: #6939
> Signed-off-by: Samuel Rufinatscha <s.rufinatscha at proxmox.com>
> ---
>   proxmox-acme/src/account.rs      | 10 +++++-----
>   proxmox-acme/src/async_client.rs |  6 +++---
>   proxmox-acme/src/client.rs       |  2 +-
>   proxmox-acme/src/request.rs      |  4 ++--
>   4 files changed, 11 insertions(+), 11 deletions(-)
> 
> diff --git a/proxmox-acme/src/account.rs b/proxmox-acme/src/account.rs
> index 73d786b8..60719865 100644
> --- a/proxmox-acme/src/account.rs
> +++ b/proxmox-acme/src/account.rs
> @@ -85,7 +85,7 @@ impl Account {
>               method: "POST",
>               content_type: crate::request::JSON_CONTENT_TYPE,
>               body,
> -            expected: crate::request::CREATED,
> +            expected: vec![crate::request::CREATED],

while this is defined as dedicated constant...

>           };
>   
>           Ok(NewOrder::new(request))
> @@ -107,7 +107,7 @@ impl Account {
>               method: "POST",
>               content_type: crate::request::JSON_CONTENT_TYPE,
>               body,
> -            expected: 200,
> +            expected: vec![200],

... these and the others below are not. Same for the 204 status code you 
are about to add.

So in preparation for adding the new status code, these should probably 
be defined as, either:
- as dedicated status code constants as well, or
- all moved over to directly use 
https://docs.rs/http/1.3.1/http/status/struct.StatusCode.html

I feel like the latter is not done here intentionally to avoid the 
dependency on hyper or http (re-exported by hyper) for the api types only.

@wolfgang, comments on that?

>           })
>       }
>   
> @@ -132,7 +132,7 @@ impl Account {
>               method: "POST",
>               content_type: crate::request::JSON_CONTENT_TYPE,
>               body,
> -            expected: 200,
> +            expected: vec![200],
>           })
>       }
>   
> @@ -157,7 +157,7 @@ impl Account {
>               method: "POST",
>               content_type: crate::request::JSON_CONTENT_TYPE,
>               body,
> -            expected: 200,
> +            expected: vec![200],
>           })
>       }
>   
> @@ -405,7 +405,7 @@ impl AccountCreator {
>               method: "POST",
>               content_type: crate::request::JSON_CONTENT_TYPE,
>               body,
> -            expected: crate::request::CREATED,
> +            expected: vec![crate::request::CREATED],
>           })
>       }
>   
> diff --git a/proxmox-acme/src/async_client.rs b/proxmox-acme/src/async_client.rs
> index 60e1f359..0901aa8d 100644
> --- a/proxmox-acme/src/async_client.rs
> +++ b/proxmox-acme/src/async_client.rs
> @@ -421,7 +421,7 @@ impl AcmeClient {
>           };
>   
>           if parts.status.is_success() {
> -            if status != request.expected {
> +            if !request.expected.contains(&status) {
>                   return Err(Error::InvalidApi(format!(
>                       "ACME server responded with unexpected status code: {:?}",
>                       parts.status
> @@ -501,7 +501,7 @@ impl AcmeClient {
>                   method: "GET",
>                   content_type: "",
>                   body: String::new(),
> -                expected: 200,
> +                expected: vec![200],
>               },
>               nonce,
>           )
> @@ -553,7 +553,7 @@ impl AcmeClient {
>                   method: "HEAD",
>                   content_type: "",
>                   body: String::new(),
> -                expected: 200,
> +                expected: vec![200, 204],
>               },
>               nonce,
>           )
> diff --git a/proxmox-acme/src/client.rs b/proxmox-acme/src/client.rs
> index d8a62081..ea8a8655 100644
> --- a/proxmox-acme/src/client.rs
> +++ b/proxmox-acme/src/client.rs
> @@ -203,7 +203,7 @@ impl Inner {
>           let got_nonce = self.update_nonce(&mut response)?;
>   
>           if response.is_success() {
> -            if response.status != request.expected {
> +            if !request.expected.contains(&response.status) {
>                   return Err(Error::InvalidApi(format!(
>                       "API server responded with unexpected status code: {:?}",
>                       response.status
> diff --git a/proxmox-acme/src/request.rs b/proxmox-acme/src/request.rs
> index 78a90913..38e825d6 100644
> --- a/proxmox-acme/src/request.rs
> +++ b/proxmox-acme/src/request.rs
> @@ -17,8 +17,8 @@ pub struct Request {
>       /// The body to pass along with request, or an empty string.
>       pub body: String,
>   
> -    /// The expected status code a compliant ACME provider will return on success.
> -    pub expected: u16,
> +    /// The set of HTTP status codes that indicate a successful response from an ACME provider.
> +    pub expected: Vec<u16>,
>   }
>   
>   /// An ACME error response contains a specially formatted type string, and can optionally





More information about the pbs-devel mailing list