aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@debian.org>2024-06-13 18:43:06 +0200
committerGuilhem Moulin <guilhem@fripost.org>2024-06-13 19:18:49 +0200
commitedb498097d7fd4d52c4f49c164776f7b15e59703 (patch)
tree2ddf897b625fce006af7bca5626eb7189a109570
parent3307551410bb24d41fa947701e7b3a031f29fb69 (diff)
Backport upstream patches to fix fix post-issuance validation logic.
As well as the upstream test suite. Closes: #1072847
-rw-r--r--debian/patches/Adjust-test-suite-against-current-Let-s-Encrypt-staging-e.patch183
-rw-r--r--debian/patches/Fix-post-issuance-validation-logic.patch174
-rw-r--r--debian/patches/series2
3 files changed, 359 insertions, 0 deletions
diff --git a/debian/patches/Adjust-test-suite-against-current-Let-s-Encrypt-staging-e.patch b/debian/patches/Adjust-test-suite-against-current-Let-s-Encrypt-staging-e.patch
new file mode 100644
index 0000000..063217a
--- /dev/null
+++ b/debian/patches/Adjust-test-suite-against-current-Let-s-Encrypt-staging-e.patch
@@ -0,0 +1,183 @@
+From: Guilhem Moulin <guilhem@fripost.org>
+Date: Thu, 13 Jun 2024 15:54:11 +0200
+Subject: Adjust test suite against current Let's Encrypt staging environment
+
+Origin: https://git.guilhem.org/lacme/commit/?id=cb0b301e7a62a71d9e4454f9f7af5358c857c48c
+Origin: https://git.guilhem.org/lacme/commit/?id=f84716c064312dd9dc0d149f0ec7a12f5c88c3af
+Origin: https://git.guilhem.org/lacme/commit/?id=a41444b8b1fe5349a4a33c45f1e96036845609bb
+Origin: https://git.guilhem.org/lacme/commit/?id=98e4397f5330245cb7f8a21054ab078c4d0bba82
+---
+ tests/account-encrypted-gpg | 2 +-
+ tests/account-encrypted-openssl | 1 +
+ tests/accountd | 1 +
+ tests/accountd-kid | 4 +++-
+ tests/cert-install | 2 +-
+ tests/cert-revoke | 4 ++--
+ tests/cert-verify | 20 ++++----------------
+ tests/old-accountd | 1 +
+ tests/old-lacme | 1 +
+ 9 files changed, 15 insertions(+), 21 deletions(-)
+
+diff --git a/tests/account-encrypted-gpg b/tests/account-encrypted-gpg
+index fd1e4ac..7cb978d 100644
+--- a/tests/account-encrypted-gpg
++++ b/tests/account-encrypted-gpg
+@@ -9,7 +9,7 @@ keyid="$(gpg --list-secret-key --with-colons | grep -m1 ^fpr: | cut -sd: -f10)"
+ gpg --encrypt -r "$keyid" /etc/lacme/account.key
+ sed -ri '0,\|^#?privkey\s*=.*| {s||privkey = gpg:/etc/lacme/account.key.gpg|}' /etc/lacme/lacme-accountd.conf
+
+-export GPG_TTY="$(tty)"
++export GPG_TTY="$(tty)" TERM="linux"
+ lacme account
+
+ # vim: set filetype=sh :
+diff --git a/tests/account-encrypted-openssl b/tests/account-encrypted-openssl
+index e79a528..a3ad707 100644
+--- a/tests/account-encrypted-openssl
++++ b/tests/account-encrypted-openssl
+@@ -5,6 +5,7 @@ PASSPHRASE="test"
+ openssl rsa -aes128 -passout pass:"$PASSPHRASE" </etc/lacme/account.key >/etc/lacme/account.enc.key
+ sed -ri '0,\|^#?privkey\s*=.*| {s||privkey = file:/etc/lacme/account.enc.key|}' /etc/lacme/lacme-accountd.conf
+
++export TERM="linux"
+ lacme account
+
+ # vim: set filetype=sh :
+diff --git a/tests/accountd b/tests/accountd
+index a603c16..d204b9c 100644
+--- a/tests/accountd
++++ b/tests/accountd
+@@ -65,6 +65,7 @@ grep -F "Error: " ~lacme-account/.local/share/lacme/accountd.log
+ # rotate the log and start accountd
+ rm -f ~lacme-account/.local/share/lacme/accountd.log
+ runuser -u lacme-account -- lacme-accountd --socket="$SOCKET" --quiet & PID=$!
++sleep 1
+
+ # run lacme(8) multiple times using that single lacme-accountd(1) instance
+ lacme --socket="$SOCKET" --debug account 2>"$STDERR" || fail
+diff --git a/tests/accountd-kid b/tests/accountd-kid
+index e1bd63d..28f1c3c 100644
+--- a/tests/accountd-kid
++++ b/tests/accountd-kid
+@@ -23,6 +23,7 @@ EOF
+
+ SOCKET=~lacme-account/S.lacme
+ runuser -u lacme-account -- lacme-accountd --socket="$SOCKET" --quiet & PID=$!
++sleep 1
+
+ # newAccount resource fails as per RFC 8555 sec. 6.2 it requires a JWK
+ ! lacme --socket="$SOCKET" account 2>"$STDERR" || fail
+@@ -37,6 +38,7 @@ wait
+
+ rm ~lacme-account/.local/share/lacme/accountd.log
+ runuser -u lacme-account -- lacme-accountd --socket="$SOCKET" --quiet & PID=$!
++sleep 1
+
+ # newOrder works fine without JWK
+ lacme --socket="$SOCKET" newOrder
+@@ -46,7 +48,7 @@ test /etc/lacme/simpletest.rsa.crt -nt /etc/lacme/simpletest.rsa.key
+ lacme --socket="$SOCKET" revokeCert /etc/lacme/simpletest.rsa.crt
+ ! lacme --socket="$SOCKET" revokeCert /etc/lacme/simpletest.rsa.crt 2>"$STDERR" || fail
+ grepstderr -Fxq "Revoking /etc/lacme/simpletest.rsa.crt"
+-grepstderr -Fxq "400 Bad Request (Certificate already revoked)"
++grepstderr -Fq "400 Bad Request (unable to revoke"
+ grepstderr -Fxq "Warning: Couldn't revoke /etc/lacme/simpletest.rsa.crt"
+
+ kill $PID
+diff --git a/tests/cert-install b/tests/cert-install
+index 69faae4..dfb882a 100644
+--- a/tests/cert-install
++++ b/tests/cert-install
+@@ -79,7 +79,7 @@ check_chain() {
+
+ # 'certificate' installs only the leaf certificate
+ openssl genpkey -algorithm RSA -out /etc/lacme/test1.key
+-subject="/CN=$(head -c10 /dev/urandom | base32 -w0).$DOMAINNAME"
++subject="/CN=$(head -c10 /dev/urandom | base32 -w0 | tr "A-Z" "a-z").$DOMAINNAME"
+ cat >"/etc/lacme/lacme-certs.conf.d/test1.conf" <<- EOF
+ [test1]
+ certificate-key = /etc/lacme/test1.key
+diff --git a/tests/cert-revoke b/tests/cert-revoke
+index f3d585e..179ccba 100644
+--- a/tests/cert-revoke
++++ b/tests/cert-revoke
+@@ -18,7 +18,7 @@ test /etc/lacme/simpletest.ecdsa.crt -nt /etc/lacme/simpletest.ecdsa.key
+ lacme revokeCert /etc/lacme/simpletest.ecdsa.crt
+ ! lacme revokeCert /etc/lacme/simpletest.ecdsa.crt 2>"$STDERR" || fail
+ grepstderr -Fxq "Revoking /etc/lacme/simpletest.ecdsa.crt"
+-grepstderr -Fxq "400 Bad Request (Certificate already revoked)"
++grepstderr -Fq "400 Bad Request (unable to revoke"
+ grepstderr -Fxq "Warning: Couldn't revoke /etc/lacme/simpletest.ecdsa.crt"
+
+ # and the RSA certificate using the service key
+@@ -26,7 +26,7 @@ mv -vfT /etc/lacme/simpletest.rsa.key /etc/lacme/account.key
+ lacme revokeCert /etc/lacme/simpletest.rsa.crt
+ ! lacme revokeCert /etc/lacme/simpletest.rsa.crt 2>"$STDERR" || fail
+ grepstderr -Fxq "Revoking /etc/lacme/simpletest.rsa.crt"
+-grepstderr -Fxq "400 Bad Request (Certificate already revoked)"
++grepstderr -Fq "400 Bad Request (unable to revoke"
+ grepstderr -Fxq "Warning: Couldn't revoke /etc/lacme/simpletest.rsa.crt"
+
+ # vim: set filetype=sh :
+diff --git a/tests/cert-verify b/tests/cert-verify
+index 49629f2..7d27c98 100644
+--- a/tests/cert-verify
++++ b/tests/cert-verify
+@@ -8,9 +8,9 @@ for ca in /usr/share/lacme/letsencrypt-stg-root-*.pem; do
+ done
+ update-ca-certificates
+
+-# test (modified) trust store for intermediate certificates
+-openssl verify -no-CAfile -CApath /etc/ssl/certs -show_chain /usr/share/lacme/letsencrypt-stg-int-*.pem
+-openssl verify -no-CApath -CAfile /etc/ssl/certs/ca-certificates.crt -show_chain /usr/share/lacme/letsencrypt-stg-int-*.pem
++# test (modified) trust store
++openssl verify -no-CAfile -CApath /etc/ssl/certs -show_chain /usr/share/lacme/letsencrypt-stg-root-x1.pem
++openssl verify -no-CApath -CAfile /etc/ssl/certs/ca-certificates.crt -show_chain /usr/share/lacme/letsencrypt-stg-root-x1.pem
+
+ mv /usr/share/lacme/ca-certificates.crt /usr/share/lacme/ca-certificates.crt.back
+ ! lacme newOrder 2>"$STDERR" || fail
+@@ -20,19 +20,7 @@ grepstderr -Fxq "[simpletest-rsa] Error: Received invalid X.509 certificate from
+ # verification error for unrelated CA bundle
+ cat /etc/ssl/certs/ssl-cert-snakeoil.pem >/usr/share/lacme/ca-certificates.crt
+ ! lacme newOrder 2>"$STDERR" || fail
+-grepstderr -Fxq "error 20 at 0 depth lookup: unable to get local issuer certificate"
+-grepstderr -Fxq "[simpletest-rsa] Error: Received invalid X.509 certificate from ACME server!"
+-
+-# verification error when the CA bundle contains only the root certificates
+-cat /usr/share/lacme/letsencrypt-stg-root-*.pem >/usr/share/lacme/ca-certificates.crt
+-! lacme newOrder 2>"$STDERR" || fail
+-grepstderr -Fxq "error 20 at 0 depth lookup: unable to get local issuer certificate"
+-grepstderr -Fxq "[simpletest-rsa] Error: Received invalid X.509 certificate from ACME server!"
+-
+-# verification error when the CA bundle contains only the intermediate certificates
+-cat /usr/share/lacme/letsencrypt-stg-int-*.pem >/usr/share/lacme/ca-certificates.crt
+-! lacme newOrder 2>"$STDERR" || fail
+-grepstderr -Fxq "error 2 at 1 depth lookup: unable to get issuer certificate"
++grepstderr -Fxq "error 20 at 1 depth lookup: unable to get local issuer certificate"
+ grepstderr -Fxq "[simpletest-rsa] Error: Received invalid X.509 certificate from ACME server!"
+
+ # use saved bundle as custom CAfile
+diff --git a/tests/old-accountd b/tests/old-accountd
+index b44f7ec..abd330d 100644
+--- a/tests/old-accountd
++++ b/tests/old-accountd
+@@ -21,6 +21,7 @@ DEBIAN_FRONTEND="noninteractive" apt install -y --no-install-recommends \
+
+ SOCKET=~lacme-account/S.lacme
+ runuser -u lacme-account -- lacme-accountd --socket="$SOCKET" & PID=$!
++sleep 1
+ lacme --socket="$SOCKET" account
+ lacme --socket="$SOCKET" newOrder
+
+diff --git a/tests/old-lacme b/tests/old-lacme
+index fa7d827..b1c9f88 100644
+--- a/tests/old-lacme
++++ b/tests/old-lacme
+@@ -26,6 +26,7 @@ mv -f /usr/share/lacme/ca-certificates.crt.back /usr/share/lacme/ca-certificates
+
+ SOCKET=~lacme-account/S.lacme
+ runuser -u lacme-account -- lacme-accountd --socket="$SOCKET" & PID=$!
++sleep 1
+ sed -ri "s/^\[accountd]$/#&/" /etc/lacme/lacme.conf # https://bugs.debian.org/955767
+ lacme --socket="$SOCKET" account
+ lacme --socket="$SOCKET" newOrder
diff --git a/debian/patches/Fix-post-issuance-validation-logic.patch b/debian/patches/Fix-post-issuance-validation-logic.patch
new file mode 100644
index 0000000..61f8da3
--- /dev/null
+++ b/debian/patches/Fix-post-issuance-validation-logic.patch
@@ -0,0 +1,174 @@
+From: Guilhem Moulin <guilhem@fripost.org>
+Date: Thu, 13 Jun 2024 03:32:04 +0200
+Subject: Fix post-issuance validation logic
+
+Rather than adding intermediates in the certificate bundle we now
+validate the leaf certificate with intermediates as untrusted (used for
+chain building only). Only the root certificates are used as trust
+anchor.
+
+Not pining intermediate certificates anymore is in line with Let's
+Encrypt's latest recommendations:
+
+ Rotating the set of intermediates we issue from helps keep the
+ Internet agile and more secure. It encourages automation and
+ efficiency, and discourages outdated practices like key pinning.
+ “Key Pinning” is a practice in which clients — either ACME clients
+ getting certificates for their site, or apps connecting to their own
+ backend servers — decide to trust only a single issuing intermediate
+ certificate rather than delegating trust to the system trust store.
+ Updating pinned keys is a manual process, which leads to an
+ increased risk of errors and potential business continuity failures.
+ — https://letsencrypt.org/2024/03/19/new-intermediate-certificates:
+
+Origin: https://git.guilhem.org/lacme/commit/?id=9cb882a468843bf8ce9598de8769d5baaaaae3ea
+Bug-Debian: https://bugs.debian.org/1072847
+---
+ Makefile | 8 ++-----
+ lacme | 7 +++++-
+ tests/cert-install | 67 ++++++++++++++++++++++++++++++++++++++++++------------
+ 3 files changed, 61 insertions(+), 21 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 16ac04e..523d289 100644
+--- a/Makefile
++++ b/Makefile
+@@ -16,17 +16,13 @@ $(MANUAL_FILES): $(BUILDDIR)/%: $(BUILDDIR)/%.md
+ # used for validation, see https://letsencrypt.org/certificates/
+ $(BUILDDIR)/certs/ca-certificates.crt: \
+ certs/isrgrootx1.pem \
+- certs/isrg-root-x2.pem \
+- certs/lets-encrypt-r[34].pem \
+- certs/lets-encrypt-e[12].pem
++ certs/isrg-root-x2.pem
+ mkdir -pv -- $(dir $@)
+ cat -- $^ >$@
+
+ # Staging Environment for tests, see https://letsencrypt.org/docs/staging-environment/
+ $(BUILDDIR)/certs-staging/ca-certificates.crt: \
+- certs-staging/letsencrypt-stg-root-x[12].pem \
+- certs-staging/letsencrypt-stg-int-r[34].pem \
+- certs-staging/letsencrypt-stg-int-e[12].pem
++ certs-staging/letsencrypt-stg-root-x[12].pem
+ mkdir -pv -- $(dir $@)
+ cat -- $^ >$@
+
+diff --git a/lacme b/lacme
+index 731535f..34f4415 100755
+--- a/lacme
++++ b/lacme
+@@ -826,9 +826,14 @@ elsif ($COMMAND eq 'newOrder' or $COMMAND eq 'new-cert') {
+
+ # verify certificate validity against the CA bundle
+ if ((my $CAfile = $conf->{CAfile} // '@@datadir@@/lacme/ca-certificates.crt') ne '') {
++ my $chain_tmp = File::Temp::->new(SUFFIX => '.crt', TMPDIR => 1) // die;
++ $chain_tmp->printflush($x509);
++
+ my %args = (in => $x509);
+ $args{out} = \*STDERR if $OPTS{debug};
+- my @options = ('-trusted', $CAfile, '-purpose', 'sslserver', '-x509_strict');
++ my @options = ('-trusted', $CAfile);
++ push @options, '-untrusted', $chain_tmp->filename();
++ push @options, ('-purpose', 'sslserver', '-x509_strict');
+ push @options, '-show_chain' if $OPTS{debug};
+ if (spawn(\%args, 'openssl', 'verify', @options)) {
+ print STDERR "[$s] Error: Received invalid X.509 certificate from ACME server!\n";
+diff --git a/tests/cert-install b/tests/cert-install
+index f2147d2..69faae4 100644
+--- a/tests/cert-install
++++ b/tests/cert-install
+@@ -28,6 +28,55 @@ EOF
+ grepstderr -Fxq "[bad3] Warning: Couldn't generate CSR, skipping"
+
+
++check_spki() {
++ local p1="$1" p2="$2" s1 s2
++ s1="$(openssl x509 -in "$p1" -noout -pubkey \
++ | openssl pkey -pubin -outform DER \
++ | openssl dgst -sha256 \
++ | sed 's/.*=\s*//')"
++ s2="$(openssl pkey -in "$p2" -pubout -outform DER \
++ | openssl dgst -sha256 \
++ | sed 's/.*=\s*//')"
++ if [ -n "$s1" ] && [ "$s1" = "$s2" ]; then
++ return 0
++ else
++ printf "%s != %s\\n" "$s1" "$s2" >&2
++ return 1
++ fi
++}
++check_chain() {
++ local priv="$1" chain="$2" leaf="${3-}" pem0
++
++ csplit -f "${chain%.crt}.chain.pem" "$chain" \
++ "/-----BEGIN CERTIFICATE-----/" "{*}"
++
++ pem0="${chain%.crt}.chain.pem00"
++ if [ ! -s "$pem0" ]; then
++ # 00 is empty, leaf cert is at 01
++ rm -f -- "$pem0"
++ pem0="${chain%.crt}.chain.pem01"
++ fi
++ test -s "$pem0" || return 1
++ check_spki "$pem0" "$priv"
++
++ if [ -n "$leaf" ]; then
++ diff --ignore-blank-lines --unified "$pem0" "$leaf" || return 1
++ fi
++
++ leaf="${chain%.crt}.leaf.pem"
++ mv -T -- "$pem0" "$leaf"
++
++ intermediates="${chain%.crt}.intermediates.pem"
++ sed "/^$/d" "${chain%.crt}.chain.pem"[0-9]* >"$intermediates"
++ test -s "$intermediates" || return 1 # ensure there is at least one intermediate
++
++ openssl verify -trusted /usr/share/lacme/ca-certificates.crt \
++ -untrusted "$intermediates" \
++ -purpose sslserver -x509_strict \
++ -show_chain \
++ -- "$leaf" || return 1
++}
++
+ # 'certificate' installs only the leaf certificate
+ openssl genpkey -algorithm RSA -out /etc/lacme/test1.key
+ subject="/CN=$(head -c10 /dev/urandom | base32 -w0).$DOMAINNAME"
+@@ -42,6 +91,7 @@ lacme newOrder test1 2>"$STDERR" || fail newOrder test1
+ test /etc/lacme/test1.crt -nt /etc/lacme/test1.key
+ sed -n "0,/^-----END CERTIFICATE-----$/ p" /etc/lacme/test1.crt >/etc/lacme/test1.pem
+ diff --unified /etc/lacme/test1.crt /etc/lacme/test1.pem
++check_spki /etc/lacme/test1.crt /etc/lacme/test1.key
+
+
+ check_hash() {
+@@ -70,16 +120,7 @@ EOF
+
+ lacme newOrder test2 2>"$STDERR" || fail newOrder test2
+ test /etc/lacme/test2.crt -nt /etc/lacme/test2.key
+-csplit -f /etc/lacme/test2.chain.pem /etc/lacme/test2.crt \
+- "/-----BEGIN CERTIFICATE-----/" "{*}"
+-test -s /etc/lacme/test2.chain.pem01 # leaf cert (00 is empty)
+-rm -f /etc/lacme/test2.chain.pem0[01]
+-test -s /etc/lacme/test2.chain.pem02 # depth 1
+-
+-# all certificates at depth >=1 must be in our CA bundle
+-for p in /etc/lacme/test2.chain.pem*; do
+- check_hash "$p"
+-done
++check_chain /etc/lacme/test2.key /etc/lacme/test2.crt
+
+ # 'certificate' + 'certificate-chain'
+ openssl genpkey -algorithm RSA -out /etc/lacme/test3.key
+@@ -94,10 +135,8 @@ EOF
+ lacme newOrder test3 2>"$STDERR" || fail newOrder test3
+ test /etc/lacme/test3.pem -nt /etc/lacme/test3.key
+ test /etc/lacme/test3.crt -nt /etc/lacme/test3.key
+-csplit -f /etc/lacme/test3.chain.pem /etc/lacme/test3.crt \
+- "/-----BEGIN CERTIFICATE-----/" "{*}"
+-sed -i "/^$/d" /etc/lacme/test3.chain.pem*
+-diff -q /etc/lacme/test3.chain.pem01 /etc/lacme/test3.pem
++check_chain /etc/lacme/test3.key /etc/lacme/test3.crt /etc/lacme/test3.pem
++
+ st="$(stat -c "%U:%G %#a" /etc/lacme/test3.pem)"
+ [ "$st" = "root:root 0644" ]
+ st="$(stat -c "%U:%G %#a" /etc/lacme/test3.crt)"
diff --git a/debian/patches/series b/debian/patches/series
index 70709e0..39a9e28 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1,4 @@
Mention-the-Debian-BTS-in-the-manpages.patch
client-Handle-ready-processing-valid-status-change-during.patch
+Fix-post-issuance-validation-logic.patch
+Adjust-test-suite-against-current-Let-s-Encrypt-staging-e.patch