910 lines
29 KiB
Bash
910 lines
29 KiB
Bash
#!/bin/bash
|
|
# Begin /usr/sbin/make-ca
|
|
#
|
|
# Script to create p11-kit anchors, OpenSSL certs directory, GnuTLS certificate
|
|
# bundle, NSS shared DB, and Java cacerts from upstream certdata.txt and local
|
|
# sources
|
|
#
|
|
# Authors: DJ Lucas
|
|
# Bruce Dubbs
|
|
# Graham Weldon
|
|
|
|
shopt -s extglob;
|
|
|
|
VERSION="1.8"
|
|
MAKE_CA_CONF="/etc/make-ca.conf"
|
|
|
|
# Get/set defaults
|
|
if test -f "${MAKE_CA_CONF}"; then
|
|
. "${MAKE_CA_CONF}"
|
|
else
|
|
CERTDATA="certdata.txt"
|
|
PKIDIR="/etc/pki"
|
|
SSLDIR="/etc/ssl"
|
|
CERTUTIL="/usr/bin/certutil"
|
|
KEYTOOL="${JAVA_HOME}/bin/keytool"
|
|
MD5SUM="/usr/bin/md5sum"
|
|
OPENSSL="/usr/bin/openssl"
|
|
TRUST="/usr/bin/trust"
|
|
ANCHORDIR="${PKIDIR}/anchors"
|
|
ANCHORLIST="${PKIDIR}/anchors.md5sums"
|
|
BUNDLEDIR="${PKIDIR}/tls/certs"
|
|
CABUNDLE="${BUNDLEDIR}/ca-bundle.crt"
|
|
SMBUNDLE="${BUNDLEDIR}/email-ca-bundle.crt"
|
|
CSBUNDLE="${BUNDLEDIR}/objsign-ca-bundle.crt"
|
|
CERTDIR="${SSLDIR}/certs"
|
|
KEYSTORE="${PKIDIR}/tls/java"
|
|
NSSDB="${PKIDIR}/nssdb"
|
|
LOCALDIR="${SSLDIR}/local"
|
|
DESTDIR=""
|
|
URL="https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt"
|
|
fi
|
|
|
|
# Some data in the certs have UTF-8 characters
|
|
# It doesn't really matter which locale, change if you like
|
|
export LANG=en_US.utf8
|
|
|
|
TEMPDIR=$(mktemp -d)
|
|
WORKDIR="${TEMPDIR}/work"
|
|
CERTDATAY=0
|
|
FORCE=0
|
|
GET=0
|
|
REBUILD=0
|
|
WITH_P12=0
|
|
WITH_NSS=0
|
|
|
|
function get_args(){
|
|
while test -n "${1}" ; do
|
|
case "${1}" in
|
|
-C | --certdata)
|
|
if test "${REBUILD}" == "0" -a "${GET}" == "0"; then
|
|
check_arg $1 $2
|
|
CERTDATA="${2}"
|
|
CERTDATAY="1"
|
|
shift 2
|
|
else
|
|
echo "Error: ${1} cannot be used with the -r/--rebuild or -g/--get switches."
|
|
exit 3
|
|
fi
|
|
if test ! -f "${CERTDATA}" -a "${GET}" == "0"; then
|
|
echo "Error: ${CERTDATA} not found!"
|
|
exit 3
|
|
fi
|
|
;;
|
|
-D | --destdir)
|
|
check_arg $1 $2
|
|
DESTDIR="${2}"
|
|
echo ${DESTDIR} | grep -q "^\." && DESTDIR="${PWD}/${DESTDIR}"
|
|
shift 2
|
|
;;
|
|
-P | --pkidir)
|
|
check_arg $1 $2
|
|
PKIDIR="${2}"
|
|
ANCHORDIR="${PKIDIR}/anchors"
|
|
NSSDB="${PKIDIR}/nssdb"
|
|
echo "${@}" | grep -e "-a " -e "--anchordir" \
|
|
-e "-n " -e "--nssdb" > /dev/null
|
|
if test "${?}" == "0"; then
|
|
echo "Error! ${1} cannot be used with the -a/--anchordir or -n/--nssdb switches."
|
|
echo ""
|
|
exit 3
|
|
fi
|
|
shift 2
|
|
;;
|
|
-S | --ssldir)
|
|
check_arg $1 $2
|
|
SSLDIR="${2}"
|
|
CERTDIR="${SSLDIR}/certs"
|
|
LOCALDIR="${SSLDIR}/local"
|
|
echo "${@}" | grep -e "-d " -e "--cadir" > /dev/null 2>&1
|
|
if test "${?}" == "0"; then
|
|
echo "Error! ${1} cannot be used with the -d/--cadir switch."
|
|
echo ""
|
|
exit 3
|
|
fi
|
|
|
|
shift 2
|
|
;;
|
|
-a | --anchordir)
|
|
check_arg $1 $2
|
|
ANCHORDIR="${2}"
|
|
echo "${@}" | grep -e "-P " -e "--pkidir" > /dev/null 2>&1
|
|
if test "${?}" == "0"; then
|
|
echo "Error! ${1} cannot be used with the -P/--pkidir switch."
|
|
echo ""
|
|
exit 3
|
|
fi
|
|
shift 2
|
|
;;
|
|
-b | --bundledir)
|
|
check_arg $1 $2
|
|
BUNDLEDIR="${2}"
|
|
shift 2
|
|
;;
|
|
-d | --cadir)
|
|
check_arg $1 $2
|
|
CERTDIR="${2}"
|
|
echo "$@" | grep -e "-S" -e "--ssldir" > /dev/null 2>&1
|
|
if test "${?}" == "0"; then
|
|
echo "Error! ${1} cannot be used with the -S/--ssldir switch."
|
|
echo ""
|
|
exit 3
|
|
fi
|
|
shift 2
|
|
;;
|
|
-g | --get)
|
|
if test "${REBUILD}" == "0" -a "${CERTDATAY}" == "0"; then
|
|
GET="1"
|
|
CERTDATA="${TEMPDIR}/certdatanew.txt"
|
|
shift 1
|
|
else
|
|
echo "Error: ${1} cannot be used with the -r/--rebuild or -C/--certdata switches."
|
|
exit 3
|
|
fi
|
|
;;
|
|
-j | --javacerts)
|
|
check_arg $1 $2
|
|
KEYSTORE="${2}"
|
|
shift 2
|
|
;;
|
|
-k | --keytool)
|
|
check_arg $1 $2
|
|
KEYTOOL="${2}"
|
|
shift 2
|
|
;;
|
|
-l | --localdir)
|
|
check_arg $1 $2
|
|
LOCALDIR="${2}"
|
|
shift 2
|
|
;;
|
|
-m | --java-p12)
|
|
WITH_P12="1"
|
|
shift 1
|
|
;;
|
|
-n | --nssdb)
|
|
echo "${2}" | grep -v "^-" > /dev/null
|
|
if [ "$?" -ne "0" -o ! -n "$2" ]; then
|
|
WITH_NSS="1"
|
|
shift 1
|
|
else
|
|
NSSDB="${2}"
|
|
WITH_NSS="1"
|
|
echo "${@}" | grep -e "-P " -e "--pkidir" > /dev/null
|
|
if test "${?}" == "0"; then
|
|
echo "Error! ${1} cannot be used with both an argument and the -P/--pkidir switch."
|
|
echo ""
|
|
exit 3
|
|
fi
|
|
shift 2
|
|
fi
|
|
;;
|
|
-p | --proxy)
|
|
check_arg $1 $2
|
|
PROXY="${2}"
|
|
shift 2
|
|
;;
|
|
-r | --rebuild)
|
|
if test "${CERTDATAY}" == "0" -a "${GET}" == "0"; then
|
|
REBUILD="1"
|
|
FORCE="1"
|
|
shift 1
|
|
else
|
|
echo "Error: ${1} cannot be used with the -C/--certdata or -g/--get switches."
|
|
exit 3
|
|
fi
|
|
;;
|
|
-s | --openssl)
|
|
check_arg $1 $2
|
|
OPENSSL="${2}"
|
|
shift 2
|
|
;;
|
|
-t | --certutil)
|
|
check_arg $1 $2
|
|
CERTUTIL="${2}"
|
|
WITH_NSS="1"
|
|
shift 2
|
|
;;
|
|
-u | --trust)
|
|
check_arg $1 $2
|
|
TRUST="${2}"
|
|
shift 2
|
|
;;
|
|
-f | --force)
|
|
FORCE="1"
|
|
shift 1
|
|
;;
|
|
-h | --help)
|
|
showhelp
|
|
exit 0
|
|
;;
|
|
-v | --version)
|
|
echo -e "$(basename ${0}) ${VERSION}\n"
|
|
exit 0
|
|
;;
|
|
# Handle getopt style short args (use extglob instead of loop)
|
|
-+([a-z,A-Z]))
|
|
# split up the arguments and call recursively with trailing break
|
|
arg="${1}"
|
|
newargs=$( echo ${1} | sed 's@-@@' | \
|
|
sed 's/.\{1\}/& /g' | \
|
|
sed 's/[^ ]* */-&/g')
|
|
newargs="${newargs} $(echo ${@} | sed "s@${arg}@@")"
|
|
get_args ${newargs}
|
|
break;
|
|
;;
|
|
*)
|
|
showhelp
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
function check_arg(){
|
|
echo "${2}" | grep "^-" > /dev/null
|
|
if [ "$?" == "0" -o ! -n "$2" ]; then
|
|
echo "Error: $1 requires a valid argument."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function showhelp(){
|
|
echo ""
|
|
echo "`basename ${0}` is a utility to deliver and manage a complete PKI configuration"
|
|
echo "for workstations and servers using only standard GNU utilities, OpenSSL, and"
|
|
echo "P11-Kit. It will optionally generate keystores for NSS if already installed,"
|
|
echo "using a Mozilla cacerts.txt or like formatted file. It was originally developed"
|
|
echo "for use with Linux From Scratch to minimize dependencies for early system"
|
|
echo "build, but has been written to be generic enough for any Linux distribution."
|
|
echo ""
|
|
echo " -C, --certdata [certdata.txt]"
|
|
echo " The location of the certificates source"
|
|
echo ""
|
|
echo " -D, --destdir [/]"
|
|
echo " Change the output directory and use relative"
|
|
echo " paths for all other values"
|
|
echo ""
|
|
echo " -P, --pkidir [/etc/pki]"
|
|
echo " The output PKI root directory - Cannot be used"
|
|
echo " with the -a / --anchordir or"
|
|
echo " -n / --nssdb switches"
|
|
echo ""
|
|
echo " -S, --ssldir [/etc/ssl]"
|
|
echo " The output SSL root direcotry - Cannot be used"
|
|
echo " with the -d / --cadir switch"
|
|
echo ""
|
|
echo " -a, --anchordir [\$PKIDIR/anchors]"
|
|
echo " The output directory for .p11-kit trust anchors"
|
|
echo ""
|
|
echo " -b, --bundledir [\$PKIDIR/certs]"
|
|
echo " The output direcotry for the PEM formated"
|
|
echo " bundles"
|
|
echo ""
|
|
echo " -d, --cadir [\$SSLDIR/certs]"
|
|
echo " The output directory for the OpenSSL trusted"
|
|
echo " CA certificates"
|
|
echo ""
|
|
echo " -j, --javacerts [\$PKIDIR/java/cacerts]"
|
|
echo " The output directory for the Java cacerts"
|
|
echo " file(s)"
|
|
echo ""
|
|
echo " -l, --localdir [\$SSLDIR/local]"
|
|
echo " The path to a local set of OpenSSL trusted"
|
|
echo " certificates, used to both override trust bits"
|
|
echo " from upstream source and provide system local"
|
|
echo " certifiates"
|
|
echo ""
|
|
echo " -m, --java-p12"
|
|
echo " Export Java PKCS#12 store - this will default to"
|
|
echo " \$PKIDIR/java/cacerts.p12 unless modified by"
|
|
echo " the '-j/--javacerts' switch"
|
|
echo ""
|
|
echo " -n, --nssdb {\$PKIDIR/nssdb}"
|
|
echo " The output path for the shared NSS DB"
|
|
echo ""
|
|
echo " -p, --proxy [URI:PORT]"
|
|
echo " Use proxy server for download"
|
|
echo ""
|
|
echo " -k, --keytool [\$JAVA_HOME/bin/keytool]"
|
|
echo " The path of the Java keytool utility"
|
|
echo ""
|
|
echo " -s, --openssl [/usr/bin/openssl]"
|
|
echo " The path of the openssl utility"
|
|
echo ""
|
|
echo " -t, --certutil [/usr/bin/certutil]"
|
|
echo " The path of the NSS certutil utility"
|
|
echo ""
|
|
echo " -u, --trust [/usr/bin/trust]"
|
|
echo " The path of the p11-kit trust utility"
|
|
echo ""
|
|
echo " -f, --force Force run, even if source is not newer"
|
|
echo ""
|
|
echo " -g, --get Download certdata.txt directly from Mozilla's"
|
|
echo " Mecurial server"
|
|
echo ""
|
|
echo " -h, --help Show this help message and exit"
|
|
echo ""
|
|
echo " -r, --rebuild Rebuild the entire PKI tree using the previous"
|
|
echo " certdata.txt file"
|
|
echo ""
|
|
echo " -v. --version Show version information and exit"
|
|
echo ""
|
|
echo "Example: `basename ${0}` -f -C ~/certdata.txt"
|
|
echo ""
|
|
}
|
|
|
|
# Convert CKA_TRUST values to trust flags for certutil
|
|
function convert_trust(){
|
|
case $1 in
|
|
CKT_NSS_TRUSTED_DELEGATOR)
|
|
echo "C"
|
|
;;
|
|
CKT_NSS_NOT_TRUSTED)
|
|
echo "p"
|
|
;;
|
|
CKT_NSS_MUST_VERIFY_TRUST)
|
|
echo ""
|
|
;;
|
|
esac
|
|
}
|
|
|
|
function convert_moz_distrust(){
|
|
# SERVER
|
|
val=$(grep "CKA_NSS_SERVER_DISTRUST_AFTER" "${1}" | cut -d " " -f 2)
|
|
if test "${val}" == "CK_BBOOL"; then
|
|
val=$(grep "CKA_NSS_SERVER_DISTRUST_AFTER" "${1}" | cut -d " " -f 3)
|
|
if test "${val}" == "CK_FALSE"; then
|
|
mozsadistrust="%00"
|
|
else
|
|
mozsadistrust="UNKNOWN"
|
|
fi
|
|
elif test "${val}" == "MULTILINE_OCTAL"; then
|
|
mozsadistrust=`printf $(grep -A1 "CKA_NSS_SERVER_DISTRUST_AFTER" "${1}" | tail -n1)`
|
|
else
|
|
mozsadistrust="UNKNOWN"
|
|
fi
|
|
|
|
# EMAIL
|
|
val=$(grep "CKA_NSS_EMAIL_DISTRUST_AFTER" "${1}" | cut -d " " -f 2)
|
|
if test "${val}" == "CK_BBOOL"; then
|
|
val=$(grep "CKA_NSS_EMAIL_DISTRUST_AFTER" "${1}" | cut -d " " -f 3)
|
|
if test "${val}" == "CK_FALSE"; then
|
|
mozsmdistrust="%00"
|
|
else
|
|
mozsmdistrust="UNKNOWN"
|
|
fi
|
|
elif test "${val}" == "MULTILINE_OCTAL"; then
|
|
mozsmdistrust=`printf $(grep -A1 "CKA_NSS_EMAIL_DISTRUST_AFTER" "${1}" | tail -n1)`
|
|
else
|
|
mozsmdistrust="UNKNOWN"
|
|
fi
|
|
unset val
|
|
}
|
|
|
|
function convert_trust_arg(){
|
|
case $1 in
|
|
C)
|
|
case $2 in
|
|
sa)
|
|
echo "-addtrust serverAuth"
|
|
;;
|
|
sm)
|
|
echo "-addtrust emailProtection"
|
|
;;
|
|
cs)
|
|
echo "-addtrust codeSigning"
|
|
;;
|
|
ca)
|
|
echo "-addtrust clientAuth"
|
|
;;
|
|
esac
|
|
;;
|
|
p)
|
|
case $2 in
|
|
sa)
|
|
echo "-addreject serverAuth"
|
|
;;
|
|
sm)
|
|
echo "-addreject emailProtection"
|
|
;;
|
|
cs)
|
|
echo "-addreject codeSigning"
|
|
;;
|
|
ca)
|
|
echo "-addreject clientAuth"
|
|
;;
|
|
esac
|
|
;;
|
|
*)
|
|
echo ""
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Define p11-kit ext value constants (see p11-kit API documentation)
|
|
function get_p11_val() {
|
|
case $1 in
|
|
p11sasmcs)
|
|
p11value="0%2a%06%03U%1d%25%01%01%ff%04 0%1e%06%08%2b%06%01%05%05%07%03%04%06%08%2b%06%01%05%05%07%03%01%06%08%2b%06%01%05%05%07%03%03"
|
|
;;
|
|
|
|
p11sasm)
|
|
p11value="0 %06%03U%1d%25%01%01%ff%04%160%14%06%08%2b%06%01%05%05%07%03%04%06%08%2b%06%01%05%05%07%03%01"
|
|
;;
|
|
|
|
p11sacs)
|
|
p11value="0 %06%03U%1d%25%01%01%ff%04%160%14%06%08%2b%06%01%05%05%07%03%01%06%08%2b%06%01%05%05%07%03%03"
|
|
;;
|
|
|
|
p11sa)
|
|
p11value="0%16%06%03U%1d%25%01%01%ff%04%0c0%0a%06%08%2b%06%01%05%05%07%03%01"
|
|
;;
|
|
|
|
p11smcs)
|
|
p11value="0 %06%03U%1d%25%01%01%ff%04%160%14%06%08%2b%06%01%05%05%07%03%04%06%08%2b%06%01%05%05%07%03%03"
|
|
;;
|
|
|
|
p11sm)
|
|
p11value="0%16%06%03U%1d%25%01%01%ff%04%0c0%0a%06%08%2b%06%01%05%05%07%03%04"
|
|
;;
|
|
|
|
p11cs)
|
|
p11value="0%16%06%03U%1d%25%01%01%ff%04%0c0%0a%06%08%2b%06%01%05%05%07%03%03"
|
|
;;
|
|
|
|
p11)
|
|
p11value="0%18%06%03U%1d%25%01%01%ff%04%0e0%0c%06%0a%2b%06%01%04%01%99w%06%0a%10"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
function get_p11_label() {
|
|
# $1 == individual nss certificate extracted from certdata.txt
|
|
# or x509 certificate with OpenSSL text values
|
|
|
|
subjectline=$(grep -m1 "Subject:" ${1} | sed 's@\s*=\s*@=@g')
|
|
|
|
p11label="$(echo ${subjectline} | grep -o "CN=.*$" | cut -d ',' -f 1 | sed 's@CN=@@')"
|
|
|
|
# Fallback to the last OU value if CN does not exeist in Subject string
|
|
if [ "${p11label}" == "" ]; then
|
|
p11label="$(echo ${subjectline} | grep -o "OU=.*$" | sed 's@OU=.*, OU=@OU=@g'| cut -d ',' -f 1 | sed 's@OU=@@')"
|
|
|
|
# If still empty, fall back to Object value as a last resort
|
|
if [ "${p11label}" == "" ]; then
|
|
p11label="$(echo ${subjectline} | grep -o "O=.*$" | cut -d ',' -f 1 | sed 's@O=@@')"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function get_trust_values() {
|
|
# $1 == individual certificate extracted from NSS certdata.txt
|
|
|
|
# Determine certificate trust values for SSL/TLS, S/MIME, and Code Signing
|
|
satrust="$(convert_trust `grep '^CKA_TRUST_SERVER_AUTH' ${1} | \
|
|
cut -d " " -f 3`)"
|
|
smtrust="$(convert_trust `grep '^CKA_TRUST_EMAIL_PROTECTION' ${1} | \
|
|
cut -d " " -f 3`)"
|
|
cstrust="$(convert_trust `grep '^CKA_TRUST_CODE_SIGNING' ${1} | \
|
|
cut -d " " -f 3`)"
|
|
# Not currently included in NSS certdata.txt
|
|
#catrust="$(convert_trust `grep '^CKA_TRUST_CLIENT_AUTH' ${1} | \
|
|
# cut -d " " -f 3`)"
|
|
|
|
# Determine distrust values
|
|
convert_moz_distrust ${1}
|
|
}
|
|
|
|
function get_p11_trust() {
|
|
# if distrusted at all, x-distrusted
|
|
if test "${satrust}" == "p" -o "${smtrust}" == "p" -o "${cstrust}" == "p"
|
|
then
|
|
# if any distrusted, x-distrusted
|
|
p11trust="x-distrusted: true"
|
|
p11oid="1.3.6.1.4.1.3319.6.10.1"
|
|
p11value="0.%06%0a%2b%06%01%04%01%99w%06%0a%01%04 0%1e%06%08%2b%06%01%05%05%07%03%04%06%08%2b%06%01%05%05%07%03%01%06%08%2b%06%01%05%05%07%03%03"
|
|
else
|
|
p11trust="trusted: true"
|
|
p11oid="2.5.29.37"
|
|
trustp11="p11"
|
|
if test "${satrust}" == "C"; then
|
|
trustp11="${trustp11}sa"
|
|
fi
|
|
if test "${smtrust}" == "C"; then
|
|
trustp11="${trustp11}sm"
|
|
fi
|
|
if test "${cstrust}" == "C"; then
|
|
trustp11="${trustp11}cs"
|
|
fi
|
|
get_p11_val "${trustp11}"
|
|
fi
|
|
|
|
}
|
|
|
|
function write_anchor() {
|
|
echo "[p11-kit-object-v1]" >> "${anchorfile}"
|
|
echo "label: \"${p11label}\"" >> "${anchorfile}"
|
|
echo "class: x-certificate-extension" >> "${anchorfile}"
|
|
echo "object-id: ${p11oid}" >> "${anchorfile}"
|
|
echo "value: \"${p11value}\"" >> "${anchorfile}"
|
|
echo "modifiable: false" >> "${anchorfile}"
|
|
echo "${certkey}" >> "${anchorfile}"
|
|
echo "" >> "${anchorfile}"
|
|
echo "[p11-kit-object-v1]" >> "${anchorfile}"
|
|
echo "label: \"${p11label}\"" >> "${anchorfile}"
|
|
echo "${p11trust}" >> "${anchorfile}"
|
|
echo "nss-mozilla-ca-policy: ${moz_trust}" >> "${anchorfile}"
|
|
echo "modifiable: false" >> "${anchorfile}"
|
|
if test "${mozsadistrust}" != "UNKNOWN"; then
|
|
echo "nss-server-distrust-after: \"${mozsadistrust}\"" >> "${anchorfile}"
|
|
fi
|
|
if test "${mozsmdistrust}" != "UNKNOWN"; then
|
|
echo "nss-email-distrust-after: \"${mozsmdistrust}\"" >> "${anchorfile}"
|
|
fi
|
|
echo "${certcer}" >> "${anchorfile}"
|
|
echo "${certtxt}" | sed 's@^@#@' >> "${anchorfile}"
|
|
echo "Added to p11-kit anchor directory with trust '${satrust},${smtrust},${cstrust}'."
|
|
}
|
|
|
|
function write_nss_db() {
|
|
# $1 == NSS database
|
|
# $2 == x509 certificate in PEM format
|
|
|
|
"${CERTUTIL}" -d "sql:${1}" -A \
|
|
-t "${satrust},${smtrust},${cstrust}" \
|
|
-n "${p11label}" -i "${2}" > /dev/null 2>&1
|
|
echo "Added to NSS shared DB with trust '${satrust},${smtrust},${cstrust}'."
|
|
}
|
|
|
|
function write_java_p12() {
|
|
# $1 == cacerts.p12 file
|
|
# $2 == x509 certificate in PEM format
|
|
|
|
# Remove existing certificate
|
|
"${KEYTOOL}" -delete -noprompt -alias "${p11label}" \
|
|
-keystore "${1}" \
|
|
-storepass 'changeit' > /dev/null 2>&1
|
|
# Determine ExtendedKeyUsage
|
|
EKU=""
|
|
EKUVAL=""
|
|
if test "${satrust}" == "C"; then EKU="serverAuth"; fi
|
|
if test "${smtrust}" == "C"; then
|
|
if test "${EKU}" == ""; then
|
|
EKU="clientAuth"
|
|
else
|
|
EKU="${EKU},clientAuth"
|
|
fi
|
|
fi
|
|
if test "${cstrust}" == "C"; then
|
|
if test "${EKU}" == ""; then
|
|
EKU="codeSigning"
|
|
else
|
|
EKU="${EKU},codeSigning"
|
|
fi
|
|
fi
|
|
if test "${EKU}" != ""; then
|
|
EKUVAL="-ext EKU=${EKU}"
|
|
"${KEYTOOL}" -importcert -file "${2}" -storetype PKCS12 \
|
|
-noprompt -alias "${p11label}" -storepass 'changeit' \
|
|
-keystore "${1}" $EKUVAL \
|
|
> /dev/null 2>&1
|
|
echo "Added to Java cacerts (PKCS#12) with trust '${satrust},${smtrust},${cstrust}'."
|
|
unset EKU
|
|
unset EKUVAL
|
|
fi
|
|
}
|
|
|
|
# Process command line arguments
|
|
get_args $@
|
|
|
|
test ! -x "${OPENSSL}" && \
|
|
echo "OpenSSL not found at ${OPENSSL}. Exiting..." && exit 1
|
|
mkdir -p "${TEMPDIR}"/{certs,pki/anchors,work}
|
|
|
|
if test "${WITH_P12}" -eq "1"; then
|
|
test ! -x "${KEYTOOL}" && \
|
|
echo "Java keytool not found at ${KEYTOOL}. Exiting..." && exit 1
|
|
mkdir -p "${TEMPDIR}/ssl/java"
|
|
fi
|
|
|
|
if test "${WITH_NSS}" -eq "1"; then
|
|
test ! -x "${CERTUTIL}" && \
|
|
echo "NSS certutil not found at ${CERTUTIL}. Exiting..." && exit 1
|
|
# Create a blank NSS DB
|
|
mkdir -p "${TEMPDIR}/pki/nssdb"
|
|
"${CERTUTIL}" -N --empty-password -d "sql:${TEMPDIR}/pki/nssdb"
|
|
fi
|
|
|
|
# Download certdata.txt if selected
|
|
if test "${GET}" == "1"; then
|
|
echo -n "Checking for new version of certdata.txt..."
|
|
HOST=$(echo "${URL}" | /usr/bin/cut -d / -f 3)
|
|
_url=$(echo "${URL}" | sed 's@raw-file@log@')
|
|
SARGS="-ign_eof -connect ${HOST}:443"
|
|
if test "${PROXY}x" != "x"; then
|
|
SARGS="${SARGS} -proxy ${PROXY}"
|
|
fi
|
|
echo GET ${_url} | \
|
|
${OPENSSL} s_client ${SARGS} 2> /dev/null > "${TEMPDIR}/certdata.txt.log"
|
|
unset _url
|
|
echo "done."
|
|
|
|
# Error out here if we couldn't get the file
|
|
grep -m1 "<i>" "${TEMPDIR}/certdata.txt.log" > /dev/null 2>&1
|
|
if test "$?" -gt 0; then
|
|
echo "Unable to get revision from server! Exiting."
|
|
exit 1
|
|
fi
|
|
|
|
# See if we need to update before downloading the file
|
|
REVISION=$(grep -m1 "<i>" "${TEMPDIR}/certdata.txt.log" | cut -d "<" -f 1)
|
|
if test -e "${DESTDIR}${SSLDIR}/certdata.txt"; then
|
|
OLDVERSION=$(grep "^# Revision:" "${DESTDIR}${SSLDIR}/certdata.txt" | \
|
|
cut -d ":" -f 2)
|
|
if test "${OLDVERSION}x" == "${REVISION}x" -a "${FORCE}" == "0"; then
|
|
echo "No update required! Use --force to update anyway."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Download the new file
|
|
echo -n "Downloading certdata.txt..."
|
|
echo GET ${URL} | \
|
|
${OPENSSL} s_client ${SARGS} 2> /dev/null >> "${CERTDATA}"
|
|
_line=$(( $(grep -n "certdata.txt" "${CERTDATA}" | cut -d ":" -f 1) - 1))
|
|
sed -e "1,${_line}d" -i "${CERTDATA}"
|
|
sed "1i # Revision:${REVISION}" -i "${CERTDATA}"
|
|
echo "done."
|
|
fi
|
|
|
|
if test "${REBUILD}" == "1"; then
|
|
CERTDATA="${DESTDIR}${SSLDIR}/certdata.txt"
|
|
fi
|
|
|
|
if test ! -r "${CERTDATA}"; then
|
|
echo "${CERTDATA} was not found. The certdata.txt file must be in the local"
|
|
echo "directory, speficied with the -C/--certdata switch, or downloaded with"
|
|
echo "the -g/--get switch."
|
|
exit 1
|
|
fi
|
|
|
|
REVISION=$(grep "^# Revision" "${CERTDATA}" | cut -d ":" -f 2)
|
|
|
|
if test "${REVISION}x" == "x"; then
|
|
echo "WARNING! ${CERTDATA} has no 'Revision' value."
|
|
echo "Will run conversion unconditionally."
|
|
sleep 2
|
|
REVISION="$(date -u +%Y%m%d-%H%M)"
|
|
echo "# Revision:${REVISION}" > "${WORKDIR}/certdata.txt"
|
|
else
|
|
if test "${FORCE}" == "1"; then
|
|
echo "Output forced. Will run conversion unconditionally."
|
|
sleep 2
|
|
elif test "${DESTDIR}x" == "x"; then
|
|
test -f "${CABUNDLE}" &&
|
|
OLDVERSION=$(grep "^# Revision:" "${CABUNDLE}" | cut -d ":" -f 2)
|
|
if test "${OLDVERSION}x" == "${REVISION}x"; then
|
|
echo "No update required! Use --force to update anyway."
|
|
exit 0
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
cat "${CERTDATA}" >> "${WORKDIR}/certdata.txt"
|
|
pushd "${WORKDIR}" > /dev/null 2>&1
|
|
|
|
# Get a list of starting lines for each cert
|
|
CERTBEGINLIST=`grep -n "^# Certificate" "${WORKDIR}/certdata.txt" | \
|
|
cut -d ":" -f1`
|
|
|
|
# Dump individual certs to temp file
|
|
for certbegin in ${CERTBEGINLIST}; do
|
|
awk "NR==$certbegin,/^CKA_TRUST_STEP_UP_APPROVED/" "${WORKDIR}/certdata.txt" \
|
|
> "${TEMPDIR}/certs/${certbegin}.tmp"
|
|
done
|
|
|
|
unset CERTBEGINLIST certbegin
|
|
|
|
for tempfile in ${TEMPDIR}/certs/*.tmp; do
|
|
# Get trust values for the certifcate
|
|
get_trust_values "${tempfile}"
|
|
|
|
# Convert to a PEM formated certificate
|
|
printf $(awk '/^CKA_VALUE/{flag=1;next}/^END/{flag=0}flag{printf $0}' \
|
|
"${tempfile}") | "${OPENSSL}" x509 -text -inform DER -fingerprint \
|
|
> tempfile.crt
|
|
|
|
# Get individual values for certificates
|
|
certkey="$(${OPENSSL} x509 -in tempfile.crt -noout -pubkey)"
|
|
certcer="$(${OPENSSL} x509 -in tempfile.crt)"
|
|
certtxt="$(${OPENSSL} x509 -in tempfile.crt -noout -text)"
|
|
|
|
# Get p11-kit label, oid, and values
|
|
get_p11_label "${tempfile}"
|
|
|
|
# Get p11 trust and OID values
|
|
get_p11_trust
|
|
|
|
# Get a hash for the cert
|
|
keyhash=$("${OPENSSL}" x509 -noout -in tempfile.crt -hash)
|
|
|
|
# Print information about cert
|
|
echo "Certificate: ${p11label}"
|
|
echo "Keyhash: ${keyhash}"
|
|
|
|
# Place certificate into trust anchors dir
|
|
anchorlabel=$(echo ${p11label} | sed -e 's@ @_@g' -e 's@(@@g' -e 's@)@@g')
|
|
anchorfile="${TEMPDIR}/pki/anchors/${anchorlabel}.p11-kit"
|
|
moz_trust="true"
|
|
write_anchor
|
|
|
|
# Import all certificates with trust args to the temporary NSS DB
|
|
if test "${WITH_NSS}" == "1"; then
|
|
write_nss_db ${TEMPDIR}/pki/nssdb tempfile.crt
|
|
fi
|
|
|
|
# Import all certificates with trust args to the java cacerts.p12 file
|
|
if test "${WITH_P12}" == "1"; then
|
|
write_java_p12 "${TEMPDIR}/ssl/java/cacerts.p12" tempfile.crt
|
|
fi
|
|
|
|
# Clean up the directory and environment as we go
|
|
rm -f tempfile.crt
|
|
unset keyhash subject count
|
|
unset mozsadistrust mozsmdistrust anchorlabel anchorfile moz_trust
|
|
unset trustlist rejectlist satrust smtrust cstrust catrust
|
|
unset p11trust p11oid p11value trustp11 p11label
|
|
|
|
echo -e "\n"
|
|
done
|
|
unset tempfile
|
|
|
|
# Install anchors in $ANCHORDIR
|
|
if test -d "${DESTDIR}${ANCHORDIR}"; then
|
|
rm -rf "${DESTDIR}${ANCHORDIR}"
|
|
fi
|
|
install -dm755 "${DESTDIR}${ANCHORDIR}"
|
|
install -m644 "${TEMPDIR}"/pki/anchors/*.p11-kit "${DESTDIR}${ANCHORDIR}"
|
|
|
|
# Install NSS Shared DB
|
|
if test "${WITH_NSS}" == "1"; then
|
|
sed -e "s@${TEMPDIR}/pki/nssdb@${NSSDB}@" \
|
|
-e 's/library=/library=libnsssysinit.so/' \
|
|
-e 's/Flags=internal/Flags=internal,moduleDBOnly/' \
|
|
-i "${TEMPDIR}/pki/nssdb/pkcs11.txt"
|
|
test -d "${DESTDIR}${NSSDB}" && rm -rf "${DESTDIR}${NSSDB}"
|
|
install -dm755 "${DESTDIR}${NSSDB}" > /dev/null 2>&1
|
|
install -m644 "${TEMPDIR}"/pki/nssdb/{cert9.db,key4.db,pkcs11.txt} \
|
|
"${DESTDIR}${NSSDB}"
|
|
fi
|
|
|
|
# Install Java cacerts.p12 in ${KEYSTORE}
|
|
if test "${WITH_P12}" == "1"; then
|
|
test -f "${DESTDIR}${KEYSTORE}/cacerts.p12" &&
|
|
rm -f "${DESTDIR}${KEYSTORE}/cacerts.p12"
|
|
install -m644 "${TEMPDIR}/ssl/java/cacerts.p12" \
|
|
"${DESTDIR}${KEYSTORE}/cacerts.p12"
|
|
fi
|
|
|
|
# Import any certs in $LOCALDIR
|
|
# Don't do any checking, just trust the admin
|
|
if test -d "${LOCALDIR}"; then
|
|
echo "Processing local certificates..."
|
|
for cert in `find "${LOCALDIR}" -name "*.pem"`; do
|
|
# Get some information about the certificate
|
|
get_p11_label ${cert}
|
|
keyhash=$("${OPENSSL}" x509 -noout -in "${cert}" -hash)
|
|
subject=$("${OPENSSL}" x509 -noout -in "${cert}" -subject)
|
|
if test "${p11label}" == ""; then
|
|
# This will always be OpenSSL, values will be separated by spaces
|
|
p11label=$( echo "${subject}" | grep -o "CN = .*" | sed 's@CN = @@' | cut -d "," -f 1)
|
|
fi
|
|
echo "Certificate: ${p11label}"
|
|
echo "Keyhash: ${keyhash}"
|
|
|
|
# Get trust information
|
|
trustlist=$("${OPENSSL}" x509 -in "${cert}" -text -trustout | \
|
|
grep -A1 "Trusted Uses")
|
|
satrust=""
|
|
smtrust=""
|
|
cstrust=""
|
|
catrust=""
|
|
satrust=$(echo "${trustlist}" | \
|
|
grep "TLS Web Server" > /dev/null 2>&1 && echo "C")
|
|
smtrust=$(echo "${trustlist}" | \
|
|
grep "E-mail Protection" > /dev/null 2>&1 && echo "C")
|
|
cstrust=$(echo "${trustlist}" | \
|
|
grep "Code Signing" > /dev/null 2>&1 && echo "C")
|
|
catrust=$(echo "${trustlist}" | \
|
|
grep "Client Auth" > /dev/null 2>&1 && echo "C")
|
|
|
|
# Get reject information
|
|
rejectlist=$("${OPENSSL}" x509 -in "${cert}" -text -trustout | \
|
|
grep -A1 "Rejected Uses")
|
|
if test "${satrust}" == ""; then satrust=$(echo "${rejectlist}" | \
|
|
grep "TLS Web Server" > /dev/null 2>&1 && echo "p"); fi
|
|
if test "${smtrust}" == ""; then smtrust=$(echo "${rejectlist}" | \
|
|
grep "E-mail Protection" > /dev/null 2>&1 && echo "p"); fi
|
|
if test "${cstrust}" == ""; then cstrust=$(echo "${rejectlist}" | \
|
|
grep "Code Signing" > /dev/null 2>&1 && echo "p"); fi
|
|
if test "${catrust}" == ""; then catrust=$(echo "${rejectlist}" | \
|
|
grep "Client Auth" > /dev/null 2>&1 && echo "p"); fi
|
|
|
|
|
|
# Get individual values for certificates
|
|
certkey="$(${OPENSSL} x509 -in ${cert} -noout -pubkey)"
|
|
certcer="$(${OPENSSL} x509 -in ${cert})"
|
|
certtxt="$(${OPENSSL} x509 -in ${cert} -noout -text)"
|
|
|
|
# Get p11 trust and OID values
|
|
get_p11_trust
|
|
|
|
# Place certificate into trust anchors dir
|
|
anchorlabel=$(echo ${p11label} | sed -e 's@ @_@g' -e 's@(@@g' -e 's@)@@')
|
|
anchorfile="${DESTDIR}${ANCHORDIR}/${anchorlabel}.p11-kit"
|
|
moz_trust="false"
|
|
mozsadistrust="UNKNOWN"
|
|
mozsmdistrust="UNKNOWN"
|
|
write_anchor
|
|
|
|
# Generate working copy
|
|
"${OPENSSL}" x509 -in "${cert}" -text -fingerprint > tempfile.crt
|
|
|
|
# Add to Shared NSS DB
|
|
if test "${WITH_NSS}" == "1"; then
|
|
write_nss_db "${DESTDIR}${NSSDB}" tempfile.crt
|
|
fi
|
|
|
|
# Import certificate (with trust args) into the java cacerts.p12 file
|
|
if test "${WITH_P12}" == "1"; then
|
|
write_java_p12 "${DESTDIR}${KEYSTORE}/cacerts.p12" tempfile.crt
|
|
fi
|
|
|
|
unset keyhash subject count
|
|
unset mozsadistrust mozsmdistrust anchorlabel anchorfile moz_trust
|
|
unset trustlist rejectlist satrust smtrust cstrust catrust
|
|
unset p11trust p11oid p11value trustp11 p11label
|
|
echo -e "\n"
|
|
|
|
done
|
|
unset cert
|
|
fi
|
|
|
|
# Install certdata.txt
|
|
if test "${REBUILD}" == "0"; then
|
|
install -dm755 "${DESTDIR}${SSLDIR}"
|
|
install -m644 "${WORKDIR}/certdata.txt" "${DESTDIR}${SSLDIR}/certdata.txt"
|
|
fi
|
|
|
|
# Clean up the mess
|
|
popd > /dev/null 2>&1
|
|
rm -rf "${TEMPDIR}"
|
|
# Build ANCHORLIST
|
|
"${MD5SUM}" "${DESTDIR}${ANCHORDIR}"/* > "${DESTDIR}${ANCHORLIST}"
|
|
|
|
# Build alternate formats using p11-kit trust
|
|
install -dm755 "${DESTDIR}${CERTDIR}" "${DESTDIR}${BUNDLEDIR}" "${DESTDIR}${KEYSTORE}"
|
|
echo -n "Extracting OpenSSL certificates to ${DESTDIR}${CERTDIR}..."
|
|
"${TRUST}" extract --filter=certificates --format=openssl-directory \
|
|
--overwrite --comment "${DESTDIR}${CERTDIR}" \
|
|
&& echo "Done!" || echo "Failed!!!"
|
|
echo -n "Extracting GNUTLS server auth certificates to ${DESTDIR}${CABUNDLE}..."
|
|
"${TRUST}" extract --filter=certificates --format=pem-bundle \
|
|
--purpose server-auth --overwrite --comment "${DESTDIR}${CABUNDLE}" \
|
|
&& echo "Done!" || echo "Failed!!!"
|
|
echo -n "Extracting GNUTLS S-Mime certificates to ${DESTDIR}${SMBUNDLE}..."
|
|
"${TRUST}" extract --filter=certificates --format=pem-bundle \
|
|
--purpose email --overwrite --comment "${DESTDIR}${SMBUNDLE}" \
|
|
&& echo "Done!" || echo "Failed!!!"
|
|
echo -n "Extracting GNUTLS code signing certificates to ${DESTDIR}${CSBUNDLE}..."
|
|
"${TRUST}" extract --filter=certificates --format=pem-bundle \
|
|
--purpose code-signing --overwrite --comment \
|
|
"${DESTDIR}${CSBUNDLE}" && echo "Done!" || echo "Failed!!!"
|
|
echo -n "Extracting Java cacerts (JKS) to ${DESTDIR}${KEYSTORE}/cacerts..."
|
|
"${TRUST}" extract --filter=certificates --format=java-cacerts \
|
|
--purpose server-auth --overwrite \
|
|
--comment "${DESTDIR}${KEYSTORE}/cacerts" \
|
|
&& echo "Done!" || echo "Failed!!!"
|
|
|
|
# End /usr/sbin/make-ca
|