aboutsummaryrefslogtreecommitdiffstats
path: root/debian/patches/client-Handle-ready-processing-valid-status-change-during.patch
blob: daeffad64c88d00952f22e51be61e6f899304f0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
From: Guilhem Moulin <guilhem@fripost.org>
Date: Tue, 25 Apr 2023 10:51:36 +0200
Subject: =?utf-8?q?client=3A_Handle_=22ready=22_=E2=86=92_=22processing=22_?=
 =?utf-8?q?=E2=86=92_=22valid=22_status_change_during_newOrder=2E?=
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

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!

Bug-Debian: https://bugs.debian.org/1034834
---
 client | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/client b/client
index fdef865..4d4d129 100755
--- a/client
+++ b/client
@@ -351,11 +351,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};
@@ -366,19 +367,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";
         }