git: a401c8cb26b2 - main - certctl: Split certificate bundles before processing.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 05 Oct 2023 15:11:31 UTC
The branch main has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=a401c8cb26b22688087ad7c5ee527718459df15a
commit a401c8cb26b22688087ad7c5ee527718459df15a
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2023-10-05 14:50:01 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2023-10-05 15:11:22 +0000
certctl: Split certificate bundles before processing.
This allows 'certctl rehash' to do the right thing when ca_root_nss is
installed, instead of linking the entire bundle to the hash of the
first certificate it contains.
MFC after: 3 days
Reviewed by: allanjude
Differential Revision: https://reviews.freebsd.org/D42087
---
usr.sbin/certctl/certctl.sh | 99 ++++++++++++++++++++++++++++-----------------
1 file changed, 63 insertions(+), 36 deletions(-)
diff --git a/usr.sbin/certctl/certctl.sh b/usr.sbin/certctl/certctl.sh
index 02d055102c33..b7d3a95bc7d7 100755
--- a/usr.sbin/certctl/certctl.sh
+++ b/usr.sbin/certctl/certctl.sh
@@ -32,7 +32,6 @@ set -u
: ${DESTDIR:=}
: ${DISTBASE:=}
-: ${FILEPAT:="\.pem$|\.crt$|\.cer$|\.crl$"}
############################################################ GLOBALS
@@ -63,6 +62,16 @@ perform()
fi
}
+cert_files_in()
+{
+ find -L "$@" -type f \( \
+ -name '*.pem' -or \
+ -name '*.crt' -or \
+ -name '*.cer' -or \
+ -name '*.crl' \
+ \) 2>/dev/null
+}
+
do_hash()
{
local hash
@@ -93,23 +102,32 @@ get_decimal()
return 0
}
-create_trusted_link()
+create_trusted()
{
local hash certhash otherfile otherhash
local suffix
+ local link=${2:+-lm}
hash=$(do_hash "$1") || return
certhash=$(openssl x509 -sha1 -in "$1" -noout -fingerprint)
for otherfile in $(find $UNTRUSTDESTDIR -name "$hash.*") ; do
otherhash=$(openssl x509 -sha1 -in "$otherfile" -noout -fingerprint)
if [ "$certhash" = "$otherhash" ] ; then
- info "Skipping untrusted certificate $1 ($otherfile)"
+ info "Skipping untrusted certificate $hash ($otherfile)"
return 1
fi
done
+ for otherfile in $(find $CERTDESTDIR -name "$hash.*") ; do
+ otherhash=$(openssl x509 -sha1 -in "$otherfile" -noout -fingerprint)
+ if [ "$certhash" = "$otherhash" ] ; then
+ verbose "Skipping duplicate entry for certificate $hash"
+ return 0
+ fi
+ done
suffix=$(get_decimal "$CERTDESTDIR" "$hash")
verbose "Adding $hash.$suffix to trust store"
- perform install ${INSTALLFLAGS} -lrs "$(realpath "$1")" "$CERTDESTDIR/$hash.$suffix"
+ perform install ${INSTALLFLAGS} -m 0444 ${link} \
+ "$(realpath "$1")" "$CERTDESTDIR/$hash.$suffix"
}
# Accepts either dot-hash form from `certctl list` or a path to a valid cert.
@@ -137,6 +155,7 @@ resolve_certname()
create_untrusted()
{
local srcfile filename
+ local link=${2:+-lm}
set -- $(resolve_certname "$1")
srcfile=$1
@@ -147,12 +166,13 @@ create_untrusted()
fi
verbose "Adding $filename to untrusted list"
- perform install ${INSTALLFLAGS} -lrs "$srcfile" "$UNTRUSTDESTDIR/$filename"
+ perform install ${INSTALLFLAGS} -m 0444 ${link} \
+ "$srcfile" "$UNTRUSTDESTDIR/$filename"
}
do_scan()
{
- local CFUNC CSEARCH CPATH CFILE
+ local CFUNC CSEARCH CPATH CFILE CERT SPLITDIR
local oldIFS="$IFS"
CFUNC="$1"
CSEARCH="$2"
@@ -160,14 +180,25 @@ do_scan()
IFS=:
set -- $CSEARCH
IFS="$oldIFS"
- for CPATH in "$@"; do
- [ -d "$CPATH" ] || continue
- info "Scanning $CPATH for certificates..."
- for CFILE in $(ls -1 "${CPATH}" | grep -Ee "${FILEPAT}") ; do
- [ -e "$CPATH/$CFILE" ] || continue
- verbose "Reading $CFILE"
- "$CFUNC" "$CPATH/$CFILE"
- done
+ for CFILE in $(cert_files_in "$@") ; do
+ verbose "Reading $CFILE"
+ case $(grep -c '^Certificate:$' "$CFILE") in
+ 0)
+ ;;
+ 1)
+ "$CFUNC" "$CFILE" link
+ ;;
+ *)
+ verbose "Multiple certificates found, splitting..."
+ SPLITDIR=$(mktemp -d)
+ egrep '^[^#]' "$CFILE" | \
+ split -p '^Certificate:$' - "$SPLITDIR/x"
+ for CERT in $(find "$SPLITDIR" -type f) ; do
+ "$CFUNC" "$CERT"
+ done
+ rm -rf "$SPLITDIR"
+ ;;
+ esac
done
}
@@ -175,43 +206,39 @@ do_list()
{
local CFILE subject
- if [ -e "$1" ] ; then
- cd "$1"
- for CFILE in *.[0-9] ; do
- if [ ! -s "$CFILE" ] ; then
- info "Unable to read $CFILE"
- ERRORS=$((ERRORS + 1))
- continue
- fi
- subject=
- if [ $VERBOSE -eq 0 ] ; then
- subject=$(openssl x509 -noout -subject -nameopt multiline -in "$CFILE" |
- sed -n '/commonName/s/.*= //p')
- fi
- [ "$subject" ] ||
- subject=$(openssl x509 -noout -subject -in "$CFILE")
- printf "%s\t%s\n" "$CFILE" "$subject"
- done
- cd -
- fi
+ for CFILE in $(find "$@" \( -type f -or -type l \) -name '*.[0-9]') ; do
+ if [ ! -s "$CFILE" ] ; then
+ info "Unable to read $CFILE"
+ ERRORS=$((ERRORS + 1))
+ continue
+ fi
+ subject=
+ if ! "$VERBOSE" ; then
+ subject=$(openssl x509 -noout -subject -nameopt multiline -in "$CFILE" | sed -n '/commonName/s/.*= //p')
+ fi
+ if [ -z "$subject" ] ; then
+ subject=$(openssl x509 -noout -subject -in "$CFILE")
+ fi
+ printf "%s\t%s\n" "${CFILE##*/}" "$subject"
+ done
}
cmd_rehash()
{
if [ -e "$CERTDESTDIR" ] ; then
- perform find "$CERTDESTDIR" -type link -delete
+ perform find "$CERTDESTDIR" \( -type f -or -type l \) -delete
else
perform install -d -m 0755 "$CERTDESTDIR"
fi
if [ -e "$UNTRUSTDESTDIR" ] ; then
- perform find "$UNTRUSTDESTDIR" -type link -delete
+ perform find "$UNTRUSTDESTDIR" \( -type f -or -type l \) -delete
else
perform install -d -m 0755 "$UNTRUSTDESTDIR"
fi
do_scan create_untrusted "$UNTRUSTPATH"
- do_scan create_trusted_link "$TRUSTPATH"
+ do_scan create_trusted "$TRUSTPATH"
}
cmd_list()