Index: usr.sbin/certctl/certctl.sh =================================================================== --- usr.sbin/certctl/certctl.sh +++ usr.sbin/certctl/certctl.sh @@ -39,6 +39,7 @@ ERRORS=0 NOOP=0 UNPRIV=0 +BLACKLIST_HASHPATH= ############################################################ FUNCTIONS @@ -79,7 +80,7 @@ hash=$( do_hash "$1" ) || return certhash=$( openssl x509 -sha1 -in "$1" -noout -fingerprint ) - for blistfile in $(find $BLACKLISTDESTDIR -name "$hash.*"); do + for blistfile in $(find $BLACKLIST_HASHPATH -name "$hash.*"); do blisthash=$( openssl x509 -sha1 -in "$blistfile" -noout -fingerprint ) if [ "$certhash" = "$blisthash" ]; then echo "Skipping blacklisted certificate $1 ($blistfile)" @@ -102,13 +103,13 @@ if [ -e "$1" ]; then hash=$( do_hash "$1" ) || return srcfile=$(realpath "$1") - suffix=$(get_decimal "$BLACKLISTDESTDIR" "$hash") + suffix=$(get_decimal "$BLACKLIST_HASHPATH" "$hash") filename="$hash.$suffix" echo "$srcfile" "$hash.$suffix" elif [ -e "${CERTDESTDIR}/$1" ]; then srcfile=$(realpath "${CERTDESTDIR}/$1") hash=$(echo "$1" | sed -Ee 's/\.([0-9])+$//') - suffix=$(get_decimal "$BLACKLISTDESTDIR" "$hash") + suffix=$(get_decimal "$BLACKLIST_HASHPATH" "$hash") filename="$hash.$suffix" echo "$srcfile" "$hash.$suffix" fi @@ -118,16 +119,72 @@ { local srcfile filename + if [ -z "${BLACKLIST_HASHPATH}" ]; then + BLACKLIST_HASHPATH=$(mktemp -d ${TMPDIR:-/tmp}/certctl.XXXXXXX) + trap 'rm -rf ${BLACKLIST_HASHPATH}' 0 + fi + set -- $(resolve_certname "$1") - srcfile=$1 - filename=$2 + srcfile="$1" + filename="$2" - if [ -z "$srcfile" -o -z "$filename" ]; then + if [ -z "${srcfile}" -o -z "${filename}" ]; then return fi [ $VERBOSE -gt 0 ] && echo "Adding $filename to blacklist" - [ $NOOP -eq 0 ] && install ${INSTALLFLAGS} -lrs "$srcfile" "$BLACKLISTDESTDIR/$filename" + [ $NOOP -eq 0 ] && install ${INSTALLFLAGS} -lrs "${srcfile}" "${BLACKLIST_HASHPATH}/${filename}" +} + +add_blacklisted() +{ + local srcfile filename + + set -- $(resolve_certname "$1") + srcfile="$1" + filename="$2" + + if [ -z "${srcfile}" -o -z "${filename}" ]; then + return + fi + + [ $VERBOSE -gt 0 ] && echo "Installing $filename to $BLACKLISTDESTDIR" + + # Install the entirety of the file as-is here, so that we don't risk a + # broken symlink removing the entry. + [ $NOOP -eq 0 ] && install ${INSTALLFLAGS} "${srcfile}" "${BLACKLISTDESTDIR}" +} + +remove_blacklisted() +{ + local BFILE blistfile blisthash blistpath certhash + local oldIFS + + BFILE="$1" + oldIFS="$IFS" + IFS=: + set -- $BLACKLISTPATH + IFS="$oldIFS" + + if [ ! -s "${BFILE}" ]; then + echo "Cannot find ${BFILE}" >&2 + ERRORS=$(( ${ERRORS} + 1 )) + return + fi + + certhash=$( openssl x509 -sha256 -in "${BFILE}" -noout -fingerprint ) + for blistpath in "$@"; do + if [ ! -d "${blistpath}" ]; then + continue + fi + for blistfile in $(ls -1 "${blistpath}" | grep -Ee "${FILEPAT}"); do + blisthash=$( openssl x509 -sha256 -in "${blistpath}/${blistfile}" -noout -fingerprint ) + if [ "${certhash}" = "${blisthash}" ]; then + echo "Removing ${blistpath}/${blistfile}" + [ $NOOP -eq 0 ] && rm -f "${blistpath}/${blistfile}" + fi + done + done } do_scan() @@ -153,7 +210,9 @@ do_list() { - local CFILE subject + local CFILE subject ffunc + + ffunc="$2" if [ -e "$1" ]; then cd "$1" @@ -170,7 +229,11 @@ fi [ "$subject" ] || subject=$( openssl x509 -noout -subject -in "$CFILE" ) - printf "%s\t%s\n" "$CFILE" "$subject" + if [ -z "$ffunc" ]; then + printf "%s\t%s\n" "$CFILE" "$subject" + else + "$ffunc" "$CFILE" "$subject" + fi done cd - fi @@ -185,11 +248,6 @@ else mkdir -p "$CERTDESTDIR" fi - if [ -e "$BLACKLISTDESTDIR" ]; then - find "$BLACKLISTDESTDIR" -type link -delete - else - mkdir -p "$BLACKLISTDESTDIR" - fi fi do_scan create_blacklisted "$BLACKLISTPATH" @@ -210,40 +268,35 @@ [ $NOOP -eq 0 ] && mkdir -p "$BLACKLISTDESTDIR" for BFILE in "$@"; do echo "Adding $BFILE to blacklist" - create_blacklisted "$BFILE" + add_blacklisted "$BFILE" done } cmd_unblacklist() { - local BFILE blisthash certhash hash + local BFILE shift # verb for BFILE in "$@"; do - if [ -s "$BFILE" ]; then - hash=$( do_hash "$BFILE" ) - certhash=$( openssl x509 -sha1 -in "$BFILE" -noout -fingerprint ) - for BLISTEDFILE in $(find $BLACKLISTDESTDIR -name "$hash.*"); do - blisthash=$( openssl x509 -sha1 -in "$BLISTEDFILE" -noout -fingerprint ) - if [ "$certhash" = "$blisthash" ]; then - echo "Removing $(basename "$BLISTEDFILE") from blacklist" - [ $NOOP -eq 0 ] && rm -f $BLISTEDFILE - fi - done - 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 + remove_blacklisted "$BFILE" done } +blacklist_formatter() +{ + local cfile subject + + cfile=$(realpath "$1") + subject="$2" + + printf "%s\t%s\n" "$cfile" "$subject" +} + cmd_blacklisted() { + do_scan create_blacklisted "$BLACKLISTPATH" >/dev/null echo "Listing Blacklisted Certificates:" - do_list "$BLACKLISTDESTDIR" + do_list "$BLACKLIST_HASHPATH" blacklist_formatter } usage() @@ -281,9 +334,9 @@ [ $UNPRIV -eq 1 ] && INSTALLFLAGS="-U -M ${METALOG} -D ${DESTDIR}" : ${LOCALBASE:=$(sysctl -n user.localbase)} : ${TRUSTPATH:=${DESTDIR}/usr/share/certs/trusted:${DESTDIR}${LOCALBASE}/share/certs:${DESTDIR}${LOCALBASE}/etc/ssl/certs} -: ${BLACKLISTPATH:=${DESTDIR}/usr/share/certs/blacklisted:${DESTDIR}${LOCALBASE}/etc/ssl/blacklisted} +: ${BLACKLISTDESTDIR:=${DESTDIR}${LOCALBASE}/share/certs/blacklisted} +: ${BLACKLISTPATH:=${DESTDIR}/usr/share/certs/blacklisted:${DESTDIR}${LOCALBASE}/etc/ssl/blacklisted:${BLACKLISTDESTDIR}} : ${CERTDESTDIR:=${DESTDIR}/etc/ssl/certs} -: ${BLACKLISTDESTDIR:=${DESTDIR}/etc/ssl/blacklisted} [ $# -gt 0 ] || usage case "$1" in