acmesh-official / acme.sh

A pure Unix shell script implementing ACME client protocol
https://acme.sh
GNU General Public License v3.0
39.33k stars 4.97k forks source link

Challenge entry not properly extracted if errors are present when issuing certificates #4933

Open Ajadaz opened 10 months ago

Ajadaz commented 10 months ago

I tried to issue a new certificate today, but I messed up my nginx config so the issuing failed initially. Subsequent attempts also failed, but after staring at the debug log a bit, it seemed to me that it was an issue with acme.sh.

The debug log makes the issue pretty clear.

[Wed Dec 27 10:49:00 UTC 2023] _idn_temp
[Wed Dec 27 10:49:00 UTC 2023] _candidates='cloud.arborusgroup.com,{"identifier":{"type":"dns","value":"example.com"},"status":"invalid","expires":"2024-01-26T09:37:10Z","challenges":[{"type":"http-01","url":"https://acme.zerossl.com/v2/DV90/chall/X_zibH7gBsX9FDpNLsKPvw","status":"invalid","error":{},"token":"O4-YzxyoyvzhVw54KSGFCIZSXyvG2RW_B_rKOshx5CE"}]}#https://acme.zerossl.com/v2/DV90/authz/h60LmUF30XYAqWDFop_azg'
[Wed Dec 27 10:49:00 UTC 2023] response='{"identifier":{"type":"dns","value":"example.com"},"status":"invalid","expires":"2024-01-26T09:37:10Z","challenges":[{"type":"http-01","url":"https://acme.zerossl.com/v2/DV90/chall/X_zibH7gBsX9FDpNLsKPvw","status":"invalid","error":{},"token":"O4-YzxyoyvzhVw54KSGFCIZSXyvG2RW_B_rKOshx5CE"}]}#https://acme.zerossl.com/v2/DV90/authz/h60LmUF30XYAqWDFop_azg'
[Wed Dec 27 10:49:00 UTC 2023] _authz_url='https://acme.zerossl.com/v2/DV90/authz/h60LmUF30XYAqWDFop_azg'
[Wed Dec 27 10:49:00 UTC 2023] entry='"type":"http-01","url":"https://acme.zerossl.com/v2/DV90/chall/X_zibH7gBsX9FDpNLsKPvw","status":"invalid","error":{'
[Wed Dec 27 10:49:00 UTC 2023] token
[Wed Dec 27 10:49:00 UTC 2023] Error, can not get domain token "type":"http-01","url":"https://acme.zerossl.com/v2/DV90/chall/X_zibH7gBsX9FDpNLsKPvw","status":"invalid","error":{

The extracted variable entry from response is not correct. It gets cut off right on the closing brace of the error:{ JSON object.

https://github.com/acmesh-official/acme.sh/blob/afacdfcb95e063325d8f01ebc8daa57322307d92/acme.sh#L4693-L4718

The problem is that the regex _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*' can not properly handle the error objects, because it starts looking for the first closing } after finding the type of challenge that was requested. This is problematic when the challenge entry itself contains an object which, of course, needs to be terminated with a } leading to this unintended behavior.

I would have submitted a PR to fix this, but I just could not figure out a good way to extract the entry with regex when the error object can be arbitrarily complex.

The error can be arbitrarily complex, because the ACME RFC specifies:

error (optional, object): Error that occurred while the server was validating the challenge, if any, structured as a problem document [RFC7807]. Multiple errors can be indicated by using subproblems Section 6.7.1. A challenge object with an error MUST have status equal to "invalid".

And Section 6.7.1 gives a good example of a possible arbitrarily complex error object

{
    "type": "urn:ietf:params:acme:error:malformed",
    "detail": "Some of the identifiers requested were rejected",
    "subproblems": [
        {
            "type": "urn:ietf:params:acme:error:malformed",
            "detail": "Invalid underscore in DNS name \"_example.org\"",
            "identifier": {
                "type": "dns",
                "value": "_example.org"
            }
        },
        {
            "type": "urn:ietf:params:acme:error:rejectedIdentifier",
            "detail": "This CA will not issue for \"example.net\"",
            "identifier": {
                "type": "dns",
                "value": "example.net"
            }
        }
    ]
}

If anyone has a good idea for how to deal with these error objects that would fit into the codebase, I'd be happy to write it out and submit a PR.

github-actions[bot] commented 10 months ago

Please upgrade to the latest code and try again first. Maybe it's already fixed. acme.sh --upgrade If it's still not working, please provide the log with --debug 2, otherwise, nobody can help you.

cybercxo commented 10 months ago

Also seeing this, exactly as posted.

I inserted this directly above 4693 as a work around...

  response="$(echo "$response" | sed s/'"error":{}'/'"error":null'/)"