certctl(8): New tool for managing OpenSSL CA certificates.

Same command-line syntax as FreeBSD, clearer semantics about which
parts are config and which parts are cache.
This commit is contained in:
riastradh 2023-08-26 05:27:13 +00:00
parent 9bd4ba417d
commit 50a8b41245
26 changed files with 1673 additions and 8 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1325 2023/08/01 06:35:55 mrg Exp $
# $NetBSD: mi,v 1.1326 2023/08/26 05:27:13 riastradh Exp $
#
# Note: Don't delete entries from here - mark them as "obsolete" instead,
# unless otherwise stated below.
@ -114,6 +114,7 @@
./etc/openldap base-ldap-root
./etc/openssl base-crypto-root
./etc/openssl/certs base-crypto-root
./etc/openssl/certs.conf base-sysutil-bin
./etc/openssl/misc base-crypto-root
./etc/openssl/private base-crypto-root
./etc/pam.d base-sys-root
@ -1457,6 +1458,7 @@
./usr/sbin/btpand base-sysutil-bin
./usr/sbin/btuartd base-obsolete obsolete
./usr/sbin/catman base-man-bin
./usr/sbin/certctl base-sysutil-bin
./usr/sbin/chat base-ppp-bin
./usr/sbin/chown base-sysutil-bin
./usr/sbin/chroot base-sysutil-bin

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1763 2023/08/11 23:04:29 christos Exp $
# $NetBSD: mi,v 1.1764 2023/08/26 05:27:13 riastradh Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -2648,6 +2648,7 @@
./usr/share/man/cat8/ccdconfig.0 man-sysutil-catman .cat
./usr/share/man/cat8/cesfic/MAKEDEV.0 man-obsolete obsolete
./usr/share/man/cat8/cesfic/makedev.0 man-obsolete obsolete
./usr/share/man/cat8/certctl.0 man-sysutil-catman .cat
./usr/share/man/cat8/cgdconfig.0 man-sysutil-catman .cat
./usr/share/man/cat8/chat.0 man-ppp-catman .cat
./usr/share/man/cat8/chown.0 man-sysutil-catman .cat
@ -5902,6 +5903,7 @@
./usr/share/man/html8/canconfig.html man-netutil-htmlman html
./usr/share/man/html8/catman.html man-man-htmlman html
./usr/share/man/html8/ccdconfig.html man-sysutil-htmlman html
./usr/share/man/html8/certctl.html man-sysutil-htmlman html
./usr/share/man/html8/cgdconfig.html man-sysutil-htmlman html
./usr/share/man/html8/chat.html man-ppp-htmlman html
./usr/share/man/html8/chown.html man-sysutil-htmlman html
@ -9203,6 +9205,7 @@
./usr/share/man/man8/ccdconfig.8 man-sysutil-man .man
./usr/share/man/man8/cesfic/MAKEDEV.8 man-obsolete obsolete
./usr/share/man/man8/cesfic/makedev.8 man-obsolete obsolete
./usr/share/man/man8/certctl.8 man-sysutil-man .man
./usr/share/man/man8/cgdconfig.8 man-sysutil-man .man
./usr/share/man/man8/chat.8 man-ppp-man .man
./usr/share/man/man8/chown.8 man-sysutil-man .man

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1291 2023/08/20 19:36:56 riastradh Exp $
# $NetBSD: mi,v 1.1292 2023/08/26 05:27:14 riastradh Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -7564,6 +7564,22 @@
./usr/tests/usr.sbin tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/Atffile tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/Kyuafile tests-usr.sbin-tests compattestfile,atf,kyua
./usr/tests/usr.sbin/certctl tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/Atffile tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/Kyuafile tests-usr.sbin-tests compattestfile,atf,kyua
./usr/tests/usr.sbin/certctl/certs1 tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs1/DigiCert_Global_Root_CA.pem tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs1/Explicitly_Distrust_DigiNotar_Root_CA.pem tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs2 tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs2/GTS_Root_R1.pem tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs2/GlobalSign_Root_CA_-_R3.pem tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs3 tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs3/Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.1.pem tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs3/Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.pem tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs4 tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs4/AC_RAIZ_FNMT-RCM.pem tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/certs4/DigiCert_Global_Root_CA.pem tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/certctl/t_certctl tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/cpuctl tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/cpuctl/Atffile tests-usr.sbin-tests compattestfile,atf
./usr/tests/usr.sbin/cpuctl/Kyuafile tests-usr.sbin-tests compattestfile,atf,kyua

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.466 2022/08/21 07:10:03 lukem Exp $
# $NetBSD: Makefile,v 1.467 2023/08/26 05:27:14 riastradh Exp $
# from: @(#)Makefile 8.7 (Berkeley) 5/25/95
# Environment variables without default values:
@ -348,6 +348,7 @@ install-etc-files: .PHONY .MAKE check_DESTDIR MAKEDEV
.endfor
${MAKEDIRTARGET} ${NETBSDSRCDIR}/external/bsd/dhcpcd/sbin/dhcpcd configinstall
${MAKEDIRTARGET} ${NETBSDSRCDIR}/usr.bin/mail configinstall
${MAKEDIRTARGET} ${NETBSDSRCDIR}/usr.sbin/certctl configinstall
.if (${MKPF} != "no")
${MAKEDIRTARGET} ${NETBSDSRCDIR}/usr.sbin/pf configinstall
.endif

View File

@ -1,4 +1,4 @@
# $NetBSD: NetBSD.dist.tests,v 1.199 2023/08/20 10:27:11 riastradh Exp $
# $NetBSD: NetBSD.dist.tests,v 1.200 2023/08/26 05:27:14 riastradh Exp $
./usr/libdata/debug/usr/tests
./usr/libdata/debug/usr/tests/atf
@ -486,6 +486,11 @@
./usr/tests/usr.bin/xlint/xlint
./usr/tests/usr.bin/ztest
./usr/tests/usr.sbin
./usr/tests/usr.sbin/certctl
./usr/tests/usr.sbin/certctl/certs1
./usr/tests/usr.sbin/certctl/certs2
./usr/tests/usr.sbin/certctl/certs3
./usr/tests/usr.sbin/certctl/certs4
./usr/tests/usr.sbin/cpuctl
./usr/tests/usr.sbin/execsnoop
./usr/tests/usr.sbin/inetd

View File

@ -1,8 +1,9 @@
# $NetBSD: Makefile,v 1.7 2021/08/29 09:54:18 christos Exp $
# $NetBSD: Makefile,v 1.8 2023/08/26 05:27:14 riastradh Exp $
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/usr.sbin
TESTS_SUBDIRS+= certctl
TESTS_SUBDIRS+= cpuctl
TESTS_SUBDIRS+= execsnoop
TESTS_SUBDIRS+= inetd

View File

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.1 2023/08/26 05:27:14 riastradh Exp $
#
.include "Makefile.inc" # TESTSDIR
SUBDIR= certs1 certs2 certs3 certs4
TESTS_SH= t_certctl
.include <bsd.test.mk>

View File

@ -0,0 +1,6 @@
# $NetBSD: Makefile.inc,v 1.1 2023/08/26 05:27:14 riastradh Exp $
#
TESTSDIR= ${TESTSBASE}/usr.sbin/certctl
.include <bsd.own.mk>

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----

View File

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFijCCA3KgAwIBAgIQD////////////////////zANBgkqhkiG9w0BAQUFADBf
MQswCQYDVQQGEwJOTDESMBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdp
Tm90YXIgUm9vdCBDQTEgMB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmww
HhcNMDcwNzI3MTcxOTM3WhcNMjUwMzMxMTgxOTIyWjBfMQswCQYDVQQGEwJOTDES
MBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdpTm90YXIgUm9vdCBDQTEg
MB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmwwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCssFjBAL3YIQgLK5r+blYwBZ8bd5AQQVzDDYcRd46B
8cp86Yxq7Th0Nbva3/m7wAk3tJZzgX0zGpg595NvlX89ubF1h7pRSOiLcD6VBMXY
tsMW2YiwsYcdcNqGtA8Ui3rPENF0NqISe3eGSnnme98CEWilToauNFibJBN4ViIl
HgGLS1Fx+4LMWZZpiFpoU8W5DQI3y0u8ZkqQfioLBQftFl9VkHXYRskbg+IIvvEj
zJkd1ioPgyAVWCeCLvriIsJJsbkBgWqdbZ1Ad2h2TiEqbYRAhU52mXyC8/O3AlnU
JgEbjt+tUwbRrhjd4rI6y9eIOI6sWym5GdOY+RgDz0iChmYLG2kPyes4iHomGgVM
ktck1JbyrFIto0fVUvY//s6EBnCmqj6i8rZWNBhXouSBbefK8GrTx5FrAoNBfBXv
a5pkXuPQPOWx63tdhvvL5ndJzaNl3Pe5nLjkC1+Tz8wwGjIczhxjlaX56uF0i57p
K6kwe6AYHw4YC+VbqdPRbB4HZ4+RS6mKvNJmqpMBiLKR+jFc1abBUggJzQpjotMi
puih2TkGl/VujQKQjBR7P4DNG5y6xFhyI6+2Vp/GekIzKQc/gsnmHwUNzUwoNovT
yD4cxojvXu6JZOkd69qJfjKmadHdzIif0dDJZiHcBmfFlHqabWJMfczgZICynkeO
owIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
HQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wDQYJKoZIhvcNAQEFBQADggIBADsC
jcs8MOhuoK3yc7NfniUTBAXT9uOLuwt5zlPe5JbF0a9zvNXD0EBVfEB/zRtfCdXy
fJ9oHbtdzno5wozWmHvFg1Wo1X1AyuAe94leY12hE8JdiraKfADzI8PthV9xdvBo
Y6pFITlIYXg23PFDk9Qlx/KAZeFTAnVR/Ho67zerhChXDNjU1JlWbOOi/lmEtDHo
M/hklJRRl6s5xUvt2t2AC298KQ3EjopyDedTFLJgQT2EkTFoPSdE2+Xe9PpjRchM
Ppj1P0G6Tss3DbpmmPHdy59c91Q2gmssvBNhl0L4eLvMyKKfyvBovWsdst+Nbwed
2o5nx0ceyrm/KkKRt2NTZvFCo+H0Wk1Ya7XkpDOtXHAd3ODy63MUkZoDweoAZbwH
/M8SESIsrqC9OuCiKthZ6SnTGDWkrBFfGbW1G/8iSlzGeuQX7yCpp/Q/rYqnmgQl
nQ7KN+ZQ/YxCKQSa7LnPS3K94gg2ryMvYuXKAdNw23yCIywWMQzGNgeQerEfZ1jE
O1hZibCMjFCz2IbLaKPECudpSyDOwR5WS5WpI2jYMNjD67BVUc3l/Su49bsRn1NU
9jQZjHkJNsphFyUXC4KYcwx3dMPVDceoEkzHp1RxRy4sGn3J4ys7SN4nhKdjNrN9
j6BkOSQNPXuHr2ZcdBtLc7LljPCGmbjlxd+Ewbfr
-----END CERTIFICATE-----

View File

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.1 2023/08/26 05:27:14 riastradh Exp $
#
FILESDIR= ${TESTSDIR}/certs1
FILES+= DigiCert_Global_Root_CA.pem
FILES+= Explicitly_Distrust_DigiNotar_Root_CA.pem
.include <bsd.files.mk>
.include <bsd.inc.mk>

View File

@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo
27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w
Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw
TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl
qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH
szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8
Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk
MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p
aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN
VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID
AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb
C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy
h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4
7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J
ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef
MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/
Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT
6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ
0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm
2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb
bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
-----END CERTIFICATE-----

View File

@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
WD9f
-----END CERTIFICATE-----

View File

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.1 2023/08/26 05:27:14 riastradh Exp $
#
FILESDIR= ${TESTSDIR}/certs2
FILES+= GTS_Root_R1.pem
FILES+= GlobalSign_Root_CA_-_R3.pem
.include <bsd.files.mk>
.include <bsd.inc.mk>

View File

@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE
BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1
MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg
Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9
thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM
cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG
L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i
NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h
X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b
m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy
Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja
EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T
KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF
6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh
OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc
tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd
IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j
b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC
AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw
ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m
iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF
Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ
hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P
Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE
EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV
1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t
CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR
5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw
f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9
ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK
GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV
-----END CERTIFICATE-----

View File

@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE
BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy
MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg
Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9
thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM
cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG
L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i
NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h
X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b
m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy
Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja
EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T
KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF
6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh
OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD
VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD
VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv
ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl
AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF
661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9
am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1
ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481
PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS
3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k
SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF
3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM
ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g
StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz
Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB
jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
-----END CERTIFICATE-----

View File

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.1 2023/08/26 05:27:14 riastradh Exp $
#
FILESDIR= ${TESTSDIR}/certs3
FILES+= Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.1.pem
FILES+= Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.pem
.include <bsd.files.mk>
.include <bsd.inc.mk>

View File

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx
CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ
WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ
BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG
Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/
yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf
BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz
WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF
tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z
374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC
IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL
mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7
wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS
MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2
ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet
UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw
AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H
YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3
LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1
RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM
LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf
77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N
JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm
fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp
6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp
1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B
9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok
RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv
uu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
-----END CERTIFICATE-----

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----

View File

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.1 2023/08/26 05:27:15 riastradh Exp $
#
FILESDIR= ${TESTSDIR}/certs4
FILES+= AC_RAIZ_FNMT-RCM.pem
FILES+= DigiCert_Global_Root_CA.pem
.include <bsd.files.mk>
.include <bsd.inc.mk>

View File

@ -0,0 +1,333 @@
#!/bin/sh
# $NetBSD: t_certctl.sh,v 1.1 2023/08/26 05:27:14 riastradh Exp $
#
# Copyright (c) 2023 The NetBSD Foundation, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
CERTCTL="certctl -C certs.conf -c certs -u untrusted"
# setupconf <subdir>...
#
# Create certs/ and set up certs.conf to search the specified
# subdirectories of the source directory.
#
setupconf()
{
local sep subdir dir
mkdir certs
cat <<EOF >certs.conf
netbsd-certctl 20230816
# comment at line start
# comment not at line start, plus some intentional whitespace
# THE WHITESPACE ABOVE IS INTENTIONAL, DO NOT DELETE
EOF
# Start with a continuation line separator; then switch to
# non-continuation lines.
sep=$(printf ' \\\n\t')
for subdir; do
dir=$(atf_get_srcdir)/$subdir
cat <<EOF >>certs.conf
path$sep$(printf '%s' "$dir" | vis -M)
EOF
sep=' '
done
}
# check_empty
#
# Verify the certs directory is empty after dry runs or after
# clearing the directory.
#
check_empty()
{
local why
why=${1:-dry run}
for x in certs/*; do
if [ -e "$x" -o -h "$x" ]; then
atf_fail "certs/ should be empty after $why"
fi
done
}
# check_nonempty
#
# Verify the certs directory is nonempty.
#
check_nonempty()
{
for x in certs/*.0; do
test -e "$x" && test -h "$x" && return
done
atf_fail "certs/ should be nonempty"
}
# checks <certsN>...
#
# Run various checks with certctl.
#
checks()
{
local certs1 diginotar_base diginotar diginotar_hash subdir srcdir
certs1=$(atf_get_srcdir)/certs1
diginotar_base=Explicitly_Distrust_DigiNotar_Root_CA.pem
diginotar=$certs1/$diginotar_base
diginotar_hash=$(openssl x509 -hash -noout <$diginotar)
# Do a dry run of rehash and make sure the directory is still
# empty.
atf_check -s exit:0 $CERTCTL -n rehash
check_empty
# Distrust and trust one CA, as a dry run. The trust should
# fail because it's not currently distrusted.
atf_check -s exit:0 $CERTCTL -n untrust "$diginotar"
check_empty
atf_check -s not-exit:0 -e match:currently \
$CERTCTL -n trust "$diginotar"
check_empty
# Do a real rehash, not a dry run.
atf_check -s exit:0 $CERTCTL rehash
# Make sure all the certificates are trusted.
for subdir; do
case $subdir in
/*) srcdir=$subdir;;
*) srcdir=$(atf_get_srcdir)/$subdir;;
esac
for cert in "$srcdir"/*.pem; do
# Verify the certificate is linked by its base name.
certbase=$(basename "$cert")
atf_check -s exit:0 -o inline:"$cert" \
readlink -n "certs/$certbase"
# Verify the certificate is linked by a hash.
hash=$(openssl x509 -hash -noout <$cert)
counter=0
found=false
while [ $counter -lt 10 ]; do
if cmp -s "certs/$hash.$counter" "$cert"; then
found=true
break
fi
counter=$((counter + 1))
done
if ! $found; then
atf_fail "missing $cert"
fi
# Delete both links.
rm "certs/$certbase"
rm "certs/$hash.$counter"
done
done
# Verify the certificate bundle is there and delete it.
#
# XXX Verify its content.
atf_check -s exit:0 test -f certs/ca-certificates.crt
atf_check -s exit:0 test ! -h certs/ca-certificates.crt
rm certs/ca-certificates.crt
# Make sure after deleting everything there's nothing left.
check_empty "removing all expected certificates"
# Distrust, trust, and re-distrust one CA, and verify that it
# ceases to appear, reappears, and again ceases to appear.
# (This one has no subject hash collisions to worry about, so
# we hard-code the `.0' suffix.)
atf_check -s exit:0 $CERTCTL untrust "$diginotar"
atf_check -s exit:0 test -e "untrusted/$diginotar_base"
atf_check -s exit:0 test -h "untrusted/$diginotar_base"
atf_check -s exit:0 test ! -e "certs/$diginotar_base"
atf_check -s exit:0 test ! -h "certs/$diginotar_base"
atf_check -s exit:0 test ! -e "certs/$diginotar_hash.0"
atf_check -s exit:0 test ! -h "certs/$diginotar_hash.0"
check_nonempty
atf_check -s exit:0 $CERTCTL trust "$diginotar"
atf_check -s exit:0 test ! -e "untrusted/$diginotar_base"
atf_check -s exit:0 test ! -h "untrusted/$diginotar_base"
atf_check -s exit:0 test -e "certs/$diginotar_base"
atf_check -s exit:0 test -h "certs/$diginotar_base"
atf_check -s exit:0 test -e "certs/$diginotar_hash.0"
atf_check -s exit:0 test -h "certs/$diginotar_hash.0"
rm "certs/$diginotar_base"
rm "certs/$diginotar_hash.0"
check_nonempty
atf_check -s exit:0 $CERTCTL untrust "$diginotar"
atf_check -s exit:0 test -e "untrusted/$diginotar_base"
atf_check -s exit:0 test -h "untrusted/$diginotar_base"
atf_check -s exit:0 test ! -e "certs/$diginotar_base"
atf_check -s exit:0 test ! -h "certs/$diginotar_base"
atf_check -s exit:0 test ! -e "certs/$diginotar_hash.0"
atf_check -s exit:0 test ! -h "certs/$diginotar_hash.0"
check_nonempty
}
atf_test_case empty
empty_head()
{
atf_set "descr" "Test empty certificates store"
}
empty_body()
{
setupconf # no directories
check_empty "empty cert path"
atf_check -s exit:0 $CERTCTL -n rehash
check_empty
atf_check -s exit:0 $CERTCTL rehash
atf_check -s exit:0 test -f certs/ca-certificates.crt
atf_check -s exit:0 test \! -h certs/ca-certificates.crt
atf_check -s exit:0 test \! -s certs/ca-certificates.crt
atf_check -s exit:0 rm certs/ca-certificates.crt
check_empty "empty cert path"
}
atf_test_case onedir
onedir_head()
{
atf_set "descr" "Test one certificates directory"
}
onedir_body()
{
setupconf certs1
checks certs1
}
atf_test_case twodir
twodir_head()
{
atf_set "descr" "Test two certificates directories"
}
twodir_body()
{
setupconf certs1 certs2
checks certs1 certs2
}
atf_test_case collidehash
collidehash_head()
{
atf_set "descr" "Test colliding hashes"
}
collidehash_body()
{
# certs3 has two certificates with the same subject hash
setupconf certs1 certs3
checks certs1 certs3
}
atf_test_case collidebase
collidebase_head()
{
atf_set "descr" "Test colliding base names"
}
collidebase_body()
{
# certs1 and certs4 both have DigiCert_Global_Root_CA.pem,
# which should cause list and rehash to fail and mention
# duplicates.
setupconf certs1 certs4
atf_check -s not-exit:0 -o ignore -e match:duplicate $CERTCTL list
atf_check -s not-exit:0 -o ignore -e match:duplicate $CERTCTL rehash
}
atf_test_case manual
manual_head()
{
atf_set "descr" "Test manual operation"
}
manual_body()
{
local certs1 diginotar_base diginotar diginotar_hash
certs1=$(atf_get_srcdir)/certs1
diginotar_base=Explicitly_Distrust_DigiNotar_Root_CA.pem
diginotar=$certs1/$diginotar_base
diginotar_hash=$(openssl x509 -hash -noout <$diginotar)
setupconf certs1 certs2
cat <<EOF >>certs.conf
manual
EOF
touch certs/bogus.pem
ln -s bogus.pem certs/0123abcd.0
# Listing shouldn't mention anything in the certs/ cache.
atf_check -s exit:0 -o not-match:bogus $CERTCTL list
atf_check -s exit:0 -o not-match:bogus $CERTCTL untrusted
# Rehashing and changing the configuration should succeed, but
# mention `manual' in a warning message and should not touch
# the cache.
atf_check -s exit:0 -e match:manual $CERTCTL rehash
atf_check -s exit:0 -e match:manual $CERTCTL untrust "$diginotar"
atf_check -s exit:0 -e match:manual $CERTCTL trust "$diginotar"
# The files we created should still be there.
atf_check -s exit:0 test -f certs/bogus.pem
atf_check -s exit:0 test -h certs/0123abcd.0
}
atf_test_case evilpath
evilpath_head()
{
atf_set "descr" "Test certificate paths with evil characters"
}
evilpath_body()
{
local evildir
evildir="$(printf 'evil\n.')"
evildir=${evildir%.}
mkdir "$evildir"
cp -p "$(atf_get_srcdir)/certs2"/*.pem "$evildir"/
setupconf certs1
cat <<EOF >>certs.conf
path $(printf '%s' "$(pwd)/$evildir" | vis -M)
EOF
checks certs1 "$(pwd)/$evildir"
}
atf_init_test_cases()
{
atf_add_test_case collidebase
atf_add_test_case collidehash
atf_add_test_case empty
atf_add_test_case evilpath
atf_add_test_case manual
atf_add_test_case onedir
atf_add_test_case twodir
}

View File

@ -1,11 +1,11 @@
# $NetBSD: Makefile,v 1.291 2022/06/06 10:56:29 nia Exp $
# $NetBSD: Makefile,v 1.292 2023/08/26 05:27:15 riastradh Exp $
# from: @(#)Makefile 5.20 (Berkeley) 6/12/93
.include <bsd.own.mk>
SUBDIR= ac accton acpitools altq apm apmd arp autofs \
bad144 bootp bta2dpd btattach btconfig btdevctl bthcid btpand catman \
chroot cnwctl cpuctl crash \
certctl chroot cnwctl cpuctl crash \
dev_mkdb diskpart dumpfs dumplfs \
edquota eeprom envstat etcupdate extattrctl \
flashctl fssconfig fstyp fusermount fwctl \

10
usr.sbin/certctl/Makefile Normal file
View File

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.1 2023/08/26 05:27:15 riastradh Exp $
#
MAN= certctl.8
SCRIPTS= certctl.sh
FILESDIR= /etc/openssl
CONFIGFILES= certs.conf
.include <bsd.prog.mk>

337
usr.sbin/certctl/certctl.8 Normal file
View File

@ -0,0 +1,337 @@
.\" $NetBSD: certctl.8,v 1.1 2023/08/26 05:27:15 riastradh Exp $
.\"
.\" Copyright (c) 2023 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd August 16, 2023
.Dt CERTCTL 8
.Os
.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh NAME
.Nm certctl
.Nd configure OpenSSL certificate trust anchors
.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh SYNOPSIS
.Nm
.Op Fl nv
.Op Fl C Ar config
.Op Fl c Ar certsdir
.Op Fl u Ar distrustdir
.Ar cmd
.Op Ar args...
.\""""""""""""""""""
.Nm
.Oo Ar options Oc Cm list
.Nm
.Oo Ar options Oc Cm rehash
.Nm
.Oo Ar options Oc Cm trust Ar cert
.Nm
.Oo Ar options Oc Cm untrust Ar cert
.Nm
.Oo Ar options Oc Cm untrusted
.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh DESCRIPTION
The
.Nm
utility manages certificates used by OpenSSL-based applications as
trust anchors for certificate validation in HTTPS or other purposes.
.Nm
allows configuring the set of certificates and persistently excluding
individual certificates.
.Pp
For HTTPS certificate validation, OpenSSL applications typically
use either a directory at
.Pa /etc/openssl/certs
of hashed certificates in PEM format, with names like
.Pa "3513523f.0"
used for lookup
.Pq see Xr openssl_rehash 1 ,
or a single-file bundle at
.Pa /etc/openssl/certs/ca-certificates.crt
concatenating all the certificates in PEM format.
.Pp
.Nm
scans all directories in the certificate search path specified by the
configuration file
.Ar config
.Pq default: Pa /etc/openssl/certs.conf
for files called
.Pa *.cer ,
.Pa *.crt ,
or
.Pa *.pem
in PEM format, except for those that have been excluded by
.Nm Cm untrust ,
and keeps
.Ar certsdir
.Pq default: Pa /etc/openssl/certs
populated with symlinks to them.
.Pp
.Nm
treats
.Ar config
and
.Ar distrustdir
as configuration, and
.Ar certsdir
strictly as a cache that can be safely deleted and rebuilt with
.Nm Cm rehash .
.Nm
can also be instructed not to touch
.Ar certsdir
at all by putting
.Cm manual
in
.Ar config .
.
.\""""""""""""""""""""""""""""""""""""""
.Ss Commands
.Bl -tag -width Cm
.\""""""""""""""""""
.It Cm list
List absolute paths to trusted certificates, one per line, in
.Xr vis 1
format to encode any shell metacharacters, that
.Nm Cm rehash
would use to populate the
.Ar certsdir
cache.
.\""""""""""""""""""
.It Cm rehash
Populate
.Ar certsdir
with all trusted certificates, excluding any from
.Nm Cm untrust .
.\""""""""""""""""""
.It Cm trust Ar cert
Allow
.Ar cert
to be included in the certificate cache if it is in the certificate
search path, and rehash the certificate cache.
In other words, reverse the persistent effect of
.Nm Cm untrust Ar cert .
.Pp
.Ar cert
must be the full absolute path to a certificate that has been excluded
by
.Nm Cm untrust Ar cert .
.Pp
This does not add a new certificate which is not in the search path.
To do that, you can create a directory to hold it and put that
directory in the search path.
.\""""""""""""""""""
.It Cm untrust Ar cert
Persistently prevent
.Ar
from being included in the certificate cache, and rehash the
certificate cache.
.Pp
.Ar cert
must be the full absolute path to a certificate that is in the
certificate search path.
.\""""""""""""""""""
.It Cm untrusted
List absolute paths to untrusted certificates, one per line, in
.Xr vis 1
format to encode any shell metacharacters, that have been excluded by
.Nm Cm untrust
so that
.Nm Cm rehash
will not put them in
.Ar certsdir .
.\""""""""""""""""""
.El
.\""""""""""""""""""""""""""""""""""""""
.Ss Configuration file
The configuration file is a plain text file of lines separated by
.Tn US-ASCII
line feeds.
.Pp
.Pp
The first line must be:
.Dl netbsd-certctl 20230816
.Pp
Lines with only whitespace, or whitespace followed by the comment
character
.Ql #
are ignored.
Each line has a directive and arguments separated by whitespace, and
may be extended by
.Ql \e
to continuation lines.
.Bl -tag -width Cm
.\""""""""""""""""""
.It Cm path Ar dir
Add
.Ar dir
to the certificate search path.
.Ar dir
must be an absolute pathname,
.Xr vis 3 Ns -encoded .
.Pp
All certificates must have unique base names across all directories
in the certificate search path.
.\""""""""""""""""""
.It Cm manual
Manual override.
If specified,
.Nm
will
.Em not
modify
.Ar certsdir ,
but may still check consistency of the configuration when run and
update
.Ar distrustdir .
.\""""""""""""""""""
.El
.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh FILES
.Bl -tag -width Pa
.It Pa /etc/openssl/certs
Default directory of hashed HTTPS CA certificates.
.It Pa /etc/openssl/certs/ca-certificates.crt
Default single-file HTTPS CA certificate bundle.
.It Pa /etc/openssl/certs.conf
Default configuration file for HTTPS CA certificates.
.It Pa /etc/openssl/untrusted
Default
.Ar untrusted
directory of excluded HTTPS CA certificates.
.It Pa /usr/share/certs/mozilla/all
All root CA certificates published by Mozilla, including untrustworthy
certificates.
.It Pa /usr/share/certs/mozilla/code
All root CA certificates published by Mozilla for use in code-signing.
.It Pa /usr/share/certs/mozilla/email
All root CA certificates published by Mozilla for use in email
authentication.
.It Pa /usr/share/certs/mozilla/server
All root CA certificates published by Mozilla for use in HTTPS server
authentication.
.El
.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh EXAMPLES
Example configuration file
.Pq Pa /etc/openssl/certs.conf :
.Bd -literal -offset indent
netbsd-certctl 20230816
# Blank lines and comments are ignored.
# Comments begin with a `#' sign.
# Gather certificates from files called *.cer, *.crt, and *.pem
# under these directories.
path /usr/share/certs/mozilla/server
path /usr/pkg/share/chromium-cacerts
# If the next line is uncommented, certctl(8) will decline to
# touch /etc/openssl/certs.
#manual
.Ed
.Pp
Exclude a certificate:
.Bd -literal -offset indent
$ certctl untrust /usr/share/certs/mozilla/server/GTS_Root_R1.pem
.Ed
.Pp
There is no need to run
.Nm Cm rehash
explicitly after
.Nm Cm untrust ,
but if you do, the setting will persist.
.Pp
Rebuild the hashed certificate cache at
.Pa /etc/myapplication/certs
from
.Pa /etc/myapplication/certs.conf
and
.Pa /etc/myapplication/untrusted :
.Bd -literal -offset indent
$ certctl -c /etc/myapplication/certs \e
-C /etc/myapplication/certs.conf \e
-u /etc/myapplication/untrusted
.Ed
.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh DIAGNOSTICS
.Ex -std
.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh COMPATIBILITY
The
.Nm
utility is mostly compatible with a utility of the same name in
.Fx .
Differences:
.Bl -enum
.\""""""""""""""""""
.It
.Fx Nm
supports destdir/metalog handling;
.Nx Nm
does not.
.\""""""""""""""""""
.It
.Fx Nm
treats
.Pa /etc/ssl/certs
and
.Pa /etc/ssl/untrusted
both as configuration
.Em and
as caches;
.Nx Nm
treats
.Pa /etc/openssl/certs.conf
and
.Pa /etc/openssl/untrusted
as configuration, and treats
.Pa /etc/openssl/certs
strictly as a cache.
.Fx Nm
will forget any
.Nm Cm untrust
settings on
.Nm Cm rehash ,
but
.Nx Nm
will remember them.
.\""""""""""""""""""
.It
.Fx Nm
takes configuration through environment variables;
.Nx Nm
takes configuration through a file and command-line arguments.
.El
.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh SEE ALSO
.Xr openssl 1 ,
.Xr openssl_rehash 1
.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh HISTORY
.Nm
first appeared in
.Nx 10.0 .
A utility of the same name previously appeared in
.Fx 12.2 .

658
usr.sbin/certctl/certctl.sh Executable file
View File

@ -0,0 +1,658 @@
#!/bin/sh
# $NetBSD: certctl.sh,v 1.1 2023/08/26 05:27:15 riastradh Exp $
#
# Copyright (c) 2023 The NetBSD Foundation, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
set -o pipefail
set -Ceu
progname=$(basename -- "$0")
### Options and arguments
usage()
{
exec >&2
printf 'Usage: %s %s\n' \
"$progname" \
"[-nv] [-C <config>] [-c <certsdir>] [-u <untrusted>]"
printf ' <cmd> <args>...\n'
printf ' %s list\n' "$progname"
printf ' %s rehash\n' "$progname"
printf ' %s trust <cert>\n' "$progname"
printf ' %s untrust <cert>\n' "$progname"
printf ' %s untrusted\n' "$progname"
exit 1
}
certsdir=/etc/openssl/certs
config=/etc/openssl/certs.conf
distrustdir=/etc/openssl/untrusted
nflag=false # dry run
vflag=false # verbose
# Options used by FreeBSD:
#
# -D destdir
# -M metalog
# -U (unprivileged)
# -d distbase
#
while getopts C:c:nu:v f; do
case $f in
C) config=$OPTARG;;
c) certsdir=$OPTARG;;
n) nflag=true;;
u) distrustdir=$OPTARG;;
v) vflag=true;;
\?) usage;;
esac
done
shift $((OPTIND - 1))
if [ $# -lt 1 ]; then
usage
fi
cmd=$1
### Global state
config_paths=
config_manual=false
tmpfile=
# If tmpfile is set to nonempty, clean it up on exit.
trap 'test -n "$tmpfile" && rm -f "$tmpfile"' EXIT HUP INT TERM
### Subroutines
# error <msg> ...
#
# Print an error message to stderr.
#
# Does not exit the process.
#
error()
{
echo "$progname:" "$@" >&2
}
# run <cmd> <args>...
#
# Print a command if verbose, and run it unless it's a dry run.
#
run()
{
local t q cmdline
if $vflag; then # print command if verbose
for t; do
case $t in
''|*[^[:alnum:]+,-./:=_@]*)
# empty or unsafe -- quotify
;;
*)
# nonempty and safe-only -- no quotify
cmdline="${cmdline:+$cmdline }$t"
continue
;;
esac
q=$(printf '%s' "$t" | sed -e "s/'/'\\\''/g'")
cmdline="${cmdline:+$cmdline }'$q'"
done
printf '%s\n' "$cmdline"
fi
if ! $nflag; then # skip command if dry run
"$@"
fi
}
# configure
#
# Parse the configuration file, initializing config_*.
#
configure()
{
local lineno status formatok vconfig line contline op path vpath vop
# Count line numbers, record a persistent error status to
# return at the end, and record whether we got a format line.
lineno=0
status=0
formatok=false
# vis the config name for terminal-safe error messages.
vconfig=$(printf '%s' "$config" | vis -M)
# Read and process each line of the config file.
while read -r line; do
lineno=$((lineno + 1))
# If the line ends in an odd number of backslashes, it
# has a continuation line, so read on.
while expr "$line" : '^\(\\\\\)*\\' >/dev/null ||
expr "$line" : '^.*[^\\]\(\\\\\)*\\$' >/dev/null; do
if ! read -r contline; then
error "$vconfig:$lineno: premature end of file"
return 1
fi
line="$line$contline"
done
# Skip blank lines and comments.
case $line in
''|'#'*)
continue
;;
esac
# Require the first non-blank/comment line to identify
# the config file format.
if ! $formatok; then
if [ "$line" = "netbsd-certctl 20230816" ]; then
formatok=true
continue
else
error "$vconfig:$lineno: missing format line"
status=1
break
fi
fi
# Split the line into words and dispatch on the first.
set -- $line
op=$1
case $op in
manual)
config_manual=true
;;
path)
if [ $# -lt 2 ]; then
error "$vconfig:$lineno: missing path"
status=1
continue
fi
if [ $# -gt 3 ]; then
error "$vconfig:$lineno: excess args"
status=1
continue
fi
# Unvis the path. Hack: if the user has had
# the audacity to choose a path ending in
# newlines, prevent the shell from consuming
# them so we don't choke on their subterfuge.
path=$(printf '%s.' "$2" | unvis)
path=${path%.}
# Ensure the path is absolute. It is unclear
# what directory it should be relative to if
# not.
case $path in
/*)
;;
*)
error "$vconfig:$lineno:" \
"relative path forbidden"
status=1
continue
;;
esac
# Record the vis-encoded path in a
# space-separated list.
vpath=$(printf '%s' "$path" | vis -M)
config_paths="$config_paths $vpath"
;;
*)
vop=$(printf '%s' "$op" | vis -M)
error "$vconfig:$lineno: unknown command: $vop"
;;
esac
done <$config
return $status
}
# list_default_trusted
#
# List the vis-encoded certificate paths and their base names,
# separated by a space, for the certificates that are trusted by
# default according to the configuration.
#
# No order guaranteed; caller must sort.
#
list_default_trusted()
{
local vpath path cert base vcert vbase
for vpath in $config_paths; do
path=$(printf '%s.' "$vpath" | unvis)
path=${path%.}
# Enumerate the .pem, .cer, and .crt files.
for cert in "$path"/*.pem "$path"/*.cer "$path"/*.crt; do
# vis the certificate path.
vcert=$(printf '%s' "$cert" | vis -M)
# If the file doesn't exist, then either:
#
# (a) it's a broken symlink, so fail;
# or
# (b) the shell glob failed to match,
# so ignore it and move on.
if [ ! -e "$cert" ]; then
if [ -h "$cert" ]; then
error "broken symlink: $vcert"
status=1
fi
continue
fi
# Print the vis-encoded absolute path to the
# certificate and base name on a single line.
vbase=$(basename -- "$vcert.")
vbase=${vbase%.}
printf '%s %s\n' "$vcert" "$vbase"
done
done
}
# list_distrusted
#
# List the vis-encoded certificate paths and their base names,
# separated by a space, for the certificates that have been
# distrusted by the user.
#
# No order guaranteed; caller must sort.
#
list_distrusted()
{
local status link vlink cert vcert
status=0
for link in "$distrustdir"/*; do
# vis the link for terminal-safe error messages.
vlink=$(printf '%s' "$link" | vis -M)
# The distrust directory must only have symlinks to
# certificates. If we find a non-symlink, print a
# warning and arrange to fail.
if [ ! -h "$link" ]; then
if [ ! -e "$link" ] && \
[ "$link" = "$distrustdir/*" ]; then
# Shell glob matched nothing -- just
# ignore it.
break
fi
error "distrusted non-symlink: $vlink"
status=1
continue
fi
# Read the target of the symlink, nonrecursively. If
# the user has had the audacity to make a symlink whose
# target ends in newline, prevent the shell from
# consuming them so we don't choke on their subterfuge.
cert=$(readlink -n -- "$link" && printf .)
cert=${cert%.}
# Warn if the target is relative. Although it is clear
# what directory it would be relative to, there might
# be issues with canonicalization.
case $cert in
/*)
;;
*)
vlink=$(printf '%s' "$link" | vis -M)
vcert=$(printf '%s' "$cert" | vis -M)
error "distrusted relative symlink: $vlink -> $vcert"
;;
esac
# Print the vis-encoded absolute path to the
# certificate and base name on a single line.
vcert=$(printf '%s' "$cert" | vis -M)
vbase=$(basename -- "$vcert.")
vbase=${vbase%.}
printf '%s %s\n' "$vcert" "$vbase"
done
return $status
}
# list_trusted
#
# List the trusted certificates, excluding the distrusted one, as
# one vis(3) line per certificate. Reject duplicate base names,
# since we will be creating symlinks to the same base names in
# the certsdir. Sorted lexicographically by vis-encoding.
#
list_trusted()
{
# XXX Use dev/ino to match files instead of symlink targets?
{
list_default_trusted \
| while read -r vcert vbase; do
printf 'trust %s %s\n' "$vcert" "$vbase"
done
# XXX Find a good way to list the default-untrusted
# certificates, so if you have already distrusted one
# and it is removed from default-trust on update,
# nothing warns about this.
# list_default_untrusted \
# | while read -r vcert vbase; do
# printf 'distrust %s %s\n' "$vcert" "$vbase"
# done
list_distrusted \
| while read -r vcert vbase; do
printf 'distrust %s %s\n' "$vcert" "$vbase"
done
} | awk -v progname="$progname" '
BEGIN { status = 0 }
$1 == "trust" && $3 in trust && $2 != trust[$3] {
printf "%s: duplicate base name %s\n %s\n %s\n", \
progname, $3, trust[$3], $2 >"/dev/stderr"
status = 1
next
}
$1 == "trust" { trust[$3] = $2 }
$1 == "distrust" && !trust[$3] && !distrust[$3] {
printf "%s: distrusted certificate not found: %s\n", \
progname, $3 >"/dev/stderr"
status = 1
}
$1 == "distrust" && $2 in trust && $2 != trust[$3] {
printf "%s: distrusted certificate %s" \
" has multiple paths\n" \
" %s\n %s\n",
progname, $3, trust[$3], $2 >"/dev/stderr"
status = 1
}
$1 == "distrust" { distrust[$3] = 1 }
END {
for (vbase in trust) {
if (!distrust[vbase])
print trust[vbase]
}
exit status
}
' | sort -u
}
# rehash
#
# Delete and rebuild certsdir.
#
rehash()
{
local vcert cert certbase hash counter bundle vbundle
# If manual operation is enabled, refuse to rehash the
# certsdir, but succeed anyway so this can safely be used in
# automated scripts.
if $config_manual; then
error "manual certificates enabled, not rehashing"
return
fi
# Delete the active certificates symlink cache.
run rm -rf "$certsdir"
run mkdir "$certsdir"
# Create a temporary file for the single-file bundle. This
# will be automatically deleted on normal exit or
# SIGHUP/SIGINT/SIGTERM.
if ! $nflag; then
tmpfile=$(mktemp -t "$progname.XXXXXX")
fi
# Recreate symlinks for all of the trusted certificates.
list_trusted \
| while read -r vcert; do
cert=$(printf '%s.' "$vcert" | unvis)
cert=${cert%.}
run ln -s -- "$cert" "$certsdir"
# Add the certificate to the single-file bundle.
if ! $nflag; then
cat -- "$cert" >>$tmpfile
fi
done
# Hash the directory with openssl.
#
# XXX Pass `-v' to openssl in a way that doesn't mix with our
# shell-safe verbose commands? (Need to handle `-n' too.)
run openssl rehash -- "$certsdir"
# Install the single-file bundle.
bundle=$certsdir/ca-certificates.crt
vbundle=$(printf '%s' "$bundle" | vis -M)
$vflag && printf '# create %s\n' "$vbundle"
if ! $nflag; then
cp -- "$tmpfile" "$bundle"
rm -f -- "$tmpfile"
tmpfile=
fi
}
### Commands
usage_list()
{
exec >&2
printf 'Usage: %s list\n' "$progname"
exit 1
}
cmd_list()
{
test $# -eq 1 || usage_list
configure
list_trusted \
| while read -r vcert vbase; do
printf '%s\n' "$vcert"
done
}
usage_rehash()
{
exec >&2
printf 'Usage: %s rehash\n' "$progname"
exit 1
}
cmd_rehash()
{
test $# -eq 1 || usage_rehash
configure
rehash
}
usage_trust()
{
exec >&2
printf 'Usage: %s trust <cert>\n' "$progname"
exit 1
}
cmd_trust()
{
local cert vcert certbase vcertbase
test $# -eq 2 || usage_trust
cert=$2
configure
# XXX Accept base name.
# vis the certificate path for terminal-safe error messages.
vcert=$(printf '%s' "$cert" | vis -M)
# Verify the certificate actually exists.
if [ ! -f "$cert" ]; then
error "no such certificate: $vcert"
return 1
fi
# Verify we currently distrust a certificate by this base name.
certbase=$(basename -- "$cert.")
certbase=${certbase%.}
if [ ! -h "$distrustdir/$certbase" ]; then
error "not currently distrusted: $vcert"
return 1
fi
# Verify the certificate we distrust by this base name is the
# same one.
target=$(readlink -n -- "$distrustdir/$certbase" && printf .)
target=${target%.}
if [ "$cert" != "$target" ]; then
vcertbase=$(basename -- "$vcert")
error "distrusted $vcertbase does not point to $vcert"
return 1
fi
# Remove the link from the distrusted directory, and rehash --
# quietly, so verbose output emphasizes the distrust part and
# not the whole certificate set.
run rm -- "$distrustdir/$certbase"
$vflag && echo '# rehash'
vflag=false
rehash
}
usage_untrust()
{
exec >&2
printf 'Usage: %s untrust <cert>\n' "$progname"
exit 1
}
cmd_untrust()
{
local cert vcert certbase vcertbase target vtarget
test $# -eq 2 || usage_untrust
cert=$2
configure
# vis the certificate path for terminal-safe error messages.
vcert=$(printf '%s' "$cert" | vis -M)
# Verify the certificate actually exists. Otherwise, you might
# fail to distrust a certificate you intended to distrust,
# e.g. if you made a typo in its path.
if [ ! -f "$cert" ]; then
error "no such certificate: $vcert"
return 1
fi
# Check whether this certificate is already distrusted.
# - If the same base name points to the same path, stop here.
# - Otherwise, fail noisily.
certbase=$(basename "$cert.")
certbase=${certbase%.}
if [ -h "$distrustdir/$certbase" ]; then
target=$(readlink -n -- "$distrustdir/$certbase" && printf .)
target=${target%.}
if [ "$target" = "$cert" ]; then
$vflag && echo '# already distrusted'
return
fi
vcertbase=$(printf '%s' "$certbase" | vis -M)
vtarget=$(printf '%s' "$target" | vis -M)
error "distrusted $vcertbase at different path $vtarget"
return 1
fi
# Create the distrustdir if needed, create a symlink in it, and
# rehash -- quietly, so verbose output emphasizes the distrust
# part and not the whole certificate set.
test -d "$distrustdir" || run mkdir -- "$distrustdir"
run ln -s -- "$cert" "$distrustdir"
$vflag && echo '# rehash'
vflag=false
rehash
}
usage_untrusted()
{
exec >&2
printf 'Usage: %s untrusted\n' "$progname"
exit 1
}
cmd_untrusted()
{
test $# -eq 1 || usage_untrusted
configure
list_distrusted \
| while read -r vcert vbase; do
printf '%s\n' "$vcert"
done
}
### Main
# We accept the following aliases for user interface compatibility with
# FreeBSD:
#
# blacklist = untrust
# blacklisted = untrusted
# unblacklist = trust
case $cmd in
list) cmd_list "$@"
;;
rehash) cmd_rehash "$@"
;;
trust|unblacklist)
cmd_trust "$@"
;;
untrust|blacklist)
cmd_untrust "$@"
;;
untrusted|blacklisted)
cmd_untrusted "$@"
;;
*) vcmd=$(printf '%s' "$cmd" | vis -M)
printf '%s: unknown command: %s\n' "$progname" "$vcmd" >&2
usage
;;
esac

View File

@ -0,0 +1,13 @@
netbsd-certctl 20230816
# $NetBSD: certs.conf,v 1.1 2023/08/26 05:27:15 riastradh Exp $
#
# Configuration file for certctl(8) to manage HTTPS root CA
# certificates in /etc/openssl/certs.
#
path /usr/share/certs/mozilla/server
# For manual control over /etc/openssl/certs, e.g. if you want to
# install a separate CA bundle from pkgsrc, uncomment the next line:
#manual