1#! /bin/csh -f 2# 3# Build SystemRootCertificates.keychain and SystemTrustSettings.plist from 4# all the certs in cwd/roots. Creates these two files in ./BuiltKeychains/. 5# 6set CWD=`pwd` 7set ROOT_CERT_DIR=$CWD/roots 8set DISTRUSTED_CERT_DIR=$CWD/distrusted 9set REVOKED_CERT_DIR=$CWD/revoked 10set KC_DIR=$CWD/BuiltKeychains 11 12if((! -e "$ROOT_CERT_DIR") || (! -e "$KC_DIR")) then 13 echo "You do not seem to be in a current security_certificates directory. Aborting." 14 exit(1) 15endif 16 17# this option is essential to process filenames containing a wildcard 18set nonomatch 19 20set ROOT_CERT_KC=SystemRootCertificates.keychain 21set ROOT_CERT_KC_PATH="$KC_DIR/$ROOT_CERT_KC" 22set SETTINGS_FILE=SystemTrustSettings.plist 23set SETTINGS_FILE_PATH="$KC_DIR/$SETTINGS_FILE" 24set TEMP_CERT_KC=SystemTempCertificates.keychain 25set TEMP_CERT_KC_PATH=/tmp/"$TEMP_CERT_KC" 26set SECURITY=/usr/bin/security 27 28# save keychain list so we don't add SystemRootCertificates to it 29set SAVED_KC_LIST=`$SECURITY list -d user` 30printf "Saved user keychain list:\n%s\n\n" "${SAVED_KC_LIST}" 31 32echo Creating empty $ROOT_CERT_KC... 33rm -f "$ROOT_CERT_KC_PATH" || exit(1) 34$SECURITY create-keychain -p "$ROOT_CERT_KC" "$ROOT_CERT_KC_PATH" || exit(1) 35 36echo Creating empty $SETTINGS_FILE... 37rm -f "$SETTINGS_FILE_PATH" || exit(1) 38$SECURITY add-trusted-cert -o "$SETTINGS_FILE_PATH" || exit(1) 39 40echo Adding root certs to $ROOT_CERT_KC... 41 42cd "$ROOT_CERT_DIR" || exit(1) 43 44set GOT_ERROR=NO 45 46foreach root (*) 47 echo Processing $root... 48 if (( "$root" == "AppleDEVID.cer" )) then 49 echo " skipping intermediate $root for trust" 50 $SECURITY -q add-certificates -k "$ROOT_CERT_KC_PATH" "$root" || exit(1) 51 else 52 $SECURITY -q add-trusted-cert -i "$SETTINGS_FILE_PATH" -o "$SETTINGS_FILE_PATH" -k "$ROOT_CERT_KC_PATH" "$root" || exit(1) 53 endif 54end 55 56# After adding the trusted roots, add trust settings to explicitly distrust certs 57# 58echo Creating empty $TEMP_CERT_KC... 59rm -f "$TEMP_CERT_KC_PATH" || exit(1) 60$SECURITY create-keychain -p "$TEMP_CERT_KC" "$TEMP_CERT_KC_PATH" || exit(1) 61 62echo Explicitly distrusting certs... 63 64cd "$DISTRUSTED_CERT_DIR" || exit(1) 65 66foreach cert (*) 67 echo Processing $cert... 68 $SECURITY -q add-trusted-cert -i "$SETTINGS_FILE_PATH" -o "$SETTINGS_FILE_PATH" -k "$TEMP_CERT_KC_PATH" -r unspecified "$cert" || exit(1) 69end 70 71echo Explicitly revoking certs... 72 73cd "$REVOKED_CERT_DIR" || exit(1) 74 75foreach cert (*) 76 echo Processing $cert... 77 ### these will eventually get a different trust result than distrusted certs, when we support that; 78 ### one should produce a soft failure (warning) and the other a hard failure. 79 $SECURITY -q add-trusted-cert -i "$SETTINGS_FILE_PATH" -o "$SETTINGS_FILE_PATH" -k "$TEMP_CERT_KC_PATH" -r deny "$cert" || exit(1) 80end 81 82rm -f "$TEMP_CERT_KC_PATH" || exit(1) 83 84 85# Check that we successfully added every root in the "roots" directory 86# 87set EXPECTED=`ls -1 "$ROOT_CERT_DIR" | wc -l | awk '{print $1}'` 88 89set ACTUAL=`security find-certificate -a "$ROOT_CERT_KC_PATH" | grep "labl" | wc -l | awk '{print $1}'` 90#echo $ACTUAL 91 92if ("$EXPECTED" != "$ACTUAL") then 93 printf "Failed to add all roots (expected $EXPECTED -- actual $ACTUAL)\n" 94 exit(1) 95else 96 printf "SUCCESS - $ACTUAL certificates added\n" 97endif 98 99chmod 0644 "$SETTINGS_FILE_PATH" || exit(1) 100chmod 0644 "$ROOT_CERT_KC_PATH" || exit(1) 101 102# set the keychain list, using xargs to pass the saved argument list 103/bin/echo -n "${SAVED_KC_LIST}" | xargs $SECURITY list -d user -s 104 105set POST_KC_LIST=`$SECURITY list -d user` 106printf "Post-save user keychain list:\n%s\n\n" "${POST_KC_LIST}" 107 108echo "=== System Root Certificate Processing complete. ===" 109