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