#!/bin/bash
CWD=`/bin/pwd`
ROOT_CERT_DIR="$CWD"/roots
ALT_ROOT_CERT_DIR="$CWD"/roots_incoming
KC_DIR="$CWD"/BuiltKeychains
USE_PUBKEY=0
if [ "$USE_PUBKEY" -ne 0 ]; then
CERTLIST="$CWD"/../../tests/certlist
if [ ! -e "$CERTLIST" ]; then
printf "### BUILD FAILED: $CERTLIST is missing\n"
exit 1
fi
fi
SECURITY=/usr/bin/security
OPENSSL=/usr/bin/openssl
PLB=/usr/libexec/PlistBuddy
SaveKeychainList() {
SAVED_KC_LIST=`"$SECURITY" list -d user`
}
RestoreKeychainList() {
/bin/echo -n "$SAVED_KC_LIST" | xargs "$SECURITY" list -d user -s
}
if [ ! -e "$ROOT_CERT_DIR" ] || [ ! -e "$KC_DIR" ]; then
printf "You do not seem to be in a current security_certificates directory. Aborting.\n"
exit 1
fi
EVROOTS_CONFIG="$CWD"/evroot.config
EVROOTS_KC=EVRoots.keychain
EVROOTS_KC_PATH="/tmp/$EVROOTS_KC"
EVROOTS_PLIST=EVRoots.plist
EVROOTS_PLIST_PATH="$KC_DIR/$EVROOTS_PLIST"
SaveKeychainList
printf "Creating empty %s...\n" "$EVROOTS_KC"
/bin/rm -f "$EVROOTS_KC_PATH" || exit 1
"$SECURITY" create-keychain -p "$EVROOTS_KC" "$EVROOTS_KC_PATH" || exit 1
TMPIFS=$IFS
IFS=$'\x0A'$'\x0D'
for OID in `cat "$EVROOTS_CONFIG"`; do
OID=`echo "$OID" | sed -e 's/^ if [ "$OID" = "" ]; then continue; fi
OIDKEY=`echo "$OID" | awk '{print $1}'`
CERTFILES=`echo "$OID" | sed -e 's/^[0-9A-Z\.]* //' -e 's/\"\ */\:/g'`
IFS=$'\x3A'
for CERTFILE in $CERTFILES; do
if [ "$CERTFILE" = "" ]; then continue; fi
printf "Adding cert from file: %s\n" "$CERTFILE"
CERT_TO_ADD="$ROOT_CERT_DIR/$CERTFILE"
if [ ! -e "$CERT_TO_ADD" ]; then
CERT_TO_ADD="$ALT_ROOT_CERT_DIR/$CERTFILE"
fi
# should prune duplicates first; for now, just ignore errors
"$SECURITY" \
-q add-certificates \
-k "$EVROOTS_KC_PATH" \
"$CERT_TO_ADD"
done
IFS=$'\x0A'$'\x0D'
done
printf "Removing %s...\n" "$EVROOTS_PLIST"
/bin/rm -f "$EVROOTS_PLIST_PATH"
# second pass: get hashes and build the EVRoots plist
for OID in `cat "$EVROOTS_CONFIG"`; do
# ignore comments and blank lines
OID=`echo "$OID" | sed -e 's/^#.*//'`
if [ "$OID" = "" ]; then continue; fi
# grab OID key
OIDKEY=`echo "$OID" | awk '{print $1}'`
# add an array for this OID key
"$PLB" -c "add :$OIDKEY array" "$EVROOTS_PLIST_PATH"
# convert rest of line into comma-delimited filename list
CERTFILES=`echo "$OID" | sed -e 's/^[0-9A-Z\.]* //' -e 's/\"\ */\:/g'`
IFS=$'\x3A'
# process each certificate file
IDX=0
for CERTFILE in $CERTFILES; do
if [ "$CERTFILE" = "" ]; then continue; fi
CERT_TO_HASH="$ROOT_CERT_DIR/$CERTFILE"
if [ ! -e "$CERT_TO_HASH" ]; then
printf "... Could not find file to hash: \"%s\"\n" "$CERT_TO_HASH"
CERT_TO_HASH="$ALT_ROOT_CERT_DIR/$CERTFILE"
fi
if [ "$USE_PUBKEY" -ne 0 ]; then
PK_SHA1=`"$OPENSSL" x509 -inform DER -in "$CERT_TO_HASH" -ocspid | grep "Public key" | awk '{print $5}'`
PK_MD5=`"$CERTLIST" -k "$EVROOTS_KC_PATH" -p --md5 --sha1 | grep "$PK_SHA1" | sed -e 's/^.\{37\}//' | awk '{print $1}'`
printf "Public key hashes for \"%s\":\n" "$CERTFILE"
printf " MD5: %s SHA1: %s\n" "$PK_MD5" "$PK_SHA1"
printf "%s" "$PK_MD5" | xxd -r -p > /tmp/md5hashtmp
printf "%s" "$PK_SHA1" | xxd -r -p > /tmp/sha1hashtmp
IDX_NEXT=`expr $IDX + 1`
"$PLB" -c "add :$OIDKEY:$IDX data" \
-c "import :$OIDKEY:$IDX /tmp/md5hashtmp" \
-c "add :$OIDKEY:$IDX_NEXT data" \
-c "import :$OIDKEY:$IDX_NEXT /tmp/sha1hashtmp" \
"$EVROOTS_PLIST_PATH"
VERIFY_ERROR=0
DATA=`"$PLB" -c "print :$OIDKEY:$IDX data" \
"$EVROOTS_PLIST_PATH" | \
xxd -u -p | sed -e 's/0A$//'`
if [ "$DATA" != "$PK_MD5" ]; then VERIFY_ERROR=1; fi
DATA=`"$PLB" -c "print :$OIDKEY:$IDX_NEXT data" \
"$EVROOTS_PLIST_PATH" | \
xxd -u -p | sed -e 's/0A$//'`
if [ "$DATA" != "$PK_SHA1" ]; then VERIFY_ERROR=1; fi
if [ ! "$VERIFY_ERROR" -eq 0 ]; then
printf "### BUILD FAILED: data verification error!\n"
printf "You likely need to install a newer version of $PLB; see <rdar://6208924> for details\n"
RestoreKeychainList
/bin/rm -f "$EVROOTS_PLIST_PATH"
exit 1
fi
else
CERT_SHA1=`"$OPENSSL" x509 -inform DER -in "$CERT_TO_HASH" -fingerprint -noout | sed -e 's/SHA1 Fingerprint=//' -e 's/://g'`
printf "Certificate fingerprint for \"%s\":\n" "$CERTFILE"
printf " SHA1: %s\n" "$CERT_SHA1"
printf "%s" "$CERT_SHA1" | xxd -r -p > /tmp/certsha1hashtmp
IDX_NEXT=`expr $IDX + 1`
"$PLB" -c "add :$OIDKEY:$IDX data" \
-c "import :$OIDKEY:$IDX /tmp/certsha1hashtmp" \
"$EVROOTS_PLIST_PATH"
VERIFY_ERROR=0
DATA=`"$PLB" -c "print :$OIDKEY:$IDX data" \
"$EVROOTS_PLIST_PATH" | \
xxd -u -p | sed -e 's/0A$//'`
if [ "$DATA" != "$CERT_SHA1" ]; then VERIFY_ERROR=1; fi
if [ ! "$VERIFY_ERROR" -eq 0 ]; then
printf "### BUILD FAILED: data verification error!\n"
printf "You likely need to install a newer version of $PLB; see <rdar://6208924> for details\n"
RestoreKeychainList
/bin/rm -f "$EVROOTS_PLIST_PATH"
exit 1
fi
fi
IDX="$IDX_NEXT"
done
IFS=$'\x0A'$'\x0D'
done
IFS="$TMPIFS"
RestoreKeychainList
/bin/chmod 0644 "$EVROOTS_PLIST_PATH"
printf "Built $EVROOTS_PLIST_PATH successfully\n"
exit 0