Module Name: src Committed By: riastradh Date: Sun Sep 3 18:31:36 UTC 2023
Modified Files: src/usr.sbin/postinstall: postinstall.in Log Message: postinstall(8): Handle various certs.conf scenarios gracefully. Tested the following scenarios: 1. fresh install empty /etc/openssl/certs default /etc/openssl/certs.conf - opensslcertsconf [x] check: pass [x] fix: pass -- nothing - opensslcertsrehash [x] check: fail -- needs rehash [x] fix: pass -- quietly rehash successfully (go to 4) 2. fresh upgrade empty /etc/openssl/certs no /etc/openssl/certs.conf - opensslcertsconf [x] check: fail -- complain missing /etc/openssl/certs.conf [x] fix: pass -- install default /etc/openssl/certs.conf (go to 1) - opensslcertsrehash [x] check: fail -- complain missing /etc/openssl/certs.conf - [x] fix: fail -- complain missing /etc/openssl/certs.conf 3. upgrade from certctl, changes to certs certctl-managed /etc/openssl/certs default /etc/openssl/certs.conf - opensslcertsconf [x] check: pass [x] fix: pass -- nothing - opensslcertsrehash [x] check: fail -- needs rehash [x] fix: pass -- quietly rehash successfully (go to 4) 4. upgrade from certctl, no changes to certs certctl-managed /etc/openssl/certs default /etc/openssl/certs.conf - opensslcertsconf [x] check: pass [x] fix: pass -- nothing - opensslcertsrehash [x] check: pass [x] fix: pass -- quietly rehash successfully (go to 4) 5. upgrade from mozilla-rootcerts populated /etc/openssl/certs no /etc/openssl/certs.conf - opensslcertsconf: [x] check: fail -- complain missing /etc/openssl/certs.conf [x] fix: pass -- install manual /etc/openssl/certs.conf (go to 7) - opensslcertsrehash: [x] check: fail -- complain missing /etc/openssl/certs.conf [x] fix: fail -- complain missing /etc/openssl/certs.conf 6. upgrade from mozilla-rootcerts with etcupdate naively populated /etc/openssl/certs default /etc/openssl/certs.conf - opensslcertsconf: [x] check: pass [x] fix: pass -- nothing - opensslcertsrehash: [x] check: fail -- complain mismatched certs/ and certs.conf [x] fix: fail -- complain mismatched certs/ and certs.conf 7. upgrade from mozilla-rootcerts with etcupdate manually populated /etc/openssl/certs manual /etc/openssl/certs.conf - opensslcertsconf: [x] check: pass [x] fix: pass -- nothing - opensslcertsrehash: [x] check: pass [x] fix: pass -- skip rehash because manual (go to 7) XXX Someone should draft automatic tests for postinstall. It has a very good track record, but it sure would be nice to automate this testing rather than redo it each time I make a tiny change. To generate a diff of this commit: cvs rdiff -u -r1.54 -r1.55 src/usr.sbin/postinstall/postinstall.in Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/postinstall/postinstall.in diff -u src/usr.sbin/postinstall/postinstall.in:1.54 src/usr.sbin/postinstall/postinstall.in:1.55 --- src/usr.sbin/postinstall/postinstall.in:1.54 Mon Aug 28 23:57:08 2023 +++ src/usr.sbin/postinstall/postinstall.in Sun Sep 3 18:31:36 2023 @@ -1,6 +1,6 @@ #!/bin/sh # -# $NetBSD: postinstall.in,v 1.54 2023/08/28 23:57:08 riastradh Exp $ +# $NetBSD: postinstall.in,v 1.55 2023/09/03 18:31:36 riastradh Exp $ # # Copyright (c) 2002-2022 The NetBSD Foundation, Inc. # All rights reserved. @@ -1662,24 +1662,126 @@ do_named() # -# opensslcerts +# opensslcertsconf # -additem opensslcerts "build /etc/openssl/certs cache of HTTPS CA certificates" -do_opensslcerts() +additem opensslcertsconf "ensure TLS trust anchor configuration exists" +do_opensslcertsconf() { - [ -n "$1" ] || err 3 "USAGE: do_opensslcerts fix|check" + local certsdir certsconf defaultconf + + [ -n "$1" ] || err 3 "USAGE: do_opensslcertsconf fix|check" + + certsdir="${DEST_DIR}/etc/openssl/certs" + certsconf="${DEST_DIR}/etc/openssl/certs.conf" + defaultconf="${DEST_DIR}/usr/share/examples/certctl/certs.conf" case $1 in - check) # XXX Anything to check? - return 0 + check) if [ ! -r "$certsconf" ]; then + msg "/etc/openssl/certs.conf missing; see certctl(8)" + return 1 + fi + ;; + fix) # If /etc/openssl/certs.conf is already there, nothing + # to do. + if [ -r "$certsconf" ]; then + msg "/etc/openssl/certs.conf already exists" + return 0 + fi + + # If /etc/openssl/certs is a symlink, or exists but is + # not a directory, or is a directory but is nonempty, + # then either it's managed by someone else or something + # fishy is afoot. So set it manual in that case. + # Otherwise, install the default config file. + if [ -h "$certsdir" ] || + [ -e "$certsdir" -a ! -d "$certsdir" ] || + ([ -d "$certsdir" ] && + find -f "$certsdir" -- \ + -maxdepth 0 -type d -empty -exit 1) + then + msg "/etc/openssl/certs appears manually configured" + cat <<EOF >${certsconf}.tmp +netbsd-certctl 20230816 + +# existing /etc/openssl/certs configuration detected by postinstall(8) +manual +EOF + else + msg "installing default /etc/openssl/certs.conf" + cp -- "$defaultconf" "${certsconf}.tmp" + fi && mv -f -- "${certsconf}.tmp" "$certsconf" + ;; + *) err 3 "USAGE: do_opensslcerts fix|check" + ;; + esac +} + + +# +# opensslcertsrehash +# + +additem opensslcertsrehash "make /etc/openssl/certs cache of TLS trust anchors" +do_opensslcertsrehash() +{ + local mtreekeys scratchdir + + [ -n "$1" ] || err 3 "USAGE: do_opensslcertsrehash fix|check" + + if [ ! -r "${DEST_DIR}/etc/openssl/certs.conf" ]; then + msg "/etc/openssl/certs.conf missing; see certctl(8)" + return 1 + fi + + case $1 in + check) # Create a scratch rehash for comparison. + mtreekeys="type,link" + scratchdir="${SCRATCHDIR}/opensslcerts" + certctl -c "$scratchdir" rehash || return $? + + # This will create ${scratchdir}/.certctl unless the + # configuration is manual. If the configuration is + # manual, stop here; nothing to do. certctl(8) will + # have already printed a message about that. + # + # XXX Grody to rely on the internal structure used by + # certctl(8), but less bad than having two versions of + # the config parsing logic. + if [ ! -f "${scratchdir}/.certctl" ]; then + return 0 + fi + + # Do a dry run of rehashing into the real + # /etc/openssl/certs. This curious extra step ensures + # that we report a failure if /etc/openssl/certs + # appears to be managed manually, but `manual' was not + # specified in /etc/openssl/certs.conf. + certctl -n rehash || return $? + + # Compare the trees with mtree(8). Inconveniently, + # mtree returns status zero even if there are missing + # or extra files. So instead of examining the return + # status, test for any output. Empty output means + # everything matches; otherwise the mismatch, missing, + # or extra files are output. + mtree -p "$scratchdir" -c -k "$mtreekeys" \ + | mtree -p "${DEST_DIR}/etc/openssl/certs" 2>&1 \ + | { + while read -r line; do + # mismatch, missing, or extra + msg "/etc/openssl/certs needs rehash" + exit 1 + done + exit 0 + } ;; fix) # This runs openssl(1), which is not available as a # build-time tool. So for now, restrict it to running # on the installed system. case $DEST_DIR in ''|/) ;; - *) msg "opensslcerts limited to DEST_DIR=/" + *) msg "opensslcertsrehash limited to DEST_DIR=/" return 1 ;; esac