From owner-svn-src-head@freebsd.org Wed Oct 2 01:05:54 2019 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 999BFFD0AD; Wed, 2 Oct 2019 01:05:54 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 46jdHQ3HHPz4bpW; Wed, 2 Oct 2019 01:05:54 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 5455E23D4A; Wed, 2 Oct 2019 01:05:54 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x9215s67007391; Wed, 2 Oct 2019 01:05:54 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x9215rI4007388; Wed, 2 Oct 2019 01:05:53 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201910020105.x9215rI4007388@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Wed, 2 Oct 2019 01:05:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r352949 - in head/usr.sbin: . certctl X-SVN-Group: head X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in head/usr.sbin: . certctl X-SVN-Commit-Revision: 352949 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Oct 2019 01:05:54 -0000 Author: kevans Date: Wed Oct 2 01:05:53 2019 New Revision: 352949 URL: https://svnweb.freebsd.org/changeset/base/352949 Log: [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 Added: head/usr.sbin/certctl/ head/usr.sbin/certctl/Makefile (contents, props changed) head/usr.sbin/certctl/certctl.8 (contents, props changed) head/usr.sbin/certctl/certctl.sh (contents, props changed) Modified: head/usr.sbin/Makefile Modified: head/usr.sbin/Makefile ============================================================================== --- head/usr.sbin/Makefile Wed Oct 2 01:05:29 2019 (r352948) +++ head/usr.sbin/Makefile Wed Oct 2 01:05:53 2019 (r352949) @@ -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 Added: head/usr.sbin/certctl/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/certctl/Makefile Wed Oct 2 01:05:53 2019 (r352949) @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SCRIPTS=certctl.sh +MAN= certctl.8 + +.include Added: head/usr.sbin/certctl/certctl.8 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/certctl/certctl.8 Wed Oct 2 01:05:53 2019 (r352949) @@ -0,0 +1,119 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD +.\" +.\" Copyright 2018 Allan Jude +.\" +.\" 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 /usr/share/certs/trusted +.Pa /usr/local/share/certs /usr/local/etc/ssl/certs +.It Ev BLACKLISTPATH +List of paths to search for blacklisted certificates. +Default: +.Pa /usr/share/certs/blacklisted +.Pa /usr/local/etc/ssl/blacklisted +.It Ev CERTDESTDIR +Destination directory for symbolic links to trusted certificates. +Default: +.Pa /etc/ssl/certs +.It Ev BLACKLISTDESTDIR +Destination directory for symbolic links to blacklisted certificates. +Default: +.Pa /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 Added: head/usr.sbin/certctl/certctl.sh ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/certctl/certctl.sh Wed Oct 2 01:05:53 2019 (r352949) @@ -0,0 +1,230 @@ +#!/bin/sh +#- +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# +# Copyright 2018 Allan Jude +# +# 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 " + echo " Add to the list of blacklisted certificates" + echo " $SCRIPTNAME [-nv] unblacklist " + echo " Remove 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 +################################################################################