diff --git a/MDM/AppConfig/README.md b/enterprise/MDM/AppConfig/README.md similarity index 100% rename from MDM/AppConfig/README.md rename to enterprise/MDM/AppConfig/README.md diff --git a/MDM/AppConfig/minimal-specfile.xml b/enterprise/MDM/AppConfig/minimal-specfile.xml similarity index 100% rename from MDM/AppConfig/minimal-specfile.xml rename to enterprise/MDM/AppConfig/minimal-specfile.xml diff --git a/MDM/AppConfig/specfile.xml b/enterprise/MDM/AppConfig/specfile.xml similarity index 100% rename from MDM/AppConfig/specfile.xml rename to enterprise/MDM/AppConfig/specfile.xml diff --git a/enterprise/resign/App/ad-hoc/README.md b/enterprise/resign/App/ad-hoc/README.md new file mode 100644 index 000000000..3b6207398 --- /dev/null +++ b/enterprise/resign/App/ad-hoc/README.md @@ -0,0 +1,3 @@ +Place your `unsigned.ipa` file in this folder, which should be signed for `ad-hoc` build. + +After the resigning process, here you will find the `signed.ipa` file. \ No newline at end of file diff --git a/enterprise/resign/App/app-store/README.md b/enterprise/resign/App/app-store/README.md new file mode 100644 index 000000000..ad7c43659 --- /dev/null +++ b/enterprise/resign/App/app-store/README.md @@ -0,0 +1,4 @@ +Place your `unsigned.ipa` file in this folder, which should be signed for `app-store` build. + +After the resigning process, here you will find the `signed.ipa` file. + diff --git a/enterprise/resign/Provisioning Files/ad-hoc/README.md b/enterprise/resign/Provisioning Files/ad-hoc/README.md new file mode 100644 index 000000000..1bc95ea8a --- /dev/null +++ b/enterprise/resign/Provisioning Files/ad-hoc/README.md @@ -0,0 +1,5 @@ +#### Place the following provisioning files in this folder, which was created for ad-hoc build: + +- App.mobileprovision +- FileProvider.mobileprovision +- Intent.mobileprovision diff --git a/enterprise/resign/Provisioning Files/app-store/README.md b/enterprise/resign/Provisioning Files/app-store/README.md new file mode 100644 index 000000000..6e8d91d90 --- /dev/null +++ b/enterprise/resign/Provisioning Files/app-store/README.md @@ -0,0 +1,5 @@ +#### Place the following provisioning files in this folder, which was created for the app-store: + +- App.mobileprovision +- FileProvider.mobileprovision +- Intent.mobileprovision \ No newline at end of file diff --git a/enterprise/resign/README.md b/enterprise/resign/README.md new file mode 100644 index 000000000..7d8e40df8 --- /dev/null +++ b/enterprise/resign/README.md @@ -0,0 +1,58 @@ +# Script to resign your iOS ownCloud App + +This script allows you to resign the ownCloud App IPA file with a different Apple certificate. +Decide if you want to sign the app for Ad-Hoc (`ad-hoc`) installation or for the App Store(`app-store`). + +## App IDs and Provisioning Files + +1. You need to generate the following App IDs with `App Groups` enabled on the Apple Developer Portal `Identifiers` section: + + - `com.yourcompany.ios-app` + + - `com.yourcompany.ios-app.ownCloud-File-Provider` + + - `com.yourcompany.ios-app.ownCloud-Intent` + + + + This IDs must match with `Bundle Identifier` value for the related Xcode target. + +2. Generate one App Group: + + - `group.com.yourcompany.ios-app` + + + + Please keep the prefix `group.` and append the bundle identifier of the app target. + +3. Edit the App IDs and assign the App Group created on step 2. + +4. Generate the mobile provisioning (App Store or Ad-Hoc) for both App IDs using a Distribution certificate (this certificate must be installed on the computer and its common name will be used as parameter on the script) + +## Certificate + +- Get the name of your signing certificate. In most cases this will be named `iPhone Distribution: YOUR COMPANY`. + +## Instructions + +1. Rename your `.ipa` file to `unsigned.ipa` + +2. Put the `unsigned.ipa` on the folder `App/ad-hoc/` or `App/app-store/` + +3. Put your mobile provisioning inside `Provisioning Files/ad-hoc/` or `Provisioning Files/app-store/` + +4. The mobile provisioning must be named: + + - `App.mobileprovision` + - `FileProvider.mobileprovision` + - `Intent.mobileprovision` + +5. Execute the script + + - `sh resignOwncloudApp "COMMON NAME DISTRIBUTION CERT" "ad-hoc"` + + - `sh resignOwncloudApp "COMMON NAME DISTRIBUTION CERT" "app-store"` + + + + Replace `"COMMON NAME DISTRIBUTION CERT"` with the name of your certificate, e.g. `"iPhone Distribution: YOUR COMPANY"`. diff --git a/enterprise/resign/resignOwncloudApp b/enterprise/resign/resignOwncloudApp new file mode 100755 index 000000000..c5a3b0309 --- /dev/null +++ b/enterprise/resign/resignOwncloudApp @@ -0,0 +1,233 @@ +#! /bin/bash + + # Copyright (C) 2020, ownCloud GmbH. + # + # This code is covered by the GNU Public License Version 3. + # + # For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ + # You should have received a copy of this license along with this program. If not, see . + +VERSION="1.0.0" + +#Define output formats +BOLD="$(tput bold)" +UNDERLINED="$(tput smul)" +NOTUNDERLINED="$(tput rmul)" +WARN="$(tput setaf 1)" +SUCCESS="$(tput setaf 2)" +INFO="$(tput setaf 3)" +NC="$(tput sgr0)" # No Color + + +usage() +{ + echo "Usage: $0 CERTIFICATE_IDENTITY METHOD" + echo " $0 \"Certificate Identity\" ad-hoc" + echo " $0 \"Certificate Identity\" app-store" + echo "Version: ${VERSION}" + echo "" + echo "Found Certificate Identities:" + echo " Fingerprint \"Certificate Identity\"" + echo " -----------------------------------------------------------------" + security find-identity -pcodesigning -v + exit 1 +} + +#Check if all required parameters exist +if [ $# -lt 2 ]; then + usage +fi +if ! [[ "$2" =~ ^(ad-hoc|app-store)$ ]]; then + usage +fi + +echo +echo "${BOLD}${SUCCESS}ownCloud iOS-App Resigning${NC}" +echo "Version ${VERSION}" +echo +echo "${SUCCESS}Starting resign process…${NC}" +echo "" + +#Define variables +IDENTITY=$1 +METHOD=$2 +BUILD_DIR="App" +NAME_FINAL_IPA="signed.ipa" +UNSIGNED_IPA="$BUILD_DIR/$METHOD/unsigned.ipa" +ERROR_SHA1=0 +FINAL_IPA="$BUILD_DIR/$METHOD/$NAME_FINAL_IPA" +APPTEMP="$BUILD_DIR/$METHOD/apptemp" +APPPAYLOAD="$APPTEMP/Payload" +APPDIR="$APPPAYLOAD/ownCloud.app" +PROVISIONING_DIR="Provisioning Files" + +DISTRIBUTION_MOBILEPROVISION="$PROVISIONING_DIR/$METHOD/App.mobileprovision" +FILEPROVIDER_MOBILEPROVISION="$PROVISIONING_DIR/$METHOD/FileProvider.mobileprovision" +INTENT_MOBILEPROVISION="$PROVISIONING_DIR/$METHOD/Intent.mobileprovision" + +declare -a MOBILEPROVISIONS=( "$DISTRIBUTION_MOBILEPROVISION" "$FILEPROVIDER_MOBILEPROVISION" "$INTENT_MOBILEPROVISION" ); +declare -a ENTITLEMENTS=( "ownCloud.entitlements" "ownCloud_File_Provider.entitlements" "ownCloud_Intents.entitlements" ); +declare -a LOCATIONS=( "$APPDIR" "$APPDIR/PlugIns/ownCloud File Provider.appex" "$APPDIR/PlugIns/ownCloud Intents.appex" ); +declare -a BUNDLEIDS=(); + +# Delete previous temporal app folder if exist +if [ -d "$APPTEMP" ]; then + rm -rf "$APPTEMP" +fi + +if [ ! -f "$UNSIGNED_IPA" ]; then + echo "${WARN}Error: can't find $UNSIGNED_IPA in the current directory${NC}" + exit 1 +fi + +# Get certificate SHA-1 +CERT_SHA_1=`security find-certificate -c "$IDENTITY" -Z | grep "^SHA-1" | cut -d: -f 2 | xargs` +# Create temp directory +mkdir $APPTEMP + +echo "${UNDERLINED}${SUCCESS}Checking Provisioning Profiles:${NOTUNDERLINED}" + +for a in "${MOBILEPROVISIONS[@]}" +do + if [ ! -f "./$a" ]; then + echo "${WARN}Error: can't find $a in the current directory${NC}" + exit 1 +else + # Convert provisioning profile to plist + security cms -D -i "$a" > "$APPTEMP/tmp.plist" + # Get provisioning SHA-1 + PROV_SHA_1=`/usr/libexec/PlistBuddy -c "Print :DeveloperCertificates:0" $APPTEMP/tmp.plist | openssl x509 -inform der -fingerprint | grep "^SHA1" | cut -d= -f 2 | ruby -ne 'puts $_.split(":").join'` + + if [ "$CERT_SHA_1" = "$PROV_SHA_1" ]; then + echo "${SUCCESS}Provisioning fingerprint matches with certificate:${NC}" + echo "${INFO}$a${NC}" + echo "" + else + echo "" + echo "${WARN}The provisioning fingerprint does not match with the certificate fingerprint:${NC}" + echo "Provisioning Profile: ${INFO}$a${NC}" + echo "Certificate Fingerprint: ${INFO}$CERT_SHA_1${NC}" + echo "Provisioning Fingerprint: ${INFO}$PROV_SHA_1${NC}" + ERROR_SHA1=1 + fi +fi +done + +if [ "$ERROR_SHA1" = 1 ]; then + echo "" + echo "Please check that you are using the correct certificate identity and the provisioning profile was signed with the chosen certificate identity." + echo "${WARN}Exit resigning. Please fix the errors above.${NC}" + exit +fi + +export PATH=$PATH:/usr/libexec + +# Unzip ipa +echo "${SUCCESS}Unzipping ipa…${NC}" +echo "" +unzip -q "$UNSIGNED_IPA" -d "$APPTEMP" || { echo "${WARN}Failed to unzip ipa file${NC}"; exit 1; } + + +# Profile +# security cms -D -i ~/Downloads/App.mobileprovision > ~/Downloads/App.plist +# /usr/libexec/PlistBuddy -c "Print :DeveloperCertificates:0" ~/Downloads/App.plist | openssl x509 -inform der -fingerprint | grep "^SHA1" | cut -d= -f 2 | ruby -ne 'puts $_.split(":").join' + + +for (( i=0; i<${#MOBILEPROVISIONS[@]}; i++ )); +do + echo "${UNDERLINED}${SUCCESS}Module:${NOTUNDERLINED}" + echo "${INFO}${LOCATIONS[$i]}${NC}" + echo "" + echo "Provisioning: ${INFO}${MOBILEPROVISIONS[$i]}${NC}" + echo "Entitlements: ${INFO}${ENTITLEMENTS[$i]}${NC}" + echo "" + + # Duplicate each mobile provision as embedded.mobileprovision and move to correct destination folder + cp "${MOBILEPROVISIONS[$i]}" "$BUILD_DIR/$METHOD/embedded.mobileprovision" + + { + mv "$BUILD_DIR/$METHOD/embedded.mobileprovision" "${LOCATIONS[$i]}" + } || { # catch + echo "${WARN}ERROR${NC}" + } + + echo "${SUCCESS}Creating entitlements…${NC}" + # Create all the necessary entitlements + PlistBuddy -x -c "print :Entitlements " /dev/stdin <<< $(security cms -D -i "./${MOBILEPROVISIONS[$i]}") > "${ENTITLEMENTS[$i]}" + TEAMID=`PlistBuddy -c "print com.apple.developer.team-identifier " "${ENTITLEMENTS[$i]}"` + echo "TeamId: ${INFO}$TEAMID${NC}" + APPGROUP=`PlistBuddy -c "print com.apple.security.application-groups:0 " "${ENTITLEMENTS[$i]}"` + echo "AppGroup: ${INFO}$APPGROUP${NC}" + APP_ID_PREFIX=`PlistBuddy -c "print :ApplicationIdentifierPrefix:0" /dev/stdin <<< $(security cms -D -i "./${MOBILEPROVISIONS[$i]}") ` + echo "ApplicationIdentifierPrefix: ${INFO}$APP_ID_PREFIX${NC}" + + # Modify entitlements + PlistBuddy -c "Set keychain-access-groups:0 $APP_ID_PREFIX.$APPGROUP" "${ENTITLEMENTS[$i]}" + + echo "" + echo "${SUCCESS}Modify ${INFO}${LOCATIONS[$i]}/Info.plist${NC}…" + # Modify Info.plists + BUNDLEID=( `PlistBuddy -c "print application-identifier " ${ENTITLEMENTS[$i]} | sed 's/^.\{11\}//'` ) + echo "Set Bundle ID: ${INFO}${BUNDLEID}${NC}" + PlistBuddy -c "Set CFBundleIdentifier ${BUNDLEID}" "${LOCATIONS[$i]}/Info.plist" + + # Modify Info.plists with ownCloud custom variables + PlistBuddy -c "Set OCAppGroupIdentifier $APPGROUP" "${LOCATIONS[$i]}/Info.plist" + PlistBuddy -c "Set OCKeychainAccessGroupIdentifier $APPGROUP" "${LOCATIONS[$i]}/Info.plist" + PlistBuddy -c "Set OCAppIdentifierPrefix $APP_ID_PREFIX." "${LOCATIONS[$i]}/Info.plist" + + # Remove old Code Signatures + rm -rf "${LOCATIONS[$i]}/_CodeSignature" + + echo "" +done + +echo "${SUCCESS}Resign App, Extensions and Frameworks…${NC}" +echo "" + +#Resign Swift & Frameworks Libraries +ls "${APPDIR}/Frameworks" | while read file +do + /usr/bin/codesign -fv -s "$IDENTITY" "${APPDIR}/Frameworks/$file" --entitlements "${ENTITLEMENTS[0]}" +done + +# Resign everything +for (( i=(${#MOBILEPROVISIONS[@]} - 1); i>=0; i-- )); +do + /usr/bin/codesign -fv -s "$IDENTITY" "${LOCATIONS[$i]}" --entitlements "${ENTITLEMENTS[$i]}" +done + + +# Generate new Payload +echo "" +echo "${SUCCESS}Packing new ipa…${NC}" +pushd "$APPTEMP" +zip -q -r "$NAME_FINAL_IPA" * +popd + +mv "$APPTEMP/$NAME_FINAL_IPA" $FINAL_IPA + +echo "" +echo "${SUCCESS}Removing temporal items…${NC}" + +# Delete temporal payload folder +echo "Removing temporal folder $APPTEMP" +rm -rf "$APPTEMP" +echo "Removing payload folder $APPPAYLOAD" +rm -rf "$APPPAYLOAD" + +# Delete temporal entitlements files +for (( i=0; i<${#ENTITLEMENTS[@]}; i++ )); +do + if [ -f "${ENTITLEMENTS[$i]}" ]; then + echo "Removing temporal ${ENTITLEMENTS[$i]}" + rm -rf "${ENTITLEMENTS[$i]}" + fi + +done + +echo +echo "${SUCCESS}Signed file:${NC} ${FINAL_IPA}" +echo +echo "${BOLD}${SUCCESS}Signing complete.${NC}" +echo