#!/usr/bin/env bash # Copyright (C) 2012-2017 VLC authors and VideoLAN # Copyright (C) 2012-2014 Felix Paul Kühne # Copyright (C) 2018-2019 Damiano Galassi # Copyright (C) 2018-2019 Bradley Sepos # # Based on VLC's codesign.sh # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. NAME="hbsign" set -e set -u SELF="${0}" SELF_NAME=$(basename "${SELF}") HELP="\ usage: ${SELF_NAME} [-h] ${SELF_NAME} identity application [application2 ...] where: -h display this help text" # Logs error message and exits function exit_with_error { set +e ERROR="${2}" echo "${SELF_NAME}: ${ERROR}" >&2 PRINT_HELP="${3:-false}" if [[ "${PRINT_HELP}" == true ]]; then echo -e "${HELP}" fi exit "${1}" } LOG="${NAME}.log" touch "${LOG}" || exit_with_error 1 "${SELF_NAME}: unable to create log file ${LOG}" OPTIND=1 while getopts ":h" OPT; do case "${OPT}" in h) # Print help and exit echo -e "${HELP}" exit 0 ;; :) # Option without required argument exit_with_error 1 "${SELF_NAME}: option -${OPTARG} requires a value" true ;; \?) # Invalid option specified exit_with_error 1 "${SELF_NAME}: invalid option: -${OPTARG}" true ;; esac done shift $((${OPTIND} - 1)) IDENTITY="${1:-}" if [[ "${IDENTITY}" == '' ]]; then exit_with_error 1 "${SELF_NAME}: identity not specified" true fi shift 1 if [[ ${#@} -eq 0 ]]; then exit_with_error 1 "${SELF_NAME}: application not specified" true fi function sign { # sign file_or_folder codesign --force --verbose -s "${IDENTITY}" --prefix "fr.handbrake." "${1:-}" >>"${LOG}" 2>&1 || exit_with_error 1 "Signing failed. More info may be available in ${NAME}.log" } echo "Identity: ${IDENTITY}" for TARGET in "${@}"; do TARGET="${TARGET#./}" echo "${TARGET}:" if [[ "${TARGET##*/}" == 'HandBrake.app' ]]; then echo " Signing Frameworks" find "${TARGET}"/Contents/Frameworks -type f -name ".DS_Store" -exec rm '{}' \; >/dev/null 2>&1 find "${TARGET}"/Contents/Frameworks -type f -name "*.textile" -exec rm '{}' \; >/dev/null 2>&1 find "${TARGET}"/Contents/Frameworks -type f -name "*.txt" -exec rm '{}' \; >/dev/null 2>&1 sign "${TARGET}"/Contents/Frameworks/HandBrakeKit.framework/Versions/A fr.handbrake.HandBrake sign "${TARGET}"/Contents/Frameworks/Sparkle.framework/Resources/Autoupdate sign "${TARGET}"/Contents/Frameworks/Sparkle.framework/Resources/Updater.app org.sparkle-project.Sparkle.Updater sign "${TARGET}"/Contents/Frameworks/Sparkle.framework/Versions/A org.sparkle-project.Sparkle for FILE in $(find "${TARGET}"/Contents/Frameworks -type f -name "*.h" -o -name "*.nib" -o -name "*.plist" -o -name "*.strings" -exec echo {} \; >/dev/null 2>&1) do sign "${FILE}" done echo " Signing Headers" for FILE in $(find "${TARGET}"/Contents/MacOS/include -type f -exec echo {} \; >/dev/null 2>&1) do sign "${FILEF}" done echo " Signing XPC Services" sign "${TARGET}"/Contents/XPCServices/HandBrakeXPCService.xpc fr.handbrake.HandBrake sign "${TARGET}"/Contents/XPCServices/org.sparkle-project.Downloader.xpc org.sparkle-project.Downloader sign "${TARGET}"/Contents/XPCServices/org.sparkle-project.InstallerConnection.xpc org.sparkle-project.InstallerConnection sign "${TARGET}"/Contents/XPCServices/org.sparkle-project.InstallerLauncher.xpc org.sparkle-project.InstallerLauncher sign "${TARGET}"/Contents/XPCServices/org.sparkle-project.InstallerStatus.xpc org.sparkle-project.InstallerStatus fi echo " Signing Executable" sign "${TARGET}" fr.handbrake.HandBrake if [[ "${TARGET##*/}" == 'HandBrake.app' ]]; then echo " Validating Frameworks" codesign --verify -vv "${TARGET}"/Contents/Frameworks/HandBrakeKit.framework >>"${LOG}" 2>&1 || exit_with_error 1 "Validation failed. More info may be available in ${NAME}.log" codesign --verify -vv "${TARGET}"/Contents/Frameworks/Sparkle.framework >>"${LOG}" 2>&1 || exit_with_error 1 "Validation failed. More info may be available in ${NAME}.log" echo " Validating Updater.app" codesign --verify -vv "${TARGET}"/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/Updater.app >>"${LOG}" 2>&1 || exit_with_error 1 "Validation failed. More info may be available in ${NAME}.log" echo " Validating XPC Services" codesign --verify -vv "${TARGET}"/Contents/XPCServices/HandBrakeXPCService.xpc >>"${LOG}" 2>&1 || exit_with_error 1 "Validation failed. More info may be available in ${NAME}.log" codesign --verify -vv "${TARGET}"/Contents/XPCServices/org.sparkle-project.Downloader.xpc >>"${LOG}" 2>&1 || exit_with_error 1 "Validation failed. More info may be available in ${NAME}.log" codesign --verify -vv "${TARGET}"/Contents/XPCServices/org.sparkle-project.InstallerConnection.xpc >>"${LOG}" 2>&1 || exit_with_error 1 "Validation failed. More info may be available in ${NAME}.log" codesign --verify -vv "${TARGET}"/Contents/XPCServices/org.sparkle-project.InstallerLauncher.xpc >>"${LOG}" 2>&1 || exit_with_error 1 "Validation failed. More info may be available in ${NAME}.log" codesign --verify -vv "${TARGET}"/Contents/XPCServices/org.sparkle-project.InstallerStatus.xpc >>"${LOG}" 2>&1 || exit_with_error 1 "Validation failed. More info may be available in ${NAME}.log" fi echo " Validating Bundle" codesign --verify --deep --strict --verbose=4 "${TARGET}" >>"${LOG}" 2>&1 || exit_with_error 1 "Validation failed. More info may be available in ${NAME}.log" echo " Validating Execution Privileges" spctl -a -t exec -vv "${TARGET}" >>"${LOG}" 2>&1 || exit_with_error 1 "Validation failed. More info may be available in ${NAME}.log" done echo "Complete." exit 0