[2/3] Add certctl(8)
This is a simple utility to hash all trusted on the system into /etc/ssl/certs. It also allows the user to blacklist certificates they do not trust. This work was done primarily by allanjude@, with minor contributions by myself. No objection from: secteam Differential Revision: https://reviews.freebsd.org/D16857
This commit is contained in:
parent
4ed49b4dcb
commit
345af4051a
@ -124,6 +124,9 @@ SUBDIR.${MK_BLUETOOTH}+= bluetooth
|
||||
SUBDIR.${MK_BOOTPARAMD}+= bootparamd
|
||||
SUBDIR.${MK_BSDINSTALL}+= bsdinstall
|
||||
SUBDIR.${MK_BSNMP}+= bsnmpd
|
||||
.if ${MK_CAROOT} != "no"
|
||||
SUBDIR.${MK_OPENSSL}+= certctl
|
||||
.endif
|
||||
SUBDIR.${MK_CXGBETOOL}+= cxgbetool
|
||||
SUBDIR.${MK_DIALOG}+= bsdconfig
|
||||
SUBDIR.${MK_EFI}+= efivar efidp efibootmgr
|
||||
|
6
usr.sbin/certctl/Makefile
Normal file
6
usr.sbin/certctl/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SCRIPTS=certctl.sh
|
||||
MAN= certctl.8
|
||||
|
||||
.include <bsd.prog.mk>
|
119
usr.sbin/certctl/certctl.8
Normal file
119
usr.sbin/certctl/certctl.8
Normal file
@ -0,0 +1,119 @@
|
||||
.\"
|
||||
.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
.\"
|
||||
.\" Copyright 2018 Allan Jude <allanjude@freebsd.org>
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted providing 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 AUTHOR ``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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 19, 2019
|
||||
.Dt CERTCTL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm certctl
|
||||
.Nd "tool for managing trusted and blacklist TLS certificates"
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl v
|
||||
.Ic list
|
||||
.Nm
|
||||
.Op Fl v
|
||||
.Ic blacklisted
|
||||
.Nm
|
||||
.Op Fl nv
|
||||
.Ic rehash
|
||||
.Nm
|
||||
.Op Fl nv
|
||||
.Ic blacklist Ar file
|
||||
.Nm
|
||||
.Op Fl nv
|
||||
.Ic unblacklist Ar file
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility manages the list of TLS Certificate Authorities that are trusted by
|
||||
applications that use OpenSSL.
|
||||
.Pp
|
||||
Flags:
|
||||
.Bl -tag -width 4n
|
||||
.It Fl n
|
||||
No-Op mode, do not actually perform any actions.
|
||||
.It Fl v
|
||||
be verbose, print details about actions before performing them.
|
||||
.El
|
||||
.Pp
|
||||
Primary command functions:
|
||||
.Bl -tag -width blacklisted
|
||||
.It Ic list
|
||||
List all currently trusted certificate authorities.
|
||||
.It Ic blacklisted
|
||||
List all currently blacklisted certificates.
|
||||
.It Ic rehash
|
||||
Rebuild the list of trusted certificate authorities by scanning all directories
|
||||
in
|
||||
.Ev TRUSTPATH
|
||||
and all blacklisted certificates in
|
||||
.Ev BLACKLISTPATH .
|
||||
A symbolic link to each trusted certificate is placed in
|
||||
.Ev CERTDESTDIR
|
||||
and each blacklisted certificate in
|
||||
.Ev BLACKLISTDESTDIR .
|
||||
.It Ic blacklist
|
||||
Add the specified file to the blacklist.
|
||||
.It Ic unblacklist
|
||||
Remove the specified file from the blacklist.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width BLACKLISTDESTDIR
|
||||
.It Ev DESTDIR
|
||||
Alternate destination directory to operate on.
|
||||
.It Ev TRUSTPATH
|
||||
List of paths to search for trusted certificates.
|
||||
Default:
|
||||
.Pa <DESTDIR>/usr/share/certs/trusted
|
||||
.Pa <DESTDIR>/usr/local/share/certs <DESTDIR>/usr/local/etc/ssl/certs
|
||||
.It Ev BLACKLISTPATH
|
||||
List of paths to search for blacklisted certificates.
|
||||
Default:
|
||||
.Pa <DESTDIR>/usr/share/certs/blacklisted
|
||||
.Pa <DESTDIR>/usr/local/etc/ssl/blacklisted
|
||||
.It Ev CERTDESTDIR
|
||||
Destination directory for symbolic links to trusted certificates.
|
||||
Default:
|
||||
.Pa <DESTDIR>/etc/ssl/certs
|
||||
.It Ev BLACKLISTDESTDIR
|
||||
Destination directory for symbolic links to blacklisted certificates.
|
||||
Default:
|
||||
.Pa <DESTDIR>/etc/ssl/blacklisted
|
||||
.It Ev EXTENSIONS
|
||||
List of file extensions to read as certificate files.
|
||||
Default: *.pem *.crt *.cer *.crl *.0
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr openssl 1
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
first appeared in
|
||||
.Fx 12.0
|
||||
.Sh AUTHORS
|
||||
.An Allan Jude Aq Mt allanjude@freebsd.org
|
230
usr.sbin/certctl/certctl.sh
Executable file
230
usr.sbin/certctl/certctl.sh
Executable file
@ -0,0 +1,230 @@
|
||||
#!/bin/sh
|
||||
#-
|
||||
# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
#
|
||||
# Copyright 2018 Allan Jude <allanjude@freebsd.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted providing 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 AUTHOR ``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 AUTHOR 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.
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
############################################################ CONFIGURATION
|
||||
|
||||
: ${DESTDIR:=}
|
||||
: ${TRUSTPATH:=${DESTDIR}/usr/share/certs/trusted:${DESTDIR}/usr/local/share/certs:${DESTDIR}/usr/local/etc/ssl/certs}
|
||||
: ${BLACKLISTPATH:=${DESTDIR}/usr/share/certs/blacklisted:${DESTDIR}/usr/local/etc/ssl/blacklisted}
|
||||
: ${CERTDESTDIR:=${DESTDIR}/etc/ssl/certs}
|
||||
: ${BLACKLISTDESTDIR:=${DESTDIR}/etc/ssl/blacklisted}
|
||||
: ${EXTENSIONS:="*.pem *.crt *.cer *.crl *.0"}
|
||||
: ${VERBOSE:=0}
|
||||
|
||||
############################################################ GLOBALS
|
||||
|
||||
SCRIPTNAME="${0##*/}"
|
||||
ERRORS=0
|
||||
NOOP=0
|
||||
|
||||
############################################################ FUNCTIONS
|
||||
|
||||
do_hash()
|
||||
{
|
||||
local hash
|
||||
|
||||
if hash=$( openssl x509 -noout -subject_hash -in "$1" ); then
|
||||
echo "$hash"
|
||||
return 0
|
||||
else
|
||||
echo "Error: $1" >&2
|
||||
ERRORS=$(( $ERRORS + 1 ))
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
create_trusted_link()
|
||||
{
|
||||
local hash
|
||||
|
||||
hash=$( do_hash "$1" ) || return
|
||||
if [ -e "$BLACKLISTDESTDIR/$hash.0" ]; then
|
||||
echo "Skipping blacklisted certificate $1 ($BLACKLISTDESTDIR/$hash.0)"
|
||||
return 1
|
||||
fi
|
||||
[ $VERBOSE -gt 0 ] && echo "Adding $hash.0 to trust store"
|
||||
[ $NOOP -eq 0 ] && ln -fs "$1" "$CERTDESTDIR/$hash.0"
|
||||
}
|
||||
|
||||
create_blacklisted()
|
||||
{
|
||||
local hash
|
||||
|
||||
hash=$( do_hash "$1" ) || return
|
||||
[ $VERBOSE -gt 0 ] && echo "Adding $hash.0 to blacklist"
|
||||
[ $NOOP -eq 0 ] && ln -fs "$1" "$BLACKLISTDESTDIR/$hash.0"
|
||||
}
|
||||
|
||||
do_scan()
|
||||
{
|
||||
local CFUNC CSEARCH CPATH CFILE
|
||||
local oldIFS="$IFS"
|
||||
CFUNC="$1"
|
||||
CSEARCH="$2"
|
||||
|
||||
IFS=:
|
||||
set -- $CSEARCH
|
||||
IFS="$oldIFS"
|
||||
for CPATH in "$@"; do
|
||||
[ -d "$CPATH" ] || continue
|
||||
echo "Scanning $CPATH for certificates..."
|
||||
cd "$CPATH"
|
||||
for CFILE in $EXTENSIONS; do
|
||||
[ -e "$CFILE" ] || continue
|
||||
[ $VERBOSE -gt 0 ] && echo "Reading $CFILE"
|
||||
"$CFUNC" "$CPATH/$CFILE"
|
||||
done
|
||||
cd -
|
||||
done
|
||||
}
|
||||
|
||||
do_list()
|
||||
{
|
||||
local CFILE subject
|
||||
|
||||
if [ -e "$1" ]; then
|
||||
cd "$1"
|
||||
for CFILE in *.0; do
|
||||
if [ ! -s "$CFILE" ]; then
|
||||
echo "Unable to read $CFILE" >&2
|
||||
ERRORS=$(( $ERRORS + 1 ))
|
||||
continue
|
||||
fi
|
||||
subject=
|
||||
if [ $VERBOSE -eq 0 ]; then
|
||||
subject=$( openssl x509 -noout -subject -nameopt multiline -in "$CFILE" |
|
||||
sed -n '/commonName/s/.*= //p' )
|
||||
fi
|
||||
[ "$subject" ] ||
|
||||
subject=$( openssl x509 -noout -subject -in "$CFILE" )
|
||||
printf "%s\t%s\n" "$CFILE" "$subject"
|
||||
done
|
||||
cd -
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_rehash()
|
||||
{
|
||||
|
||||
[ $NOOP -eq 0 ] && rm -rf "$CERTDESTDIR"
|
||||
[ $NOOP -eq 0 ] && mkdir -p "$CERTDESTDIR"
|
||||
[ $NOOP -eq 0 ] && mkdir -p "$BLACKLISTDESTDIR"
|
||||
|
||||
do_scan create_blacklisted "$BLACKLISTPATH"
|
||||
do_scan create_trusted_link "$TRUSTPATH"
|
||||
}
|
||||
|
||||
cmd_list()
|
||||
{
|
||||
echo "Listing Trusted Certificates:"
|
||||
do_list "$CERTDESTDIR"
|
||||
}
|
||||
|
||||
cmd_blacklist()
|
||||
{
|
||||
local BPATH
|
||||
|
||||
shift # verb
|
||||
[ $NOOP -eq 0 ] && mkdir -p "$BLACKLISTDESTDIR"
|
||||
for BFILE in "$@"; do
|
||||
echo "Adding $BFILE to blacklist"
|
||||
create_blacklisted "$BFILE"
|
||||
done
|
||||
}
|
||||
|
||||
cmd_unblacklist()
|
||||
{
|
||||
local BFILE hash
|
||||
|
||||
shift # verb
|
||||
for BFILE in "$@"; do
|
||||
if [ -s "$BFILE" ]; then
|
||||
hash=$( do_hash "$BFILE" )
|
||||
echo "Removing $hash.0 from blacklist"
|
||||
[ $NOOP -eq 0 ] && rm -f "$BLACKLISTDESTDIR/$hash.0"
|
||||
elif [ -e "$BLACKLISTDESTDIR/$BFILE" ]; then
|
||||
echo "Removing $BFILE from blacklist"
|
||||
[ $NOOP -eq 0 ] && rm -f "$BLACKLISTDESTDIR/$BFILE"
|
||||
else
|
||||
echo "Cannot find $BFILE" >&2
|
||||
ERRORS=$(( $ERRORS + 1 ))
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
cmd_blacklisted()
|
||||
{
|
||||
echo "Listing Blacklisted Certificates:"
|
||||
do_list "$BLACKLISTDESTDIR"
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
exec >&2
|
||||
echo "Manage the TLS trusted certificates on the system"
|
||||
echo " $SCRIPTNAME [-v] list"
|
||||
echo " List trusted certificates"
|
||||
echo " $SCRIPTNAME [-v] blacklisted"
|
||||
echo " List blacklisted certificates"
|
||||
echo " $SCRIPTNAME [-nv] rehash"
|
||||
echo " Generate hash links for all certificates"
|
||||
echo " $SCRIPTNAME [-nv] blacklist <file>"
|
||||
echo " Add <file> to the list of blacklisted certificates"
|
||||
echo " $SCRIPTNAME [-nv] unblacklist <file>"
|
||||
echo " Remove <file> from the list of blacklisted certificates"
|
||||
exit 64
|
||||
}
|
||||
|
||||
############################################################ MAIN
|
||||
|
||||
while getopts nv flag; do
|
||||
case "$flag" in
|
||||
n) NOOP=1 ;;
|
||||
v) VERBOSE=$(( $VERBOSE + 1 )) ;;
|
||||
esac
|
||||
done
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
[ $# -gt 0 ] || usage
|
||||
case "$1" in
|
||||
list) cmd_list ;;
|
||||
rehash) cmd_rehash ;;
|
||||
blacklist) cmd_blacklist "$@" ;;
|
||||
unblacklist) cmd_unblacklist "$@" ;;
|
||||
blacklisted) cmd_blacklisted ;;
|
||||
*) usage # NOTREACHED
|
||||
esac
|
||||
|
||||
retval=$?
|
||||
[ $ERRORS -gt 0 ] && echo "Encountered $ERRORS errors" >&2
|
||||
exit $retval
|
||||
|
||||
################################################################################
|
||||
# END
|
||||
################################################################################
|
Loading…
Reference in New Issue
Block a user