ndilieto / uacme

ACMEv2 client written in plain C with minimal dependencies
GNU General Public License v3.0
423 stars 36 forks source link

ZeroSSL keeps returning status:invalid for one out of two authorization request. Expects a retry? #78

Closed moll closed 5 months ago

moll commented 5 months ago

Hey,

Thanks for maintaining uacme! I'm not sure who's issue this is, but I thought I'd start with uacme as you're probably more knowledgeable of the related specs than a random customer service rep from ZeroSSL.

I'm trying to to refresh a certificate with ZeroSSL that has two names --- the root and a wilcard --- example.com,*.example.com. Due to some configuration issue, the authorization was cut short yesterday. That is, only a single auth request succeeded -- for the root example.com. Since then, however, it seems ZeroSSL reuses the authorizations/challenges and considers one out of the two constantly valid and the other invalid.

In other words, the initialization returns two auths:

{
    "status": "pending",
    "expires": "2024-05-04T22:26:35Z",
    "identifiers": [
        {
            "type": "dns",
            "value": "example.com"
        },
        {
            "type": "dns",
            "value": "*.example.com"
        }
    ],
    "authorizations": [
        "https://acme.zerossl.com/v2/DV90/authz/ABC",
        "https://acme.zerossl.com/v2/DV90/authz/XYZ"
    ],
    "finalize": "https://acme.zerossl.com/v2/DV90/order/FOO/finalize"
}

The first constantly returns valid. I presume they remember that yesterday this succeeded:

{
    "identifier": {
        "type": "dns",
        "value": "example.com"
    },
    "status": "valid",
    "expires": "2024-03-05T22:26:35Z",
    "challenges": [
        {
            "type": "dns-01",
            "url": "https://acme.zerossl.com/v2/DV90/chall/XXX",
            "status": "valid",
            "validated": "2024-02-04T22:26:39Z",
            "token": "SNAFU"
        }
    ]
}

The other, the wildcard auth, constantly returns invalid:

{
    "identifier": {
        "type": "dns",
        "value": "example.com"
    },
    "status": "invalid",
    "expires": "2024-03-05T22:26:35Z",
    "challenges": [
        {
            "type": "dns-01",
            "url": "https://acme.zerossl.com/v2/DV90/chall/YYY",
            "status": "invalid",
            "error": {
            },
            "token": "SNAFU"
        }
    ],
    "wildcard": true
}

While I'm not familiar with the ACME protocol, it seems to be ZeroSSL presumes the second challenge should still be used, even though it's currently with an invalid status. Uacme, though, bails out after not seeing pending there and presumes that once the status flips to invalid, it'll never switch to valid.

So, any idea who's bug this is?

Thanks!

moll commented 5 months ago

I've now skimmed the ACME spec and I'm beginning to suspect it might be an issue on ZeroSSL's side. I notified them via their online contact form and wrote the following:

Hey,

Thanks for providing the ACME service for free!

So, it seems to me that ZeroSSL is returning cached authorizations for new orders, even if those authorizations and challenges were deemed "invalid". From reading the ACME spec (https://datatracker.ietf.org/doc/html/rfc8555#section-8), the "invalid" state of a challenge and authorization is terminal. That is, the server won't retry further and client must fail the order. This results in the whole certificate process getting stuck as one of the challenges is forever invalid.

I've pasted the server responses on https://github.com/ndilieto/uacme/issues/78. At that time I was unsure who's issue this is, but reading the ACME spec hints that it might an issue on ZeroSSL side.

Cheers!

ndilieto commented 5 months ago

As you figured out by yourself, uacme is just following RFC8555 to the letter in this case and the problem is with ZeroSSL.