certctl(8): Avoid clobbering prepopulated /etc/openssl/certs.

Also avoid clobbering some other edge cases like symlinks or
non-directories there.

This way, we have the following transitions on system updates:

- If /etc/openssl/certs is empty (as in default NetBSD<10 installs):
  quietly populated on rehash.

- If /etc/openssl/certs is nonempty (you've added things to it,
  e.g. by hand or with mozilla-rootcerts) and has never been managed
  by certctl(8): left alone on rehash, with an error message to
  explain what you need to do.

- If /etc/openssl/certs has been managed by certctl(8): quietly
  updated on rehash.

Note: This means current installations made since certctl(8) was
added will be treated like /etc/openssl/certs is nonempty and has
never been managed by certctl(8).  To work around this, you can just
delete /etc/openssl/certs and rerun `certctl rehash'.
This commit is contained in:
riastradh 2023-08-28 22:25:49 +00:00
parent 9189de7638
commit 1cac5d57e4
3 changed files with 51 additions and 8 deletions

View File

@ -1,4 +1,4 @@
$NetBSD: UPDATING,v 1.342 2023/07/19 17:49:40 martin Exp $
$NetBSD: UPDATING,v 1.343 2023/08/28 22:25:49 riastradh Exp $
This file (UPDATING) is intended to be a brief reference to recent
changes that might cause problems in the build process, and a guide for
@ -19,6 +19,21 @@ See also: BUILDING, build.sh, Makefile.
Recent changes:
^^^^^^^^^^^^^^^
20230828:
If:
- you updated to current and ran postinstall between 20230826
and 20230828 inclusive, and
- you are not using anything outside the base system to
populate /etc/openssl/certs (e.g., manually adding
certificates or using ca-certificates or mozilla-rootcerts or
mozilla-rootcerts-openssl from pkgsrc),
delete /etc/openssl/certs and rerun postinstall or just
`certctl rehash'.
Otherwise, certctl(8) will think someone else has left
/etc/openssl/certs in the way and will avoid clobbering it on
upgrade from older NetBSD.
20230718:
build.sh will use mk.conf in the same directory as build.sh instead
of /etc/mk.conf, unless MAKECONF is already defined in the environment.

View File

@ -1,6 +1,6 @@
#!/bin/sh
# $NetBSD: t_certctl.sh,v 1.4 2023/08/28 22:25:41 riastradh Exp $
# $NetBSD: t_certctl.sh,v 1.5 2023/08/28 22:25:49 riastradh Exp $
#
# Copyright (c) 2023 The NetBSD Foundation, Inc.
# All rights reserved.
@ -358,7 +358,6 @@ symlinkcertsdir_body()
mkdir empty
ln -sfn empty certs
atf_expect_fail "certctl clobbers symlink at /etc/openssl/certs"
atf_check -s not-exit:0 -e match:symlink $CERTCTL -n rehash
atf_check -s not-exit:0 -e match:symlink $CERTCTL rehash
atf_check -s exit:0 rmdir empty
@ -375,7 +374,6 @@ regularfilecertsdir_body()
rmdir certs
echo 'hello world' >certs
atf_expect_fail "certctl clobbers file at /etc/openssl/certs"
atf_check -s not-exit:0 -e match:directory $CERTCTL -n rehash
atf_check -s not-exit:0 -e match:directory $CERTCTL rehash
atf_check -s exit:0 rm certs
@ -393,7 +391,6 @@ prepopulatedcerts_body()
setupconf certs1
ln -sfn "$(atf_get_srcdir)/certs2"/*.pem certs/
atf_expect_fail "certctl clobbers prepopulated /etc/openssl/certs"
atf_check -s not-exit:0 -e match:manual $CERTCTL -n rehash
atf_check -s not-exit:0 -e match:manual $CERTCTL rehash
for cert in "$(atf_get_srcdir)/certs2"/*.pem; do

View File

@ -1,6 +1,6 @@
#!/bin/sh
# $NetBSD: certctl.sh,v 1.2 2023/08/28 22:25:32 riastradh Exp $
# $NetBSD: certctl.sh,v 1.3 2023/08/28 22:25:50 riastradh Exp $
#
# Copyright (c) 2023 The NetBSD Foundation, Inc.
# All rights reserved.
@ -427,9 +427,40 @@ rehash()
return
fi
# Delete the active certificates symlink cache.
run rm -rf "$certsdir"
# Delete the active certificates symlink cache, if either it is
# empty or nonexistent, or it is tagged for use by certctl.
if [ -f "$certsdir/.certctl" ]; then
# Directory exists and is managed by certctl(8).
# Safe to delete it and everything in it.
run rm -rf "$certsdir"
elif [ -h "$certsdir" ]; then
# Paranoia: refuse to chase a symlink. (Caveat: this
# is not secure against an adversary who can recreate
# the symlink at any time. Just a helpful check for
# mistakes.)
error "certificates directory is a symlink"
return 1
elif [ ! -e "$certsdir" ]; then
# Directory doesn't exist at all. Nothing to do!
elif [ ! -d "$certsdir" ]; then
error "certificates directory is not a directory"
return 1
elif ! find "$certsdir" -maxdepth 0 -type d -empty -exit 1; then
# certsdir exists, is a directory, and is empty. Safe
# to delete it with rmdir and take it over.
run rmdir "$certsdir"
else
error "existing certificates; set manual or move them"
return 1
fi
run mkdir "$certsdir"
if $vflag; then
printf '# initialize %s\n' "$certsdir"
fi
if ! $nflag; then
printf 'This directory is managed by certctl(8).\n' \
>$certsdir/.certctl
fi
# Create a temporary file for the single-file bundle. This
# will be automatically deleted on normal exit or