From nobody Fri May 30 12:42:19 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4b82v013rxz5xd7v; Fri, 30 May 2025 12:42:20 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4b82v00M0pz3HC7; Fri, 30 May 2025 12:42:20 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1748608940; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Trt4q20IhkW6ukM5KMoHeiEVusPtmbgqoY109EpNlS8=; b=MW/7EW4/jEFqxxRlL19V2pl6go/9oGLwuDotLUeud705I8ghFxC6tUyptpO8AsAgGA2ZeZ 1Ke0Lz0YlbdZuBhSHQDvxkOeemhPEu7AMTpcwkuV1KNtFyTHxMFfOBqlY3Zpc7BAdmcDcM BxGaO/4LuCFp+DbNv+JrE/T+/lQxNfEmdoRDCttNUphi1OS8gFeFLrh5lkGveAOWBfPQH0 wYTg6MP7zS4U2udDVltQEX60XYpb/0jNut9G7iKnrn2dyLBNnJKt299CEmQ717DaYEsXs5 TJfsAgClauXCGxVyaVFjGyx5dnzN9RMQ02cv0Kmgtg7hLl3uNbR3AIAq4a+SfQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1748608940; a=rsa-sha256; cv=none; b=e0sELgSFzig0GS2tFPNmVFIU6p1OFp5l+OBFEcz4Q6Z+5+vNAv7X8VPWrvVhTJyxEVZsMX VCeQZ7hF/KSB9vmHFeX+MLQclbt5fABPA/kdFv6BPA3xgCDqKQ2GjY5wa3Ag1MU1vyJ/k5 N6YV80o6CFfESul8AVT3dr8LUK/99e0tsDoT1xDnc1wdKFd/IvKT1PGHPWpvNEStGkbe3j PNNjGMnMberFBxstGdTi7DNAluWrlkroKAt5/5gNgCKnofisbprt9REa48QpCBywwF/mJG Fxh2SwhBvxuByCtQKsdrxHV7PmRxGS3tQAp/BJP5tjhUORxE3jY+TW1B+zr1Og== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1748608940; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Trt4q20IhkW6ukM5KMoHeiEVusPtmbgqoY109EpNlS8=; b=wcgTnWkwfaIqq+T8p1KTFx3zrx2o1654FkVsN96xeL0v49iCnEQAMuqz9BkiUeDuP1mn9/ tdh9uQSSjG3av9PF8IEYWUdCQ33pDVpyH3c+77eS5P9Hyp9HcZcxrRj0QDa+00OuiXXAxn 0lvmXwyQYXl4myvKv0waofl/1fDUIEoA3+U3Y0gB7KOfT9ulI3fpr+88KVu0Hw/xbArPGB DKbYwq+ISvS6DvKrOLhrzpdEs1Ssw6986uoHDIhkJVa8GBc0rT5MnpRkt+m28to37D1Ivn 4h8bAA4k/ERuuUMKs9TMsMDDKQowo+Za3UCFJ40U63DXsqcwi44Tmlo0ag03EQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4b82tz6sJczskQ; Fri, 30 May 2025 12:42:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 54UCgJUZ022070; Fri, 30 May 2025 12:42:19 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 54UCgJKp022067; Fri, 30 May 2025 12:42:19 GMT (envelope-from git) Date: Fri, 30 May 2025 12:42:19 GMT Message-Id: <202505301242.54UCgJKp022067@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= Subject: git: 9c34a6876a60 - stable/14 - certctl: Split certificate bundles before processing. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 9c34a6876a60dc10fda6ad6a0cbe8f99a372aadc Auto-Submitted: auto-generated The branch stable/14 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=9c34a6876a60dc10fda6ad6a0cbe8f99a372aadc commit 9c34a6876a60dc10fda6ad6a0cbe8f99a372aadc Author: Dag-Erling Smørgrav AuthorDate: 2023-10-05 14:50:01 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2025-05-30 12:40:53 +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 (cherry picked from commit a401c8cb26b22688087ad7c5ee527718459df15a) certctl: Fix recent regressions. - If an untrusted certificate is also found in the list of trusted certificate, issue a warning and skip it, but don't fail. - Split on -+BEGIN CERTIFICATE-+ instead of "Certificate:" since that's what we're really looking for. Also fix a long-standing bug: .crl files are not certificates, so we should not include them when searching for certificates. Reported by: madpilot, netchild, tijl Reviewed by: netchild, allanjude Differential Revision: https://reviews.freebsd.org/D42276 (cherry picked from commit 87945a082980260b52507ad5bfb3a0ce773a80da) certctl: Convert line endings before inspecting files. This ensures that certificate files or bundles with DOS or Mac line endings are recognized as such and handled identically to those with Unix line endings. PR: 274952 Reviewed by: allanjude Differential Revision: https://reviews.freebsd.org/D42490 (cherry picked from commit f7d16a627efa8ba610eb9b8a12dd67b6cdbb2542) certctl: Revert to symlinks. Unfortunately tar will not be able to extract base.txz to a system where /etc and /usr are not on the same filesystem if the certificates are hard links. PR: 277828 Reviewed by: mp Differential Revision: https://reviews.freebsd.org/D44496 (cherry picked from commit 3fed4f0db53a66a0135bea5c491431eb3348cf51) --- usr.sbin/certctl/certctl.sh | 105 ++++++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 37 deletions(-) diff --git a/usr.sbin/certctl/certctl.sh b/usr.sbin/certctl/certctl.sh index 5af8fecb93ac..458f5c53682f 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,20 @@ perform() fi } +cert_files_in() +{ + find -L "$@" -type f \( \ + -name '*.pem' -or \ + -name '*.crt' -or \ + -name '*.cer' \ + \) 2>/dev/null +} + +eolcvt() +{ + cat "$@" | tr -s '\r' '\n' +} + do_hash() { local hash @@ -93,23 +106,32 @@ get_decimal() return 0 } -create_trusted_link() +create_trusted() { local hash certhash otherfile otherhash local suffix + local link=${2:+-lrs} 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)" - return 1 + info "Skipping untrusted certificate $hash ($otherfile)" + return 0 + 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 +159,7 @@ resolve_certname() create_untrusted() { local srcfile filename + local link=${2:+-lrs} set -- $(resolve_certname "$1") srcfile=$1 @@ -147,12 +170,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 +184,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 $(eolcvt "$CFILE" | egrep -c '^-+BEGIN CERTIFICATE-+$') in + 0) + ;; + 1) + "$CFUNC" "$CFILE" link + ;; + *) + verbose "Multiple certificates found, splitting..." + SPLITDIR=$(mktemp -d) + eolcvt "$CFILE" | egrep '^(---|[0-9A-Za-z/+=]+$)' | \ + split -p '^-+BEGIN CERTIFICATE-+$' - "$SPLITDIR/x" + for CERT in $(find "$SPLITDIR" -type f) ; do + "$CFUNC" "$CERT" + done + rm -rf "$SPLITDIR" + ;; + esac done } @@ -175,43 +210,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()