aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2023-04-25 10:51:36 +0200
committerGuilhem Moulin <guilhem@fripost.org>2023-04-25 11:11:03 +0200
commit53238c70f7a12e233a6ca83cf2b50168e5b9592e (patch)
tree58c0a8613062102f847d761d2c6836f74869075e
parentb3af3526b293f396da02a6276ea86ca17dcd2d03 (diff)
client: Handle "ready" → "processing" → "valid" status change during newOrder.
Instead of just "ready" → "valid", which may be what we observe when the server is fast enough, but according to RFC 8555 sec. 7.1.6 the state actually transitions via "processing" state and we need to account for that. It appears Let's Encrypt staging environment now has different timing conditions and lacme is unable to request certificates due to this issue. Thanks to Alexander Borkowski for the report!
-rwxr-xr-xclient29
1 files changed, 16 insertions, 13 deletions
diff --git a/client b/client
index 3cda821..01c7e5a 100755
--- a/client
+++ b/client
@@ -346,11 +346,12 @@ elsif ($COMMAND eq 'newOrder') {
}
# poll the order URL (to get the status of all challenges at once)
- # until the status become 'valid'
+ # until the status become 'valid'; see RFC 8555 sec. 7.1.6 for the
+ # the status change flow
my $orderstr = join(', ', map {uc($_->{type}) .":". $_->{value}} @identifiers);
my $certuri;
- for (my $i = 0;;) {
- my $r = acme($orderurl);
+ for (my $i = 0, my $url = $orderurl, my $payload;;) {
+ my $r = acme($url => $payload);
my $resp = request_json_decode($r);
if (defined (my $problem = $resp->{error})) { # problem document (RFC 7807)
my $msg = $problem->{status};
@@ -361,19 +362,21 @@ elsif ($COMMAND eq 'newOrder') {
my $status = $resp->{status};
if (!defined $status or $status eq "invalid") {
die "Error: Invalid order $orderstr\n";
- }
- elsif ($status eq "ready") {
- my $r = acme($order->{finalize}, {csr => encode_base64url($csr)});
- my $resp = request_json_decode($r);
- $certuri = $resp->{certificate};
- last;
- }
- elsif ($status eq "valid") {
+ } elsif ($status eq "pending") {
+ # keep retrying
+ } elsif ($status eq "ready") {
+ $url = $order->{finalize};
+ $payload = {csr => encode_base64url($csr)};
+ # retry after moving to "processing" or "valid" state
+ next;
+ } elsif ($status eq "processing") {
+ $url = $orderurl;
+ undef $payload;
+ } elsif ($status eq "valid") {
$certuri = $resp->{certificate} //
die "Error: Missing \"certificate\" field in \"valid\" order\n";
last;
- }
- elsif ($status ne "pending" and $status ne "processing") {
+ } else {
warn "Unknown order status: $status\n";
}