diff --git a/.gitignore b/.gitignore
index ac1ade4..80fc24d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,6 @@ Carthage/Build
*.pkg
*.pyc
+Package/Python.framework/
+Package/entitlements.plist
+Package/config.mk
diff --git a/Crypt.xcodeproj/project.pbxproj b/Crypt.xcodeproj/project.pbxproj
index 79220f0..6b0c9d5 100644
--- a/Crypt.xcodeproj/project.pbxproj
+++ b/Crypt.xcodeproj/project.pbxproj
@@ -137,22 +137,22 @@
FCD4FD8C1BEE763C00CF7F48 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0930;
+ LastUpgradeCheck = 1150;
ORGANIZATIONNAME = "Graham Gilbert";
TargetAttributes = {
FCD4FD931BEE763C00CF7F48 = {
CreatedOnToolsVersion = 7.1;
- LastSwiftMigration = 0930;
+ LastSwiftMigration = 1150;
};
};
};
buildConfigurationList = FCD4FD8F1BEE763C00CF7F48 /* Build configuration list for PBXProject "Crypt" */;
compatibilityVersion = "Xcode 9.3";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
- English,
en,
+ Base,
);
mainGroup = FCD4FD8B1BEE763C00CF7F48;
productRefGroup = FCD4FD8B1BEE763C00CF7F48;
@@ -216,6 +216,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -258,7 +259,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
@@ -270,6 +271,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -306,7 +308,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
@@ -322,7 +324,7 @@
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 3.3.1;
+ CURRENT_PROJECT_VERSION = 4.0;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Crypt/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
@@ -331,8 +333,8 @@
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
- MACOSX_DEPLOYMENT_TARGET = 10.13;
- MARKETING_VERSION = 3.3.1;
+ MACOSX_DEPLOYMENT_TARGET = 10.14;
+ MARKETING_VERSION = 4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.grahamgilbert.Crypt;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
@@ -342,7 +344,7 @@
SWIFT_OBJC_BRIDGING_HEADER = "Crypt/Crypt-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
- SWIFT_VERSION = 4.2;
+ SWIFT_VERSION = 5.0;
WRAPPER_EXTENSION = bundle;
};
name = Debug;
@@ -355,7 +357,7 @@
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 3.3.1;
+ CURRENT_PROJECT_VERSION = 4.0;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Crypt/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
@@ -364,8 +366,8 @@
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
- MACOSX_DEPLOYMENT_TARGET = 10.13;
- MARKETING_VERSION = 3.3.1;
+ MACOSX_DEPLOYMENT_TARGET = 10.14;
+ MARKETING_VERSION = 4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.grahamgilbert.Crypt;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
@@ -373,7 +375,7 @@
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "Crypt/Crypt-Bridging-Header.h";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
- SWIFT_VERSION = 4.2;
+ SWIFT_VERSION = 5.0;
WRAPPER_EXTENSION = bundle;
};
name = Release;
diff --git a/Crypt/Info.plist b/Crypt/Info.plist
index 555a090..f672ff5 100644
--- a/Crypt/Info.plist
+++ b/Crypt/Info.plist
@@ -15,11 +15,11 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 3.3.1
+ 4.0
CFBundleSignature
????
CFBundleVersion
- 194
+ 205
NSHumanReadableCopyright
Copyright © 2018 The Crypt Project. All rights reserved.
NSPrincipalClass
diff --git a/Crypt/Mechanisms/CryptMechanism.swift b/Crypt/Mechanisms/CryptMechanism.swift
index 283d4fa..890b638 100644
--- a/Crypt/Mechanisms/CryptMechanism.swift
+++ b/Crypt/Mechanisms/CryptMechanism.swift
@@ -152,7 +152,7 @@ class CryptMechanism: NSObject {
var needsEncryption: Bool {
set {
os_log("needsEncryption set to %@", log: CryptMechanism.log, type: .default, newValue as CVarArg)
- let data = NSKeyedArchiver.archivedData(withRootObject: NSNumber.init(value: newValue))
+ guard let data = try? NSKeyedArchiver.archivedData(withRootObject: NSNumber.init(value: newValue), requiringSecureCoding: false) else { return }
_ = setHintData(key: needsEncryptionHintKey, data: data as NSData)
}
@@ -161,10 +161,10 @@ class CryptMechanism: NSObject {
guard let data = getHintData(key: needsEncryptionHintKey) else {
return false
}
- guard let value = NSKeyedUnarchiver.unarchiveObject(with: data as Data) else {
+ guard let value = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NSNumber.self, from: data as Data) else {
return false
}
- return (value as! NSNumber).boolValue
+ return (value).boolValue
}
}
diff --git a/Package/Distribution-Template b/Package/Distribution-Template
index 0a1ecdc..2b574ed 100644
--- a/Package/Distribution-Template
+++ b/Package/Distribution-Template
@@ -4,9 +4,9 @@
-
-
-
+
+
+
diff --git a/Package/FoundationPlist.py b/Package/FoundationPlist.py
deleted file mode 100644
index 1ba059e..0000000
--- a/Package/FoundationPlist.py
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/usr/bin/python
-# encoding: utf-8
-#
-# Copyright 2009-2014 Greg Neagle.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""FoundationPlist.py -- a tool to generate and parse MacOSX .plist files.
-
-This is intended as a drop-in replacement for Python's included plistlib,
-with a few caveats:
- - readPlist() and writePlist() operate only on a filepath,
- not a file object.
- - there is no support for the deprecated functions:
- readPlistFromResource()
- writePlistToResource()
- - there is no support for the deprecated Plist class.
-
-The Property List (.plist) file format is a simple XML pickle supporting
-basic object types, like dictionaries, lists, numbers and strings.
-Usually the top level object is a dictionary.
-
-To write out a plist file, use the writePlist(rootObject, filepath)
-function. 'rootObject' is the top level object, 'filepath' is a
-filename.
-
-To parse a plist from a file, use the readPlist(filepath) function,
-with a file name. It returns the top level object (again, usually a
-dictionary).
-
-To work with plist data in strings, you can use readPlistFromString()
-and writePlistToString().
-"""
-
-# PyLint cannot properly find names inside Cocoa libraries, so issues bogus
-# No name 'Foo' in module 'Bar' warnings. Disable them.
-# pylint: disable=E0611
-from Foundation import NSData
-from Foundation import NSPropertyListSerialization
-from Foundation import NSPropertyListMutableContainers
-from Foundation import NSPropertyListXMLFormat_v1_0
-# pylint: enable=E0611
-
-# Disable PyLint complaining about 'invalid' camelCase names
-# pylint: disable=C0103
-
-
-class FoundationPlistException(Exception):
- """Basic exception for plist errors"""
- pass
-
-class NSPropertyListSerializationException(FoundationPlistException):
- """Read/parse error for plists"""
- pass
-
-class NSPropertyListWriteException(FoundationPlistException):
- """Write error for plists"""
- pass
-
-def readPlist(filepath):
- """
- Read a .plist file from filepath. Return the unpacked root object
- (which is usually a dictionary).
- """
- plistData = NSData.dataWithContentsOfFile_(filepath)
- dataObject, dummy_plistFormat, error = (
- NSPropertyListSerialization.
- propertyListFromData_mutabilityOption_format_errorDescription_(
- plistData, NSPropertyListMutableContainers, None, None))
- if dataObject is None:
- if error:
- error = error.encode('ascii', 'ignore')
- else:
- error = "Unknown error"
- errmsg = "%s in file %s" % (error, filepath)
- raise NSPropertyListSerializationException(errmsg)
- else:
- return dataObject
-
-
-def readPlistFromString(data):
- '''Read a plist data from a string. Return the root object.'''
- try:
- plistData = buffer(data)
- except TypeError, err:
- raise NSPropertyListSerializationException(err)
- dataObject, dummy_plistFormat, error = (
- NSPropertyListSerialization.
- propertyListFromData_mutabilityOption_format_errorDescription_(
- plistData, NSPropertyListMutableContainers, None, None))
- if dataObject is None:
- if error:
- error = error.encode('ascii', 'ignore')
- else:
- error = "Unknown error"
- raise NSPropertyListSerializationException(error)
- else:
- return dataObject
-
-
-def writePlist(dataObject, filepath):
- '''
- Write 'rootObject' as a plist to filepath.
- '''
- plistData, error = (
- NSPropertyListSerialization.
- dataFromPropertyList_format_errorDescription_(
- dataObject, NSPropertyListXMLFormat_v1_0, None))
- if plistData is None:
- if error:
- error = error.encode('ascii', 'ignore')
- else:
- error = "Unknown error"
- raise NSPropertyListSerializationException(error)
- else:
- if plistData.writeToFile_atomically_(filepath, True):
- return
- else:
- raise NSPropertyListWriteException(
- "Failed to write plist data to %s" % filepath)
-
-
-def writePlistToString(rootObject):
- '''Return 'rootObject' as a plist-formatted string.'''
- plistData, error = (
- NSPropertyListSerialization.
- dataFromPropertyList_format_errorDescription_(
- rootObject, NSPropertyListXMLFormat_v1_0, None))
- if plistData is None:
- if error:
- error = error.encode('ascii', 'ignore')
- else:
- error = "Unknown error"
- raise NSPropertyListSerializationException(error)
- else:
- return str(plistData)
-
-
diff --git a/Package/Makefile b/Package/Makefile
index 6631565..6db985d 100644
--- a/Package/Makefile
+++ b/Package/Makefile
@@ -1,35 +1,41 @@
include /usr/local/share/luggage/luggage.make
-PB_EXTRA_ARGS+= --info "./PackageInfo"
+include config.mk
+PB_EXTRA_ARGS+= --info "./PackageInfo" --sign "${DEV_INSTALL_CERT}"
TITLE=Crypt
GITVERSION=$(shell ./build_no.sh)
BUNDLE_VERSION=$(shell /usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "../Crypt/Info.plist")
PACKAGE_VERSION=${BUNDLE_VERSION}.${GITVERSION}
REVERSE_DOMAIN=com.grahamgilbert
PACKAGE_NAME=${TITLE}
+PYTHONTOOLDIR=/tmp/relocatable-python
PAYLOAD=\
- pack-plugin\
- pack-script-postinstall\
- pack-Library-LaunchDaemons-com.grahamgilbert.crypt.plist \
- pack-checkin \
- pack-script-preinstall
+ pack-plugin\
+ pack-script-postinstall\
+ pack-Library-LaunchDaemons-com.grahamgilbert.crypt.plist \
+ pack-checkin \
+ pack-script-preinstall
#################################################
-build: clean-crypt
+build: check_variables clean-crypt
xcodebuild -project ../Crypt.xcodeproj -configuration Release
clean-crypt:
rm -rf ../build
+ @rm -rf Crypt.pkg
pack-plugin: build
@sudo ${RM} -rf ${WORK_D}
@sudo mkdir -p ${WORK_D}/Library/Security/SecurityAgentPlugins
@sudo ${CP} -R ../build/Release/Crypt.bundle ${WORK_D}/Library/Security/SecurityAgentPlugins/Crypt.bundle
+ @sudo codesign --force --deep -s "${DEV_APP_CERT}" ${WORK_D}/Library/Security/SecurityAgentPlugins/Crypt.bundle/Contents/Frameworks/*
+ @sudo codesign --force --deep -s "${DEV_APP_CERT}" ${WORK_D}/Library/Security/SecurityAgentPlugins/Crypt.bundle/Contents/MacOS/*
-pack-checkin: l_Library
+pack-checkin: clean-python build-python l_Library
@sudo mkdir -p ${WORK_D}/Library/Crypt
@sudo ${CP} checkin ${WORK_D}/Library/Crypt/checkin
- @sudo ${CP} FoundationPlist.py ${WORK_D}/Library/Crypt/FoundationPlist.py
+ @sudo ${CP} -R Python.framework ${WORK_D}/Library/Crypt/Python.framework
+ @sudo /bin/ln -s /Library/Crypt/Python.framework/Versions/3.8/bin/python3 ${WORK_D}/Library/Crypt/python
@sudo chown -R root:wheel ${WORK_D}/Library/Crypt
@sudo chmod 755 ${WORK_D}/Library/Crypt/checkin
@@ -39,3 +45,34 @@ dist: pkg
@sudo productbuild --distribution Distribution Crypt-${BUNDLE_VERSION}.pkg
@sudo rm -f Crypt.pkg
@sudo rm -f Distribution
+
+notarize:
+ @./notarize.sh "${APPLE_ACC_USER}" "${APPLE_ACC_PWD}"
+
+clean-python:
+ @rm -rf Python.framework
+ @rm -rf ${WORK_D}/Library/Crypt/Python.framework
+ @rm -rf entitlements.plist
+
+build-python:
+ # Why not just run the make_relocatable_python.py here?
+ # It can't find the temp folder that the python pkg is expanded into
+ # if issued directly from Make, so we're currently shelling out until
+ # we grok the GNU better. PS THANKS SHEA
+ @rm -rf "${PYTHONTOOLDIR}"
+ @git clone https://github.com/gregneagle/relocatable-python.git "${PYTHONTOOLDIR}"
+ @./build_python_framework.sh "${DEV_APP_CERT}"
+
+check_variables:
+ifndef DEV_INSTALL_CERT
+$(error "DEV_INSTALL_CERT" is not set)
+endif
+ifndef DEV_APP_CERT
+$(error "DEV_APP_CERT" is not set)
+endif
+ifndef APPLE_ACC_USER
+$(error "APPLE_ACC_USER" is not set)
+endif
+ifndef APPLE_ACC_PWD
+$(error "APPLE_ACC_PWD" is not set)
+endif
diff --git a/Package/build.sh b/Package/build.sh
new file mode 100755
index 0000000..cafd44c
--- /dev/null
+++ b/Package/build.sh
@@ -0,0 +1,11 @@
+#!/bin/zsh
+# builds the package and notarizes
+# requires a config.mk file in the same directory with some variables defined like below.
+
+# DEV_INSTALL_CERT=Developer ID Installer: Example, Inc (ABCDEF12345)
+# DEV_APP_CERT=Developer ID Application: Example, Inc (ABCDEF12345)
+# APPLE_ACC_USER=your_apple_dev_email@example.com
+# APPLE_ACC_PWD=your-one-time-app-password
+
+sudo make pkg
+sudo make notarize
diff --git a/Package/build_python_framework.sh b/Package/build_python_framework.sh
new file mode 100755
index 0000000..40a7fa7
--- /dev/null
+++ b/Package/build_python_framework.sh
@@ -0,0 +1,26 @@
+#!/bin/zsh
+# Build script for Python 3 framework for Sal scripts
+TOOLSDIR=$(dirname "$0")
+PYTHON_VERSION=3.8.2
+
+# build the framework
+/tmp/relocatable-python/make_relocatable_python_framework.py \
+ --python-version "${PYTHON_VERSION}" \
+ --pip-requirements requirements.txt \
+ --destination "${TOOLSDIR}"
+
+DevApp=$1
+
+# sign all the bits of python with our Apple Developer ID Installer: cert.
+find ${TOOLSDIR}/Python.framework -name '*.pyc' -delete
+find ${TOOLSDIR}/Python.framework/Versions/3.8/lib/ -type f -perm -u=x -exec codesign --force --deep --verbose -s "$DevApp" {} \;
+find ${TOOLSDIR}/Python.framework/Versions/3.8/bin/ -type f -perm -u=x -exec codesign --force --deep --verbose -s "$DevApp" {} \;
+find ${TOOLSDIR}/Python.framework/Versions/3.8/lib/ -type f -name "*dylib" -exec codesign --force --deep --verbose -s "$DevApp" {} \;
+
+/usr/libexec/PlistBuddy -c "Add :com.apple.security.cs.allow-unsigned-executable-memory bool true" ${TOOLSDIR}/entitlements.plist
+
+codesign --force --options runtime --entitlements $TOOLSDIR/entitlements.plist --deep --verbose -s "$DevApp" $TOOLSDIR/Python.framework/Versions/3.8/Resources/Python.app/
+codesign --force --deep --options runtime --entitlements $TOOLSDIR/entitlements.plist --deep --verbose -s "$DevApp" $TOOLSDIR/Python.framework/Versions/3.8/bin/*
+codesign --force --deep --options runtime --entitlements $TOOLSDIR/entitlements.plist --deep --verbose -s "$DevApp" $TOOLSDIR/Python.framework/Versions/3.8/lib/*
+codesign --force --deep --options runtime --entitlements $TOOLSDIR/entitlements.plist --deep --verbose -s "$DevApp" $TOOLSDIR/Python.framework/Versions/3.8/Python
+codesign --force --deep --verbose -s "$DevApp" $TOOLSDIR/Python.framework
diff --git a/Package/checkin b/Package/checkin
index fbc59c9..76b814f 100644
--- a/Package/checkin
+++ b/Package/checkin
@@ -1,35 +1,29 @@
-#!/usr/bin/python
+#!/Library/Crypt/python
+import datetime
+import json
import logging
-import subprocess
import os
-import urllib
+import platform
+import plistlib
+import subprocess
import sys
-import datetime
import syslog
-import platform
-import json
+import urllib
from distutils.version import LooseVersion
-import FoundationPlist
-
-from Foundation import NSDate
-from Foundation import NSArray
-from Foundation import CFPreferencesAppSynchronize
-from Foundation import CFPreferencesCopyAppValue
-from Foundation import CFPreferencesSetValue
-from Foundation import kCFPreferencesAnyUser
-from Foundation import kCFPreferencesCurrentHost
-from SystemConfiguration import SCDynamicStoreCopyConsoleUser
+import Foundation
+import SystemConfiguration
+BUNDLE_ID = "com.grahamgilbert.crypt"
+LOG_FILE = "/var/log/crypt.log"
-BUNDLE_ID = 'com.grahamgilbert.crypt'
-LOG_FILE = '/var/log/crypt.log'
-
-logging.basicConfig(format='%(asctime)s - %(levelname)s: %(message)s',
- datefmt='%Y-%m-%d %I:%M:%S %p',
- level=logging.DEBUG,
- filename=LOG_FILE)
+logging.basicConfig(
+ format="%(asctime)s - %(levelname)s: %(message)s",
+ datefmt="%Y-%m-%d %I:%M:%S %p",
+ level=logging.DEBUG,
+ filename=LOG_FILE,
+)
stdout_logging = logging.StreamHandler()
stdout_logging.setFormatter(logging.Formatter())
logging.getLogger().addHandler(stdout_logging)
@@ -37,7 +31,7 @@ logging.getLogger().addHandler(stdout_logging)
def get_console_user():
"""returns the current console user via PyObjc"""
- cfuser = SCDynamicStoreCopyConsoleUser(None, None, None)
+ cfuser = SystemConfiguration.SCDynamicStoreCopyConsoleUser(None, None, None)
return cfuser[0]
@@ -48,13 +42,13 @@ def get_os_version(only_major_minor=True, as_tuple=False):
as_tuple: Boolean. If True, return a tuple of ints, otherwise a string.
100%, completely stolen from Munki.
"""
- os_version_tuple = platform.mac_ver()[0].split('.')
+ os_version_tuple = platform.mac_ver()[0].split(".")
if only_major_minor:
os_version_tuple = os_version_tuple[0:2]
if as_tuple:
return tuple(map(int, os_version_tuple))
else:
- return '.'.join(os_version_tuple)
+ return ".".join(os_version_tuple)
def set_pref(pref_name, pref_value):
@@ -64,10 +58,14 @@ def set_pref(pref_name, pref_value):
values that control the behavior of crypt may be overridden
elsewhere (by MCX, for example)"""
try:
- CFPreferencesSetValue(
- pref_name, pref_value, BUNDLE_ID,
- kCFPreferencesAnyUser, kCFPreferencesCurrentHost)
- CFPreferencesAppSynchronize(BUNDLE_ID)
+ Foundation.CFPreferencesSetValue(
+ pref_name,
+ pref_value,
+ BUNDLE_ID,
+ Foundation.kCFPreferencesAnyUser,
+ Foundation.kCFPreferencesCurrentHost,
+ )
+ Foundation.CFPreferencesAppSynchronize(BUNDLE_ID)
except Exception:
pass
@@ -81,24 +79,24 @@ def pref(pref_name):
- default_prefs defined here.
"""
default_prefs = {
- 'RemovePlist': True,
- 'RotateUsedKey': True,
- 'OutputPath': '/private/var/root/crypt_output.plist',
- 'ValidateKey': True,
- 'KeyEscrowInterval': 1,
- 'AdditionalCurlOpts': []
+ "RemovePlist": True,
+ "RotateUsedKey": True,
+ "OutputPath": "/private/var/root/crypt_output.plist",
+ "ValidateKey": True,
+ "KeyEscrowInterval": 1,
+ "AdditionalCurlOpts": [],
}
- pref_value = CFPreferencesCopyAppValue(pref_name, BUNDLE_ID)
+ pref_value = Foundation.CFPreferencesCopyAppValue(pref_name, BUNDLE_ID)
if pref_value is None:
pref_value = default_prefs.get(pref_name)
# we're using a default value. We'll write it out to
# /Library/Preferences/.plist for admin
# discoverability
set_pref(pref_name, pref_value)
- if isinstance(pref_value, NSDate):
+ if isinstance(pref_value, Foundation.NSDate):
# convert NSDate/CFDates to strings
pref_value = str(pref_value)
- elif isinstance(pref_value, NSArray):
+ elif isinstance(pref_value, Foundation.NSArray):
pref_value = list(pref_value)
return pref_value
@@ -107,45 +105,47 @@ def GetMacName():
"""
Returns the name of the mac
"""
- theprocess = ['scutil', '--get', 'ComputerName']
- thename = subprocess.Popen(theprocess, stdin=subprocess.PIPE,
- stdout=subprocess.PIPE).communicate()[0]
- thename = thename.strip()
- return thename
+ cmd = ["/usr/sbin/scutil", "--get", "ComputerName"]
+ try:
+ return subprocess.check_output(cmd).rstrip()
+ except subprocess.SubprocessError:
+ return "UNKNOWN_COMPUTERNAME"
def curl_escape(s):
- return s.encode('utf-8').encode('string_escape').replace('"', '\\"')
+ return s.replace('"', '\\"')
def build_curl_config_file(d):
lines = []
for k, v in d.items():
- lines.append('%s = "%s"' % (k, curl_escape(v)))
- return '\n'.join(lines)
+ lines.append(f'{k} = "{curl_escape(v)}"')
+ return "\n".join(lines)
def escrow_key(plist):
- logging.info('Attempting to Escrow Key...')
- server_url = pref('ServerURL')
- logging.debug('ServerURL Pref set to: {0}...'.format(server_url))
+ logging.info("Attempting to Escrow Key...")
+ server_url = pref("ServerURL")
+ logging.debug(f"ServerURL Pref set to: {server_url}...")
if server_url is None:
return False
if server_url.endswith("/"):
- theurl = server_url+"checkin/"
+ theurl = server_url + "checkin/"
else:
- theurl = server_url+"/checkin/"
+ theurl = server_url + "/checkin/"
# In the future, we're going to submit the whole plist, but for now...
- serial = plist['SerialNumber']
- key = plist['RecoveryKey']
- username = plist['EnabledUser']
+ serial = plist["SerialNumber"]
+ key = plist["RecoveryKey"]
+ username = plist["EnabledUser"]
macname = GetMacName()
mydata = [
- ('serial', serial), ('recovery_password', key),
- ('username', username), ('macname', macname)
+ ("serial", serial),
+ ("recovery_password", key),
+ ("username", username),
+ ("macname", macname),
]
- mydata = urllib.urlencode(mydata)
- config_file = build_curl_config_file({'url': theurl, 'data': mydata})
+ mydata = urllib.parse.urlencode(mydata)
+ config_file = build_curl_config_file({"url": theurl, "data": mydata})
# --fail: Fail silently (no output at all) on server errors.
# --silent: Silent mode. Don't show progress meter or error messages.
# --show-error: When used with silent, it makes curl show an error message
@@ -156,23 +156,22 @@ def escrow_key(plist):
# The config file is a text file in which command line arguments can be
# written which then will be used as if they were written on the actual
# command line.
- cmd = ['/usr/bin/curl', '--fail', '--silent',
- '--show-error', '--location']
- if pref('AdditionalCurlOpts') and isinstance(pref('AdditionalCurlOpts'), list):
- for curl_opt in pref('AdditionalCurlOpts'):
+ cmd = ["/usr/bin/curl", "--fail", "--silent", "--show-error", "--location"]
+ if all([pref("AdditionalCurlOpts"), isinstance(pref("AdditionalCurlOpts"), list)]):
+ for curl_opt in pref("AdditionalCurlOpts"):
cmd.append(curl_opt)
- cmd.extend(['--config', '-'])
- task = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- stdin=subprocess.PIPE)
- (output, error) = task.communicate(input=config_file)
+ cmd.extend(["--config", "-"])
+ task = subprocess.Popen(
+ cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE
+ )
+ (output, error) = task.communicate(input=config_file.encode())
if task.returncode == 0:
- logging.info('Key escrow successful.')
+ logging.info("Key escrow successful.")
server_initiated_rotation(output)
return True
else:
- logging.error('Key escrow unsuccessful.')
+ logging.error("Key escrow unsuccessful.")
return False
@@ -184,19 +183,19 @@ def server_initiated_rotation(output):
try:
json_output = json.loads(output)
except ValueError:
- return ''
+ return ""
- if not pref('RotateUsedKey') or pref('RemovePlist'):
+ if not pref("RotateUsedKey") or pref("RemovePlist"):
# Don't do anything if we don't care about the good stuff
- return ''
+ return ""
- output_plist = pref('OutputPath')
+ output_plist = pref("OutputPath")
if not os.path.isfile(output_plist):
# Need this to be here too (which it should, but you never know..)
- return ''
+ return ""
- if json_output.get('rotation_required', False):
- logging.info('Removing output plist for rotation at next login.')
+ if json_output.get("rotation_required", False):
+ logging.info("Removing output plist for rotation at next login.")
os.remove(output_plist)
post_run_command()
@@ -208,52 +207,52 @@ def using_recovery_key():
"""
macos_version = get_os_version(only_major_minor=False, as_tuple=False)
- if LooseVersion(macos_version) >= LooseVersion('10.15'):
- logging.info('Checking if using a recovery key is unstable on 10.15. '
- 'Skipping.')
+ if LooseVersion(macos_version) >= LooseVersion("10.15"):
+ logging.info(
+ "Checking if using a recovery key is unstable on 10.15. " "Skipping."
+ )
return False
- cmd = ['/usr/bin/fdesetup', 'usingrecoverykey']
+ cmd = ["/usr/bin/fdesetup", "usingrecoverykey"]
try:
using_key = subprocess.check_output(cmd).strip()
except Exception:
- logging.warning('fdesetup usingrecoverykey failed to run correctly')
+ logging.warning("fdesetup usingrecoverykey failed to run correctly")
return False
- if using_key == 'true':
- logging.warning('Detected Recovery Key use.')
+ if using_key == "true":
+ logging.warning("Detected Recovery Key use.")
return True
else:
return False
def post_run_command():
- run_command = pref('PostRunCommand')
- output_plist = pref('OutputPath')
+ run_command = pref("PostRunCommand")
+ output_plist = pref("OutputPath")
if run_command and not os.path.isfile(output_plist):
- logging.info('Running {}'.format(run_command))
+ logging.info(f"Running {run_command}")
try:
output = subprocess.check_output(run_command)
logging.info(output)
except subprocess.CalledProcessError as e:
- logging.error('Failed to run PostRunCommand: {}'.format(e))
+ logging.error(f"Failed to run PostRunCommand: {e}")
def get_recovery_key(key_location):
"""Returns recovery key as a string... If we failed
to get the proper information, returns an empty string"""
# checks to see if recovery key preference is set
+
try:
- keyplist = FoundationPlist.readPlist(key_location)
- recovery_key = keyplist['RecoveryKey'].strip()
- return recovery_key
- except FoundationPlist.NSPropertyListSerializationException:
- logging.info(
- 'We had trouble getting info from {0}...'.format(key_location))
- return False
+ with open(key_location, "rb") as fp:
+ keyplist = plistlib.load(fp)
+ return keyplist["RecoveryKey"].strip()
+ except (FileNotFoundError, plistlib.InvalidFileException):
+ logging.info(f"We had trouble getting info from {key_location}...")
+ return ""
except KeyError:
- logging.warning(
- 'Problem with Key: "RecoveryKey" in {0}...'.format(key_location))
- return False
+ logging.warning(f"Problem with Key: RecoveryKey in {key_location}...")
+ return ""
def rotate_invalid_key(plist_path):
@@ -265,33 +264,32 @@ def rotate_invalid_key(plist_path):
"""
# a work aroud for https://github.com/grahamgilbert/crypt/issues/68
if not get_console_user():
- logging.info('Skipping Validation, no user is logged in.')
+ logging.info("Skipping Validation, no user is logged in.")
return True
macos_version = get_os_version(only_major_minor=False, as_tuple=False)
- if LooseVersion('10.12.5') > LooseVersion(macos_version):
- logging.warning('macOS version is too old to run reliably')
+ if LooseVersion("10.12.5") > LooseVersion(macos_version):
+ logging.warning("macOS version is too old to run reliably")
return False
if os.path.isfile(plist_path):
recovery_key = get_recovery_key(plist_path)
else:
- logging.warning('Recovery key is not present on disk')
+ logging.warning("Recovery key is not present on disk")
return False
- if recovery_key is not False:
- key_is_valid = validate_key(recovery_key)
- else:
- logging.warning('Could not retrieve recovery key from plist')
+ if not recovery_key:
+ logging.warning("Could not retrieve recovery key from plist.")
+ os.remove(plist_path)
return False
- if not key_is_valid:
- logging.info('Stored recovery key is not valid, removing from disk')
+ if not validate_key(recovery_key):
+ logging.info("Stored recovery key is not valid, removing from disk")
os.remove(plist_path)
return False
- logging.info('Stored recovery key is valid.')
+ logging.info("Stored recovery key is valid.")
return True
@@ -299,56 +297,65 @@ def validate_key(current_key):
"""Validates the given recovery key against FileVault, returns True
or False accordingly"""
- key = {'Password': current_key}
- input_plist = FoundationPlist.writePlistToString(key)
- cmd = subprocess.Popen(['/usr/bin/fdesetup', 'validaterecovery',
- '-inputplist'],
- stdout=subprocess.PIPE, stdin=subprocess.PIPE,
- stderr=subprocess.PIPE)
+ key = {"Password": current_key}
+ input_plist = plistlib.dumps(key)
+ cmd = subprocess.Popen(
+ ["/usr/bin/fdesetup", "validaterecovery", "-inputplist"],
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
stdout_data, err = cmd.communicate(input=input_plist)
if err:
logging.error(err)
- if stdout_data.strip() == 'true':
+ if stdout_data.rstrip() == b"true":
return True
else:
- logging.error('Recovery Key could not be validated.')
- logging.error('Failed with Error: {}'.format(stdout_data))
+ logging.error("Recovery Key could not be validated.")
+ logging.error(f"Failed with Error: {stdout_data}")
return False
def rotate_key(current_key, plist):
"""This rotates the recovery key to something new
by using the current recovery key"""
- rotate_inputplist = {'Password': current_key}
- input_plist = FoundationPlist.writePlistToString(rotate_inputplist)
- cmd = subprocess.Popen(['/usr/bin/fdesetup', 'changerecovery', '-personal',
- '-outputplist', '-inputplist'],
- stdout=subprocess.PIPE, stdin=subprocess.PIPE,
- stderr=subprocess.PIPE)
+ rotate_inputplist = {"Password": current_key}
+ input_plist = plistlib.dumps(rotate_inputplist)
+ cmd = subprocess.Popen(
+ [
+ "/usr/bin/fdesetup",
+ "changerecovery",
+ "-personal",
+ "-outputplist",
+ "-inputplist",
+ ],
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
stdout_data, err = cmd.communicate(input=input_plist)
- logging.info('Attempting to rotate Recovery Key.')
+ logging.info("Attempting to rotate Recovery Key.")
try:
- output_plist = FoundationPlist.readPlistFromString(stdout_data)
-
- FoundationPlist.writePlist(output_plist, plist)
- logging.info('Recovery Key rotated.')
+ output_plist = plistlib.loads(stdout_data)
+ with open(plist, "wb") as fp:
+ plistlib.dump(output_plist, fp)
+ logging.info("Recovery Key rotated.")
except Exception:
if err:
- logging.warning('Encountered error Key Rotation: {0}.'.format(err))
+ logging.warning(f"Encountered error Key Rotation: {err}.")
def get_enabled_user():
"""Crypt needs an enabled user in its plist that our normal output
doesn't give us so we need to add a user to the plist"""
- if pref('SkipUsers'):
- nonusers = pref('SkipUsers')
+ if pref("SkipUsers"):
+ nonusers = pref("SkipUsers")
else:
nonusers = []
- fde_users = subprocess.check_output(
- ["/usr/bin/fdesetup", "list"]).split('\n')
+ fde_users = subprocess.check_output(["/usr/bin/fdesetup", "list"]).split("\n")
for user in fde_users:
- if not user.split(',')[0] in nonusers:
- cryptuser = user.split(',')[0]
+ if not user.split(",")[0] in nonusers:
+ cryptuser = user.split(",")[0]
break
return cryptuser
@@ -357,68 +364,72 @@ def rotate_if_used(key_path):
"""Checks to see if the recovery key was used to unlock the machine
if it was then use our current key to rotate it"""
if not using_recovery_key():
- return ''
+ return ""
if not os.path.isfile(key_path):
- logging.warning('Could not locate {0}'.format(key_path))
- rotate_message = 'Recovery Key has been used.. Attempting to Rotate'
- logging.info(rotate_message)
+ logging.warning(f"Could not locate {key_path}")
+ return ""
+ logging.info("Recovery Key has been used.. Attempting to Rotate.")
current_key = get_recovery_key(key_path)
valid_key = validate_key(current_key)
if not valid_key:
- logging.error('Our current key is not valid')
- return ''
+ logging.error("Our current key is not valid.")
+ return ""
rotate_key(current_key, key_path)
def main():
- plist_path = pref('OutputPath')
- logging.info('OutputPath Pref is set to: {}'.format(plist_path))
- if pref('RotateUsedKey'):
+ plist_path = pref("OutputPath")
+ logging.info(f"OutputPath Pref is set to: {plist_path}")
+ if pref("RotateUsedKey"):
rotate_if_used(plist_path)
- if pref('RotateUsedKey') and pref('ValidateKey') and \
- not pref('RemovePlist'):
+ if pref("RotateUsedKey") and pref("ValidateKey") and not pref("RemovePlist"):
rotate_invalid_key(plist_path)
post_run_command()
if os.path.isfile(plist_path):
- plist = FoundationPlist.readPlist(plist_path)
+ try:
+ with open(plist_path, "rb") as fp:
+ plist = plistlib.load(fp)
+ except plistlib.InvalidFileException as err:
+ logging.error(f"Failed to read {plist_path} with error: {err}")
+ exit(-1)
# Exit if we've run this within the last hour
try:
- enableduser = plist['EnabledUser']
+ enableduser = plist["EnabledUser"]
except KeyError as e:
enableduser = get_console_user()
- skippedusers = ['root', '_mbsetupuser']
+ skippedusers = ["root", "_mbsetupuser"]
if not enableduser or enableduser in skippedusers:
enableduser = get_enabled_user()
- plist['EnabledUser'] = enableduser
- if 'last_run' in plist:
+ plist["EnabledUser"] = enableduser
+ if "last_run" in plist:
try:
- escrow_interval = int(pref('KeyEscrowInterval'))
+ escrow_interval = int(pref("KeyEscrowInterval"))
except Exception:
escrow_interval = 1
- logging.info('KeyEscrowInterval set to: {} hour(s)...'.format(
- escrow_interval))
+ logging.info(f"KeyEscrowInterval set to: {escrow_interval} hour(s)...")
now = datetime.datetime.now()
hour_ago = now - datetime.timedelta(hours=escrow_interval)
- if plist['last_run'] > hour_ago:
+ if plist["last_run"] > hour_ago:
logging.info(
- 'We escrowed less than {} hour(s) ago. Skipping...'.format(
- escrow_interval))
+ f"We escrowed less than {escrow_interval} hour(s) ago. Skipping..."
+ )
sys.exit(0)
escrow_result = escrow_key(plist=plist)
if escrow_result and os.path.isfile(plist_path):
- remove_plist = pref('RemovePlist')
- plist['escrow_success'] = True
- plist['last_run'] = datetime.datetime.now()
- FoundationPlist.writePlist(plist, plist_path)
+ remove_plist = pref("RemovePlist")
+ plist["escrow_success"] = True
+ plist["last_run"] = datetime.datetime.now()
+ with open(plist_path, "wb") as fp:
+ plistlib.dump(plist, fp)
if remove_plist is True:
+ logging.info("Removing plist due to configuration.")
os.remove(plist_path)
- logging.info('Removing plist due to configuration.')
else:
- os.chmod(plist_path, 0600)
- logging.info('Ensuring permissions on plist.')
+ logging.info("Ensuring permissions on plist.")
+ os.chmod(plist_path, 600)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/Package/notarize.sh b/Package/notarize.sh
new file mode 100755
index 0000000..4066ceb
--- /dev/null
+++ b/Package/notarize.sh
@@ -0,0 +1,64 @@
+#!/bin/zsh
+# encoding: utf-8
+
+# Borrowed with love from https://github.com/munki/munki/pull/986/files
+# Big thanks to https://github.com/lifeunexpected
+
+# Tip: if you get “You must first sign the relevant contracts online. (1048)” error
+# Go to Apple.developer.com and sign in with the account you are trying to notarize the app with and agree to the updated license agreement.
+
+BUNDLE_ID="com.grahamgilbert.Crypt"
+BUNDLE_PKG="./Crypt.pkg"
+
+if [[ "$1" == "" ]]; then
+ echo "Couldn't find a 'Apple Developer account e-mail' as argument 1"
+ exit -1
+else
+ AppleAcc=$1
+fi
+if [[ "$2" == "" ]]; then
+ echo "Couldn't find an 'Apple Developer app-specific password' as argument 2"
+ echo "More info at https://support.apple.com/en-us/HT204397"
+ exit -1
+else
+ AppleAccPwd=$2
+fi
+
+# create temporary files
+NOTARIZE_APP_LOG=$(mktemp -t notarize-app)
+NOTARIZE_INFO_LOG=$(mktemp -t notarize-info)
+
+# delete temporary files on exit
+function finish {
+ rm "$NOTARIZE_APP_LOG" "$NOTARIZE_INFO_LOG"
+}
+trap finish EXIT
+
+# submit app for notarization
+echo "Submitting App $BUNDLE_PKG for Notarization."
+if ! xcrun altool --notarize-app --primary-bundle-id "$BUNDLE_ID" --username "$AppleAcc" --password "$AppleAccPwd" -f "$BUNDLE_PKG" > "$NOTARIZE_APP_LOG" 2>&1; then
+ cat "$NOTARIZE_APP_LOG" 1>&2
+ exit 1
+fi
+
+cat "$NOTARIZE_APP_LOG"
+RequestUUID=$(awk -F ' = ' '/RequestUUID/ {print $2}' "$NOTARIZE_APP_LOG")
+
+# check status periodically
+while sleep 30 && date; do
+echo "Waiting on Apple too approve the notarization so it can be stapled. This can take a few minutes or more. Script auto checks every 30 sec"
+ # check notarization status
+
+ if ! xcrun altool --notarization-info "$RequestUUID" --username "$AppleAcc" --password "$AppleAccPwd" > "$NOTARIZE_INFO_LOG" 2>&1; then
+ cat "$NOTARIZE_INFO_LOG" 1>&2
+ exit 1
+ fi
+ cat "$NOTARIZE_INFO_LOG"
+
+ # once notarization is complete, run stapler and exit
+ if ! grep -q "Status: in progress" "$NOTARIZE_INFO_LOG"; then
+ xcrun stapler staple "$BUNDLE_PKG"
+ exit $?
+ fi
+
+done
diff --git a/Package/postinstall b/Package/postinstall
index ff7cc0a..bc12349 100644
--- a/Package/postinstall
+++ b/Package/postinstall
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/Library/Crypt/python
# Copyright 2015 Crypt Project.
#
@@ -38,84 +38,93 @@ from subprocess import PIPE, STDOUT, Popen
system_login_console_plist = "/private/var/tmp/system.login.console.plist"
## Path to authenticate.plist
-#authenticate_plist = "/private/var/tmp/authenticate.plist"
+# authenticate_plist = "/private/var/tmp/authenticate.plist"
## Mechs that support FV2AuthPlugin
-fv2_mechs = ["Crypt:Check,privileged","Crypt:CryptGUI","Crypt:Enablement,privileged"]
+fv2_mechs = ["Crypt:Check,privileged", "Crypt:CryptGUI", "Crypt:Enablement,privileged"]
fv2_index_mech = "loginwindow:done"
fv2_index_offset = 0
+
def bash_command(script):
try:
return subprocess.check_output(script)
- except (subprocess.CalledProcessError, OSError), err:
- sys.exit("[* Error] **%s** [%s]" % (err, str(script)))
+ except (subprocess.CalledProcessError, OSError) as err:
+ sys.exit(f"[* Error] **{err}** [{str(script)}]")
+
def remove_mechs_in_db(db, mech_list):
for mech in mech_list:
- for old_mech in filter(lambda x: mech in x, db['mechanisms']):
- db['mechanisms'].remove(old_mech)
+ for old_mech in filter(lambda x: mech in x, db["mechanisms"]):
+ db["mechanisms"].remove(old_mech)
return db
+
def set_mechs_in_db(db, mech_list, index_mech, index_offset):
## Clear away any previous configs
db = remove_mechs_in_db(db, mech_list)
## Add mech_list to db
- i = int(db['mechanisms'].index(index_mech)) + index_offset
+ i = int(db["mechanisms"].index(index_mech)) + index_offset
for mech in mech_list:
- db['mechanisms'].insert(i, mech)
+ db["mechanisms"].insert(i, mech)
i += 1
return db
+
def edit_authdb():
## Export "system.login.console"
- system_login_console = bash_command(["/usr/bin/security", "authorizationdb", "read", "system.login.console"])
- f_c = open(system_login_console_plist, 'w')
- f_c.write(system_login_console)
+ system_login_console = bash_command(
+ ["/usr/bin/security", "authorizationdb", "read", "system.login.console"]
+ )
+ f_c = open(system_login_console_plist, "w")
+ f_c.write(system_login_console.decode())
f_c.close()
## Export "authenticate"
- #authenticate = bash_command(["/usr/bin/security", "authorizationdb", "read", "authenticate"])
- #f_a = open(authenticate_plist, 'w')
- #f_a.write(authenticate)
- #f_a.close()
+ # authenticate = bash_command(["/usr/bin/security", "authorizationdb", "read", "authenticate"])
+ # f_a = open(authenticate_plist, 'w')
+ # f_a.write(authenticate)
+ # f_a.close()
## Leave the for loop. Possible support for ScreenSaver unlock
for p in [system_login_console_plist]:
## Parse the plist
- d = plistlib.readPlist(p)
+ with open(p, "rb") as fp:
+ d = plistlib.load(fp)
## Add FV2 mechs
d = set_mechs_in_db(d, fv2_mechs, fv2_index_mech, fv2_index_offset)
## Write out the changes
- plistlib.writePlist(d, p)
+ with open(p, "wb") as fp:
+ plistlib.dump(d, fp)
f_c = open(system_login_console_plist, "r")
- p = Popen(["/usr/bin/security", "authorizationdb", "write", "system.login.console"], stdout=PIPE, stdin=PIPE, stderr=PIPE)
- stdout_data = p.communicate(input=f_c.read())
+ p = Popen(
+ ["/usr/bin/security", "authorizationdb", "write", "system.login.console"],
+ stdout=PIPE,
+ stdin=PIPE,
+ stderr=PIPE,
+ )
+ stdout_data = p.communicate(input=f_c.read().encode())
f_c.close()
- #f_a = open(authenticate_plist, "r")
- #p = Popen(["/usr/bin/security", "authorizationdb", "write", "authenticate"], stdout=PIPE, stdin=PIPE, stderr=PIPE)
- #stdout_data = p.communicate(input=f_a.read())
- #f_a.close()
+ # f_a = open(authenticate_plist, "r")
+ # p = Popen(["/usr/bin/security", "authorizationdb", "write", "authenticate"], stdout=PIPE, stdin=PIPE, stderr=PIPE)
+ # stdout_data = p.communicate(input=f_a.read())
+ # f_a.close()
+
def check_root():
if not os.geteuid() == 0:
sys.exit("\nOnly root can run this script\n")
-def check_os():
- OSVersion, _, _ = platform.mac_ver()
- OSVersion = int(OSVersion.split('.')[1])
- if OSVersion < 9:
- sys.exit("\nOnly OS X 10.9 and above can run this script\n")
def main(argv):
check_root()
- check_os()
edit_authdb()
-if __name__ == '__main__':
+
+if __name__ == "__main__":
main(sys.argv)
diff --git a/Package/preinstall b/Package/preinstall
old mode 100644
new mode 100755
index c0ff348..e25cd03
--- a/Package/preinstall
+++ b/Package/preinstall
@@ -1,64 +1,20 @@
-#!/usr/bin/python
-
-import os
-import shutil
-import sys
-import platform
-
-import syslog
-syslog.openlog("crypt-preinstall")
-
-def fail(message, exit=True):
- syslog.syslog(syslog.LOG_ALERT, message)
- print(message)
- if exit:
- sys.exit(1)
-
-def move_old_plist():
- old_plist = '/private/var/root/recovery_key.plist'
- new_plist = '/private/var/root/crypt_output.plist'
- if os.path.exists('/private/var/root/recovery_key.plist'):
- # We have an old recovery key, move it to the new location
- try:
- shutil.move(old_plist, new_plist)
- except:
- fail('Could not move old plist to new location')
-
-def remove_old_app():
- # remove old installdir
- old_install_dir = '/usr/local/crypt'
- if os.path.exists(old_install_dir):
- shutil.rmtree(old_install_dir)
-
-
-def getOsVersion(only_major_minor=True, as_tuple=False):
- """Returns an OS version.
- Args:
- only_major_minor: Boolean. If True, only include major/minor versions.
- as_tuple: Boolean. If True, return a tuple of ints, otherwise a string.
- """
- os_version_tuple = platform.mac_ver()[0].split('.')
- if only_major_minor:
- os_version_tuple = os_version_tuple[0:2]
- if as_tuple:
- return tuple(map(int, os_version_tuple))
- else:
- return '.'.join(os_version_tuple)
-
-
-def os_check_abort():
- # abort if less than 10.12
- version_tup = getOsVersion(as_tuple=True)
- if version_tup[1] < 12:
- fail('ERROR! Crypt 3.0 does not support macOS versions before 10.12..',
- exit=False)
- fail('ERROR! Please use a previous version of Crypt..')
-
-
-def main():
- os_check_abort()
- move_old_plist()
- print('crypt-preinstall successful...')
-
-if __name__ == '__main__':
- main()
+#!/bin/zsh
+
+OLD_KEY=/private/var/root/recovery_key.plist
+NEW_KEY=/private/var/root/crypt_output.plist
+if [[ -f "$OLD_KEY" ]]; then
+ /bin/mv $OLD_KEY $NEW_KEY
+fi
+
+
+# remove old crypt
+OLD_CRYPT=/usr/local/crypt
+if [[ -d "$OLD_CRYPT" ]]; then
+ /bin/rm -r $OLD_CRYPT
+fi
+
+# remove old foundationplist, thanks for the memories.
+if [[ -f "/Library/Crypt/FoundationPlist.py" ]]; then
+ /bin/rm -r /Library/Crypt/FoundationPlist.py
+ /bin/rm -r /Library/Crypt/FoundationPlist.pyc
+fi
diff --git a/Package/preinstall.old b/Package/preinstall.old
new file mode 100644
index 0000000..c0ff348
--- /dev/null
+++ b/Package/preinstall.old
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+
+import os
+import shutil
+import sys
+import platform
+
+import syslog
+syslog.openlog("crypt-preinstall")
+
+def fail(message, exit=True):
+ syslog.syslog(syslog.LOG_ALERT, message)
+ print(message)
+ if exit:
+ sys.exit(1)
+
+def move_old_plist():
+ old_plist = '/private/var/root/recovery_key.plist'
+ new_plist = '/private/var/root/crypt_output.plist'
+ if os.path.exists('/private/var/root/recovery_key.plist'):
+ # We have an old recovery key, move it to the new location
+ try:
+ shutil.move(old_plist, new_plist)
+ except:
+ fail('Could not move old plist to new location')
+
+def remove_old_app():
+ # remove old installdir
+ old_install_dir = '/usr/local/crypt'
+ if os.path.exists(old_install_dir):
+ shutil.rmtree(old_install_dir)
+
+
+def getOsVersion(only_major_minor=True, as_tuple=False):
+ """Returns an OS version.
+ Args:
+ only_major_minor: Boolean. If True, only include major/minor versions.
+ as_tuple: Boolean. If True, return a tuple of ints, otherwise a string.
+ """
+ os_version_tuple = platform.mac_ver()[0].split('.')
+ if only_major_minor:
+ os_version_tuple = os_version_tuple[0:2]
+ if as_tuple:
+ return tuple(map(int, os_version_tuple))
+ else:
+ return '.'.join(os_version_tuple)
+
+
+def os_check_abort():
+ # abort if less than 10.12
+ version_tup = getOsVersion(as_tuple=True)
+ if version_tup[1] < 12:
+ fail('ERROR! Crypt 3.0 does not support macOS versions before 10.12..',
+ exit=False)
+ fail('ERROR! Please use a previous version of Crypt..')
+
+
+def main():
+ os_check_abort()
+ move_old_plist()
+ print('crypt-preinstall successful...')
+
+if __name__ == '__main__':
+ main()
diff --git a/Package/requirements.txt b/Package/requirements.txt
new file mode 100644
index 0000000..1444339
--- /dev/null
+++ b/Package/requirements.txt
@@ -0,0 +1 @@
+pyobjc==6.2.1