diff --git a/usr.sbin/certctl/certctl.8 b/usr.sbin/certctl/certctl.8 --- a/usr.sbin/certctl/certctl.8 +++ b/usr.sbin/certctl/certctl.8 @@ -24,7 +24,7 @@ .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 10, 2023 +.Dd February 25, 2025 .Dt CERTCTL 8 .Os .Sh NAME @@ -38,7 +38,7 @@ .Op Fl v .Ic untrusted .Nm -.Op Fl nUv +.Op Fl bBnUv .Op Fl D Ar destdir .Op Fl M Ar metalog .Ic rehash @@ -56,6 +56,14 @@ .Pp Flags: .Bl -tag -width 4n +.It Fl b +Create the CERTDESTFILE bundle file and CERTDESTFILELINKS symlinks to it, in addition to CERTDESTDIR. +Bundle files are unnecessary under normal circumstances. +You should +.Em not +use this option unless you are certain you need to generate certificate bundles. +.It Fl B +Remove CERTDESTFILE and CERTDESTFILELINKS. .It Fl D Ar destdir Specify the DESTDIR (overriding values from the environment). .It Fl d Ar distbase @@ -87,6 +95,10 @@ .Ev CERTDESTDIR and each untrusted certificate in .Ev UNTRUSTDESTDIR . +If it exists, rebuild +.Ev CERTDESTFILE +from the contents of +.Ev CERTDESTDIR . .It Ic untrust Add the specified file to the untrusted list. .It Ic trust @@ -118,6 +130,15 @@ Destination directory for symbolic links to trusted certificates. Default: .Pa /etc/ssl/certs +.It Ev CERTDESTFILE +Location of the certificate bundle file. +Default: +.Pa /etc/ssl/cert.pem +.It Ev CERTDESTFILELINKS +List of symbolic links to create that will point to CERTDESTFILE. +Default: +.Pa /etc/ssl/cert.pem +.Pa /openssl/cert.pem .It Ev UNTRUSTDESTDIR Destination directory for symbolic links to untrusted certificates. Default: diff --git a/usr.sbin/certctl/certctl.sh b/usr.sbin/certctl/certctl.sh --- a/usr.sbin/certctl/certctl.sh +++ b/usr.sbin/certctl/certctl.sh @@ -40,6 +40,17 @@ NOOP=false UNPRIV=false VERBOSE=false +WANTCERTDESTFILE="maybe" +# WANTCERTDESTFILE has the following enumerated states: +# +# maybe The rehash command will create a new CERTDESTFILE only if it +# already exists. +# +# yes The rehash command will create a new CERTDESTFILE even if it +# doesn't yet exist. Set by the -b flag. +# +# no The rehash command will delete CERTDESTFILE if it exists +# and not create a new one. Set by the -B flag. ############################################################ FUNCTIONS @@ -174,6 +185,30 @@ "$srcfile" "$UNTRUSTDESTDIR/$filename" } +create_bundle() +{ + local TMPFILE + + verbose "Generating certificate bundle ${CERTDESTFILE}" + TMPFILE=$(mktemp) + printf '## Auto-generated by certctl(8). DO NOT EDIT\n' >"$TMPFILE" + find "$CERTDESTDIR" \( -type f -or -type l \) -exec cat '{}' + >>"$TMPFILE" + perform install ${INSTALLFLAGS} -m 0444 "$TMPFILE" "$CERTDESTFILE" + rm "$TMPFILE" +} + +create_bundlelink() +{ + verbose "Symlinking certificate bundle to $1" + perform install -d ${INSTALLFLAGS} -m 0755 "$(dirname "$1")" + perform install ${INSTALLFLAGS} -lrs "$CERTDESTFILE" "$1" +} + +remove_bundlelink() +{ + perform rm -f "$1" +} + do_scan() { local CFUNC CSEARCH CPATH CFILE CERT SPLITDIR @@ -227,6 +262,20 @@ done } +do_bundlelinks() +{ + local LFUNC LFILE + local oldIFS="$IFS" + LFUNC="$1" + + IFS=: + set -- $CERTDESTFILELINKS + IFS="$oldIFS" + for LFILE in "$@" ; do + "$LFUNC" "$LFILE" + done +} + cmd_rehash() { @@ -240,9 +289,23 @@ else perform install -d -m 0755 "$UNTRUSTDESTDIR" fi + # Need the loop to iterate over CERTDESTFILELINKS. + do_bundlelinks remove_bundlelink + if [ -e "$CERTDESTFILE" ] ; then + perform rm "$CERTDESTFILE" + if [ "$WANTCERTDESTFILE" = "maybe" ] ; then + # CERTDESTFILE existed and -B wasn't used, so... + WANTCERTDESTFILE="yes" + fi + fi do_scan create_untrusted "$UNTRUSTPATH" do_scan create_trusted "$TRUSTPATH" + # CERTDESTFILE existed or -b was used + if [ "$WANTCERTDESTFILE" = "yes" ] ; then + create_bundle + do_bundlelinks create_bundlelink + fi } cmd_list() @@ -303,7 +366,7 @@ echo " List trusted certificates" echo " $SCRIPTNAME [-v] untrusted" echo " List untrusted certificates" - echo " $SCRIPTNAME [-nUv] [-D ] [-d ] [-M ] rehash" + echo " $SCRIPTNAME [-bBnUv] [-D ] [-d ] [-M ] rehash" echo " Generate hash links for all certificates" echo " $SCRIPTNAME [-nv] untrust " echo " Add to the list of untrusted certificates" @@ -314,8 +377,10 @@ ############################################################ MAIN -while getopts D:d:M:nUv flag; do +while getopts bBD:d:M:nUv flag; do case "$flag" in + b) WANTCERTDESTFILE="yes" ;; + B) WANTCERTDESTFILE="no" ;; D) DESTDIR=${OPTARG} ;; d) DISTBASE=${OPTARG} ;; M) METALOG=${OPTARG} ;; @@ -341,6 +406,8 @@ : ${UNTRUSTPATH:=${DESTDIR}${DISTBASE}/usr/share/certs/untrusted:${DESTDIR}${LOCALBASE}/etc/ssl/untrusted:${DESTDIR}${LOCALBASE}/etc/ssl/blacklisted} : ${CERTDESTDIR:=${DESTDIR}${DISTBASE}/etc/ssl/certs} : ${UNTRUSTDESTDIR:=${DESTDIR}${DISTBASE}/etc/ssl/untrusted} +: ${CERTDESTFILE:=${DESTDIR}${DISTBASE}/etc/ssl/cert.pem} +: ${CERTDESTFILELINKS:=${DESTDIR}${DISTBASE}${LOCALBASE}/etc/ssl/cert.pem:${DESTDIR}${DISTBASE}${LOCALBASE}/openssl/cert.pem} [ $# -gt 0 ] || usage case "$1" in