[packages/ca-certificates] Rel 3; sync hashed CApath against a manifest instead of handing /etc/openssl/certs to trust extract

arekm arekm at pld-linux.org
Wed Jul 29 08:06:45 CEST 2026


commit 716ec8ac31f58b25a187089970e99c5472561c3d
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Wed Jul 29 07:16:53 2026 +0200

    Rel 3; sync hashed CApath against a manifest instead of handing /etc/openssl/certs to trust extract

 ca-certificates-p11-kit.patch | 115 +++++++++++++++++++++++++++++++++++++++---
 ca-certificates.spec          |  14 ++++-
 2 files changed, 120 insertions(+), 9 deletions(-)
---
diff --git a/ca-certificates.spec b/ca-certificates.spec
index fad885d..84fe8e0 100644
--- a/ca-certificates.spec
+++ b/ca-certificates.spec
@@ -13,7 +13,7 @@ Summary(pl.UTF-8):	Pliki PEM popularnych certyfikatów CA
 Name:		ca-certificates
 %define	ver_date	20260601
 Version:	%{ver_date}
-Release:	2
+Release:	3
 License:	GPL v2 (scripts), MPL v2 (mozilla certs), distributable (other certs)
 Group:		Base
 Source0:	https://ftp.debian.org/debian/pool/main/c/ca-certificates/%{name}_%{version}.tar.xz
@@ -50,8 +50,11 @@ Patch3:		%{name}-DESTDIR.patch
 Patch4:		%{name}.d.patch
 Patch5:		%{name}-p11-kit.patch
 URL:		https://packages.debian.org/sid/ca-certificates
+Requires:	findutils
+Requires:	grep
 Requires:	mktemp
 Requires:	p11-kit
+Requires:	sed
 BuildRequires:	openssl-tools
 BuildRequires:	python3
 BuildRequires:	python3-cryptography
@@ -210,7 +213,14 @@ rm -rf $RPM_BUILD_ROOT
 %{_sbindir}/update-ca-certificates --fresh || :
 
 %postun
-/usr/bin/find "%{openssldir}" -xtype l -delete || :
+# remove only what update-ca-certificates installed; local admin files stay
+if [ "$1" = "0" ] && [ -f %{openssldir}/.manifest ]; then
+	while IFS= read -r f; do
+		case "$f" in ''|*/*) continue ;; esac
+		rm -f "%{openssldir}/$f"
+	done < %{openssldir}/.manifest
+	rm -f %{openssldir}/.manifest
+fi
 
 %pretrans -p <lua>
 local mode = posix.stat("/etc/ssl/certs")
diff --git a/ca-certificates-p11-kit.patch b/ca-certificates-p11-kit.patch
index de37fbe..0a35021 100644
--- a/ca-certificates-p11-kit.patch
+++ b/ca-certificates-p11-kit.patch
@@ -1,6 +1,15 @@
 --- ca-certificates/sbin/update-ca-certificates.orig
 +++ ca-certificates/sbin/update-ca-certificates
-@@ -104,49 +104,20 @@
+@@ -95,6 +95,8 @@
+   rm -f "$TEMPBUNDLE"
+   rm -f "$ADDED"
+   rm -f "$REMOVED"
++  [ -z "$STAGING" ] || chmod u+w "$STAGING" 2>/dev/null || :
++  rm -rf "$STAGING" "$OURS" "$NEW" "$LIVE"
+ }
+ trap cleanup 0
+ 
+@@ -104,49 +106,20 @@
  ADDED="$(mktemp -p "${TMPDIR:-/tmp}" "ca-certificates.tmp.XXXXXX")"
  REMOVED="$(mktemp -p "${TMPDIR:-/tmp}" "ca-certificates.tmp.XXXXXX")"
  
@@ -54,7 +63,7 @@
  echo "Updating certificates in $ETCCERTSDIR..."
  
  # Add default certificate authorities if requested
-@@ -186,26 +157,6 @@
+@@ -186,26 +159,6 @@
  ADDED_CNT=$(wc -l < "$ADDED")
  REMOVED_CNT=$(wc -l < "$REMOVED")
  
@@ -81,7 +90,7 @@
  # chmod and mv only if TEMPBUNDLE exists or install may fail, #996005
  if [ -f "$TEMPBUNDLE" ]
  then
-@@ -215,6 +166,18 @@
+@@ -215,6 +168,110 @@
    [ -x /sbin/restorecon ] && /sbin/restorecon "$CERTBUNDLE" >/dev/null 2>&1
  fi
  
@@ -89,12 +98,104 @@
 +# p11-kit computes the hashes itself, so ca-certificates stays off the
 +# openssl -> ca-certificates dependency cycle.  Skipped under --destdir
 +# because trust reads the live system trust module, not the buildroot.
++# The extraction goes to a staging directory (trust extract --overwrite
++# unlinks everything in its target it did not write itself) and is synced
++# to ETCCERTSDIR against a manifest of what we installed before, so files
++# the local admin drops here are never deleted.
 +if [ -z "$DESTDIR" ]
 +then
-+  # drop stale symlinks (incl. the legacy openssl-rehash layout) first;
-+  # trust extract leaves foreign symlinks in place otherwise
-+  find "$ETCCERTSDIR" -maxdepth 1 -type l -delete 2>/dev/null || :
-+  trust extract --format=openssl-directory --filter=ca-anchors --overwrite "$ETCCERTSDIR"
++  MANIFEST="$ETCCERTSDIR/.manifest"
++  STAGING="$(mktemp -d -p "${TMPDIR:-/tmp}" "ca-certificates.stage.XXXXXX")"
++  OURS="$(mktemp -p "${TMPDIR:-/tmp}" "ca-certificates.tmp.XXXXXX")"
++  NEW="$(mktemp -p "${TMPDIR:-/tmp}" "ca-certificates.tmp.XXXXXX")"
++  LIVE="$(mktemp -p "${TMPDIR:-/tmp}" "ca-certificates.tmp.XXXXXX")"
++
++  trust extract --format=openssl-directory --filter=ca-anchors --overwrite "$STAGING"
++
++  mkdir -p "$ETCCERTSDIR"
++  chmod 755 "$ETCCERTSDIR"
++
++  find "$STAGING" -maxdepth 1 \( -type f -o -type l \) -printf '%f\n' | sort > "$NEW"
++
++  if [ -f "$MANIFEST" ]
++  then
++    sort "$MANIFEST" > "$OURS"
++  else
++    # No manifest yet: claim what earlier layouts generated -- hash links,
++    # symlinks into the cert stores or dangling ones (openssl-rehash
++    # layout) and TRUSTED CERTIFICATE files (direct p11-kit extraction).
++    # Anything else was placed by the local admin and is left alone.
++    {
++      find "$ETCCERTSDIR" -maxdepth 1 -type l \
++        \( -name '[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].*' \
++        -o -lname "$CERTSDIR/*" -o -lname "$LOCALCERTSDIR/*" -o -xtype l \) \
++        -printf '%f\n'
++      grep -sl -- '-----BEGIN TRUSTED CERTIFICATE-----' "$ETCCERTSDIR"/*.pem | sed 's,.*/,,'
++      echo README
++    } | sort -u > "$OURS"
++  fi
++
++  # entries we installed on a previous run and which are gone from the new set;
++  # never step outside the directory, whatever a damaged manifest claims
++  comm -23 "$OURS" "$NEW" | while IFS= read -r f
++  do
++    case "$f" in ''|*/*) continue ;; esac
++    rm -f "$ETCCERTSDIR/$f"
++  done
++
++  same_entry() {
++    if [ -L "$1" ] || [ -L "$2" ]
++    then
++      [ -L "$1" ] && [ -L "$2" ] && [ "$(readlink "$1")" = "$(readlink "$2")" ]
++    else
++      [ "$(md5sum < "$1")" = "$(md5sum < "$2")" ]
++    fi
++  }
++
++  # install the new set; identical entries are left as they are, a name
++  # collision with a differing foreign file is resolved in our favour and
++  # the foreign file is kept next to it as <name>.local
++  while IFS= read -r f
++  do
++    if [ -e "$ETCCERTSDIR/$f" ] || [ -L "$ETCCERTSDIR/$f" ]
++    then
++      if same_entry "$STAGING/$f" "$ETCCERTSDIR/$f"
++      then
++        continue
++      fi
++      if ! grep -qxF -- "$f" "$OURS"
++      then
++        echo "W: $ETCCERTSDIR/$f is in the generated namespace, keeping it as $f.local" >&2
++        mv -f "$ETCCERTSDIR/$f" "$ETCCERTSDIR/$f.local"
++      fi
++    fi
++    cp -a --remove-destination "$STAGING/$f" "$ETCCERTSDIR/$f"
++  done < "$NEW"
++
++  cat > "$ETCCERTSDIR/README" <<'EOF'
++This directory is generated by update-ca-certificates(8) from the
++/etc/certs/ca-certificates.crt bundle.  Entries listed in .manifest are
++rewritten on every run; other files are left alone, but OpenSSL ignores
++them -- a certificate is only consulted here through its hash link, and
++those all come from the trust store.
++
++To trust a local CA system wide, put its certificate in /etc/certs, list
++the file name in a /etc/ca-certificates.d/*.conf file and run
++update-ca-certificates.  It then shows up here with its hash link.
++
++To give a certificate to a single application only, keep it outside this
++directory and point that application at it directly.
++EOF
++
++  { cat "$NEW"; echo README; } > "$MANIFEST"
++
++  # files this script does not manage look trusted but are dead weight
++  find "$ETCCERTSDIR" -maxdepth 1 \( -type f -o -type l \) -printf '%f\n' | sort > "$LIVE"
++  { cat "$MANIFEST"; echo .manifest; } | sort | comm -13 - "$LIVE" | while IFS= read -r f
++  do
++    echo "W: $ETCCERTSDIR/$f is not part of the trust store and is ignored by OpenSSL, see $ETCCERTSDIR/README" >&2
++  done
++
 +fi
 +
  echo "$ADDED_CNT added, $REMOVED_CNT removed; done."
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/ca-certificates.git/commitdiff/716ec8ac31f58b25a187089970e99c5472561c3d



More information about the pld-cvs-commit mailing list