#! /bin/csh -f # # Build SystemRootCertificates.keychain and SystemTrustSettings.plist from # all the certs in cwd/roots. Creates these two files in ./BuiltKeychains/. # set CWD=`pwd` set ROOT_CERT_DIR=$CWD/roots set DISTRUSTED_CERT_DIR=$CWD/distrusted set REVOKED_CERT_DIR=$CWD/revoked set KC_DIR=$CWD/BuiltKeychains if((! -e "$ROOT_CERT_DIR") || (! -e "$KC_DIR")) then echo "You do not seem to be in a current security_certificates directory. Aborting." exit(1) endif # this option is essential to process filenames containing a wildcard set nonomatch set ROOT_CERT_KC=SystemRootCertificates.keychain set ROOT_CERT_KC_PATH="$KC_DIR/$ROOT_CERT_KC" set SETTINGS_FILE=SystemTrustSettings.plist set SETTINGS_FILE_PATH="$KC_DIR/$SETTINGS_FILE" set TEMP_CERT_KC=SystemTempCertificates.keychain set TEMP_CERT_KC_PATH=/tmp/"$TEMP_CERT_KC" set SECURITY=/usr/bin/security # save keychain list so we don't add SystemRootCertificates to it set SAVED_KC_LIST=`$SECURITY list -d user` printf "Saved user keychain list:\n%s\n\n" "${SAVED_KC_LIST}" echo Creating empty $ROOT_CERT_KC... rm -f "$ROOT_CERT_KC_PATH" || exit(1) $SECURITY create-keychain -p "$ROOT_CERT_KC" "$ROOT_CERT_KC_PATH" || exit(1) echo Creating empty $SETTINGS_FILE... rm -f "$SETTINGS_FILE_PATH" || exit(1) $SECURITY add-trusted-cert -o "$SETTINGS_FILE_PATH" || exit(1) echo Adding root certs to $ROOT_CERT_KC... cd "$ROOT_CERT_DIR" || exit(1) set GOT_ERROR=NO foreach root (*) echo Processing $root... if (( "$root" == "AppleDEVID.cer" )) then echo " skipping intermediate $root for trust" $SECURITY -q add-certificates -k "$ROOT_CERT_KC_PATH" "$root" || exit(1) else $SECURITY -q add-trusted-cert -i "$SETTINGS_FILE_PATH" -o "$SETTINGS_FILE_PATH" -k "$ROOT_CERT_KC_PATH" "$root" || exit(1) endif end # After adding the trusted roots, add trust settings to explicitly distrust certs # echo Creating empty $TEMP_CERT_KC... rm -f "$TEMP_CERT_KC_PATH" || exit(1) $SECURITY create-keychain -p "$TEMP_CERT_KC" "$TEMP_CERT_KC_PATH" || exit(1) echo Explicitly distrusting certs... cd "$DISTRUSTED_CERT_DIR" || exit(1) foreach cert (*) echo Processing $cert... $SECURITY -q add-trusted-cert -i "$SETTINGS_FILE_PATH" -o "$SETTINGS_FILE_PATH" -k "$TEMP_CERT_KC_PATH" -r unspecified "$cert" || exit(1) end echo Explicitly revoking certs... cd "$REVOKED_CERT_DIR" || exit(1) foreach cert (*) echo Processing $cert... ### these will eventually get a different trust result than distrusted certs, when we support that; ### one should produce a soft failure (warning) and the other a hard failure. $SECURITY -q add-trusted-cert -i "$SETTINGS_FILE_PATH" -o "$SETTINGS_FILE_PATH" -k "$TEMP_CERT_KC_PATH" -r deny "$cert" || exit(1) end rm -f "$TEMP_CERT_KC_PATH" || exit(1) # Check that we successfully added every root in the "roots" directory # set EXPECTED=`ls -1 "$ROOT_CERT_DIR" | wc -l | awk '{print $1}'` set ACTUAL=`security find-certificate -a "$ROOT_CERT_KC_PATH" | grep "labl" | wc -l | awk '{print $1}'` #echo $ACTUAL if ("$EXPECTED" != "$ACTUAL") then printf "Failed to add all roots (expected $EXPECTED -- actual $ACTUAL)\n" exit(1) else printf "SUCCESS - $ACTUAL certificates added\n" endif chmod 0644 "$SETTINGS_FILE_PATH" || exit(1) chmod 0644 "$ROOT_CERT_KC_PATH" || exit(1) # set the keychain list, using xargs to pass the saved argument list /bin/echo -n "${SAVED_KC_LIST}" | xargs $SECURITY list -d user -s set POST_KC_LIST=`$SECURITY list -d user` printf "Post-save user keychain list:\n%s\n\n" "${POST_KC_LIST}" echo "=== System Root Certificate Processing complete. ==="