Skip to content

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

@Ajadaz

Description

@Ajadaz

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.

acme.sh/acme.sh

Lines 4693 to 4718 in afacdfc

entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
_debug entry "$entry"
if [ -z "$keyauthorization" -a -z "$entry" ]; then
_err "Error, can not get domain token entry $d for $vtype"
_supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')"
if [ "$_supported_vtypes" ]; then
_err "The supported validation types are: $_supported_vtypes, but you specified: $vtype"
fi
_clearup
_on_issue_err "$_post_hook"
return 1
fi
if [ -z "$keyauthorization" ]; then
token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
_debug token "$token"
if [ -z "$token" ]; then
_err "Error, can not get domain token $entry"
_clearup
_on_issue_err "$_post_hook"
return 1
fi
uri="$(echo "$entry" | _egrep_o '"url":"[^"]*' | cut -d '"' -f 4 | _head_n 1)"

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions