From: tenzap Date: Wed, 13 Nov 2022 09:38:48 +0100 Subject: [PATCH] Fix build failure on macos versions < 10.11 This patch will permit to fix build issues on macos versions < 10.11 Strategy is to check at configure time which functions are available. Those that are not available, are hidden by preprocessor checks Upstream doesn't want to merge patches to build on versions prior to macos 10.13, so this patch is not forwarded upstream. See: https://github.com/keepassxreboot/keepassxc/pull/8650#issuecomment-1291750066 --- CMakeLists.txt +++ CMakeLists.txt @@ -81,6 +81,42 @@ if(APPLE) ${CMAKE_CURRENT_BINARY_DIR}/tiometry_test/ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compiler-checks/macos/control_watch_support.mm) message(STATUS "Apple watch compiler support: ${XC_APPLE_COMPILER_SUPPORT_WATCH}") + + try_compile(XC_APPLE_COMPILER_SUPPORT_errSecUserCanceled + ${CMAKE_CURRENT_BINARY_DIR}/errSecUserCanceled_test/ + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compiler-checks/macos/control_errSecUserCanceled_support.mm) + message(STATUS "errSecUserCanceled compiler support: ${XC_APPLE_COMPILER_SUPPORT_errSecUserCanceled}") + + try_compile(XC_APPLE_COMPILER_SUPPORT_LocalAuthentication + ${CMAKE_CURRENT_BINARY_DIR}/LocalAuthentication_test/ + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compiler-checks/macos/control_LocalAuthentication_support.mm) + message(STATUS "LocalAuthentication compiler support: ${XC_APPLE_COMPILER_SUPPORT_LocalAuthentication}") + + try_compile(XC_APPLE_COMPILER_SUPPORT_kSecAttrSynchronizable + ${CMAKE_CURRENT_BINARY_DIR}/kSecAttrSynchronizable_test/ + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compiler-checks/macos/control_kSecAttrSynchronizable_support.mm) + message(STATUS "kSecAttrSynchronizable compiler support: ${XC_APPLE_COMPILER_SUPPORT_kSecAttrSynchronizable}") + + try_compile(XC_APPLE_COMPILER_SUPPORT_kSecUseAuthenticationUI + ${CMAKE_CURRENT_BINARY_DIR}/kSecUseAuthenticationUI_test/ + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compiler-checks/macos/control_kSecUseAuthenticationUI_support.mm) + message(STATUS "kSecUseAuthenticationUI compiler support: ${XC_APPLE_COMPILER_SUPPORT_kSecUseAuthenticationUI}") + + try_compile(XC_APPLE_COMPILER_SUPPORT_kSecAttrAccessControl + ${CMAKE_CURRENT_BINARY_DIR}/kSecAttrAccessControl_test/ + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compiler-checks/macos/control_kSecAttrAccessControl_support.mm) + message(STATUS "kSecAttrAccessControl compiler support: ${XC_APPLE_COMPILER_SUPPORT_kSecAttrAccessControl}") + + try_compile(XC_APPLE_COMPILER_SUPPORT_kSecUseOperationPrompt + ${CMAKE_CURRENT_BINARY_DIR}/kSecUseOperationPrompt_test/ + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compiler-checks/macos/control_kSecUseOperationPrompt_support.mm) + message(STATUS "kSecUseOperationPrompt compiler support: ${XC_APPLE_COMPILER_SUPPORT_kSecUseOperationPrompt}") + + try_compile(XC_APPLE_COMPILER_SUPPORT_SecAccessControlRef + ${CMAKE_CURRENT_BINARY_DIR}/SecAccessControlRef_test/ + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compiler-checks/macos/control_SecAccessControlRef_support.mm) + message(STATUS "SecAccessControlRef compiler support: ${XC_APPLE_COMPILER_SUPPORT_SecAccessControlRef}") + endif() if(WITH_CCACHE) --- /dev/null +++ cmake/compiler-checks/macos/control_LocalAuthentication_support.mm @@ -0,0 +1,2 @@ +#include +int main() { return 0; } --- /dev/null +++ cmake/compiler-checks/macos/control_SecAccessControlRef_support.mm @@ -0,0 +1,6 @@ +#include + +int main() { + SecAccessControlRef; + return 0; +} --- /dev/null +++ cmake/compiler-checks/macos/control_errSecUserCanceled_support.mm @@ -0,0 +1,6 @@ +#include + +int main() { + errSecUserCanceled; + return 0; +} --- /dev/null +++ cmake/compiler-checks/macos/control_kSecAttrAccessControl_support.mm @@ -0,0 +1,6 @@ +#include + +int main() { + kSecAttrAccessControl; + return 0; +} --- /dev/null +++ cmake/compiler-checks/macos/control_kSecAttrSynchronizable_support.mm @@ -0,0 +1,6 @@ +#include + +int main() { + kSecAttrSynchronizable; + return 0; +} --- /dev/null +++ cmake/compiler-checks/macos/control_kSecUseAuthenticationUI_support.mm @@ -0,0 +1,6 @@ +#include + +int main() { + kSecUseAuthenticationUI; + return 0; +} --- /dev/null +++ cmake/compiler-checks/macos/control_kSecUseOperationPrompt_support.mm @@ -0,0 +1,6 @@ +#include + +int main() { + kSecUseOperationPrompt; + return 0; +} --- src/config-keepassx.h.cmake +++ src/config-keepassx.h.cmake @@ -41,10 +41,24 @@ #cmakedefine01 XC_APPLE_COMPILER_SUPPORT_BIOMETRY() #cmakedefine01 XC_APPLE_COMPILER_SUPPORT_TOUCH_ID() #cmakedefine01 XC_APPLE_COMPILER_SUPPORT_WATCH() +#cmakedefine01 XC_APPLE_COMPILER_SUPPORT_errSecUserCanceled() +#cmakedefine01 XC_APPLE_COMPILER_SUPPORT_LocalAuthentication() +#cmakedefine01 XC_APPLE_COMPILER_SUPPORT_kSecAttrSynchronizable() +#cmakedefine01 XC_APPLE_COMPILER_SUPPORT_kSecUseAuthenticationUI() +#cmakedefine01 XC_APPLE_COMPILER_SUPPORT_kSecAttrAccessControl() +#cmakedefine01 XC_APPLE_COMPILER_SUPPORT_kSecUseOperationPrompt() +#cmakedefine01 XC_APPLE_COMPILER_SUPPORT_SecAccessControlRef() #define XC_COMPILER_SUPPORT(X) XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_##X() #define XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_APPLE_BIOMETRY() XC_APPLE_COMPILER_SUPPORT_BIOMETRY() #define XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_TOUCH_ID() XC_APPLE_COMPILER_SUPPORT_TOUCH_ID() #define XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_WATCH_UNLOCK() XC_APPLE_COMPILER_SUPPORT_WATCH() +#define XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_errSecUserCanceled() XC_APPLE_COMPILER_SUPPORT_errSecUserCanceled() +#define XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_LocalAuthentication() XC_APPLE_COMPILER_SUPPORT_LocalAuthentication() +#define XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_kSecAttrSynchronizable() XC_APPLE_COMPILER_SUPPORT_kSecAttrSynchronizable() +#define XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_kSecUseAuthenticationUI() XC_APPLE_COMPILER_SUPPORT_kSecUseAuthenticationUI() +#define XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_kSecAttrAccessControl() XC_APPLE_COMPILER_SUPPORT_kSecAttrAccessControl() +#define XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_kSecUseOperationPrompt() XC_APPLE_COMPILER_SUPPORT_kSecUseOperationPrompt() +#define XC_COMPILER_SUPPORT_PRIVATE_DEFINITION_SecAccessControlRef() XC_APPLE_COMPILER_SUPPORT_SecAccessControlRef() #endif // KEEPASSX_CONFIG_KEEPASSX_H --- src/touchid/TouchID.mm +++ src/touchid/TouchID.mm @@ -9,7 +9,9 @@ #include #include +#if XC_COMPILER_SUPPORT(LocalAuthentication) #include +#endif #include #include @@ -131,7 +133,9 @@ bool TouchID::storeKey(const QString& databasePath, const QByteArray& passwordKe // We need both runtime and compile time checks here to solve the following problems: // - Not all flags are available in all OS versions, so we have to check it at compile time // - Requesting Biometry/TouchID when to fingerprint sensor is available will result in runtime error +#if XC_COMPILER_SUPPORT(SecAccessControlRef) SecAccessControlCreateFlags accessControlFlags = 0; +#endif if (isTouchIdAvailable()) { #if XC_COMPILER_SUPPORT(APPLE_BIOMETRY) // Prefer the non-deprecated flag when available @@ -147,6 +151,7 @@ bool TouchID::storeKey(const QString& databasePath, const QByteArray& passwordKe #endif } +#if XC_COMPILER_SUPPORT(SecAccessControlRef) SecAccessControlRef sacObject = SecAccessControlCreateWithFlags( kCFAllocatorDefault, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, accessControlFlags, &error); @@ -155,6 +160,7 @@ bool TouchID::storeKey(const QString& databasePath, const QByteArray& passwordKe debug("TouchID::storeKey - Error creating security flags: %s", e.localizedDescription.UTF8String); return false; } +#endif NSString *accountName = keyName.toNSString(); // The NSString is released by Qt @@ -168,15 +174,23 @@ bool TouchID::storeKey(const QString& databasePath, const QByteArray& passwordKe CFDictionarySetValue(attributes, kSecClass, kSecClassGenericPassword); CFDictionarySetValue(attributes, kSecAttrAccount, (__bridge CFStringRef) accountName); CFDictionarySetValue(attributes, kSecValueData, (__bridge CFDataRef) keychainValueData); +#if XC_COMPILER_SUPPORT(kSecAttrSynchronizable) CFDictionarySetValue(attributes, kSecAttrSynchronizable, kCFBooleanFalse); +#endif +#if XC_COMPILER_SUPPORT(kSecUseAuthenticationUI) CFDictionarySetValue(attributes, kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow); +#endif +#if XC_COMPILER_SUPPORT(kSecAttrAccessControl) && XC_COMPILER_SUPPORT(SecAccessControlRef) CFDictionarySetValue(attributes, kSecAttrAccessControl, sacObject); +#endif // add to KeyChain OSStatus status = SecItemAdd(attributes, NULL); LogStatusError("TouchID::storeKey - Status adding new entry", status); +#if XC_COMPILER_SUPPORT(SecAccessControlRef) CFRelease(sacObject); +#endif CFRelease(attributes); if (status != errSecSuccess) { @@ -222,18 +236,23 @@ bool TouchID::getKey(const QString& databasePath, QByteArray& passwordKey) const CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword); CFDictionarySetValue(query, kSecAttrAccount, (__bridge CFStringRef) accountName); CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue); +#if XC_COMPILER_SUPPORT(kSecUseOperationPrompt) CFDictionarySetValue(query, kSecUseOperationPrompt, (__bridge CFStringRef) touchPromptMessage); +#endif // get data from the KeyChain CFTypeRef dataTypeRef = NULL; OSStatus status = SecItemCopyMatching(query, &dataTypeRef); CFRelease(query); +#if XC_COMPILER_SUPPORT(errSecUserCanceled) if (status == errSecUserCanceled) { // user canceled the authentication, return true with empty key debug("TouchID::getKey - User canceled authentication"); return true; - } else if (status != errSecSuccess || dataTypeRef == NULL) { + } else +#endif + if (status != errSecSuccess || dataTypeRef == NULL) { LogStatusError("TouchID::getKey - key query error", status); return false; } --- src/CMakeLists.txt +++ src/CMakeLists.txt @@ -354,7 +354,10 @@ if(WITH_XC_KEESHARE) endif() if(APPLE) - target_link_libraries(keepassx_core "-framework Foundation -framework AppKit -framework Carbon -framework Security -framework LocalAuthentication") + target_link_libraries(keepassx_core "-framework Foundation -framework AppKit -framework Carbon -framework Security") + if(XC_APPLE_COMPILER_SUPPORT_LocalAuthentication) + target_link_libraries(keepassx_core "-framework LocalAuthentication") + endif() if(Qt5MacExtras_FOUND) target_link_libraries(keepassx_core Qt5::MacExtras) endif()