mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-11-07 01:12:57 -05:00
Fix repeating Touch ID prompt on MacOS
Also adds the APPLE_TEAM_ID and APPLE_APP_IDENTIFIER variables to CMake for using the keychain with a custom provisioning profile.
This commit is contained in:
parent
f15ba49fc6
commit
065c144633
10 changed files with 43 additions and 7 deletions
2
release-tool.py
Executable file → Normal file
2
release-tool.py
Executable file → Normal file
|
|
@ -1010,7 +1010,7 @@ class AppSign(Command):
|
|||
# (Re-)Sign main executable with --entitlements
|
||||
logger.debug('Signing main executable...')
|
||||
_run(['xcrun', 'codesign', f'--sign={identity}', '--force', '--options=runtime',
|
||||
'--entitlements', (src_dir / 'share/macosx/keepassxc.entitlements').as_posix(),
|
||||
'--entitlements', (src_dir / 'build/src/keepassxc.entitlements').as_posix(),
|
||||
(app_dir_app / 'Contents/MacOS/KeePassXC').as_posix()], cwd=None)
|
||||
|
||||
tmp_out = out_file.with_suffix(f'.{"".join(random.choices(string.ascii_letters, k=8))}{file.suffix}')
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
<key>CFBundleIconFile</key>
|
||||
<string>keepassxc.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.keepassxc.keepassxc</string>
|
||||
<string>${APPLE_APP_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.application-identifier</key>
|
||||
<string>G2S7P7J672.org.keepassxc.keepassxc</string>
|
||||
<string>${APPLE_TEAM_ID}.${APPLE_APP_IDENTIFIER}</string>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>G2S7P7J672.org.keepassxc.keepassxc</string>
|
||||
<string>${APPLE_TEAM_ID}.${APPLE_APP_IDENTIFIER}</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -442,12 +442,16 @@ set_target_properties(${PROGNAME} PROPERTIES ENABLE_EXPORTS ON)
|
|||
|
||||
# macOS App Bundle
|
||||
if(APPLE AND WITH_APP_BUNDLE)
|
||||
set(APPLE_TEAM_ID "G2S7P7J672" CACHE STRING "Apple Developer Team ID")
|
||||
set(APPLE_APP_IDENTIFIER "org.keepassxc.keepassxc" CACHE STRING "App Bundle Identifier")
|
||||
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/share/macosx/embedded.provisionprofile DESTINATION ${BUNDLE_INSTALL_DIR})
|
||||
configure_file(${CMAKE_SOURCE_DIR}/share/macosx/Info.plist.cmake ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/share/macosx/keepassxc.entitlements.cmake ${CMAKE_CURRENT_BINARY_DIR}/keepassxc.entitlements)
|
||||
set_target_properties(${PROGNAME} PROPERTIES
|
||||
MACOSX_BUNDLE ON
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist
|
||||
CPACK_BUNDLE_APPLE_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/share/macosx/keepassxc.entitlements")
|
||||
CPACK_BUNDLE_APPLE_ENTITLEMENTS "${CMAKE_CURRENT_BINARY_DIR}/keepassxc.entitlements")
|
||||
|
||||
if(QT_MAC_USE_COCOA AND EXISTS "${QT_LIBRARY_DIR}/Resources/qt_menu.nib")
|
||||
install(DIRECTORY "${QT_LIBRARY_DIR}/Resources/qt_menu.nib"
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ public:
|
|||
*/
|
||||
virtual bool saveSecret(const QString& key, const QByteArray& secretData) const = 0;
|
||||
virtual bool getSecret(const QString& key, QByteArray& secretData) const = 0;
|
||||
virtual bool hasSecret(const QString& key) const = 0;
|
||||
virtual bool removeSecret(const QString& key) const = 0;
|
||||
virtual bool removeAllSecrets() const = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -445,6 +445,7 @@ bool MacUtils::saveSecret(const QString& key, const QByteArray& secretData) cons
|
|||
CFDictionarySetValue(attributes, kSecAttrAccount, static_cast<CFStringRef>(keyName.toNSString()));
|
||||
CFDictionarySetValue(attributes, kSecValueData, keyValueData);
|
||||
CFDictionarySetValue(attributes, kSecAttrSynchronizable, kCFBooleanFalse);
|
||||
CFDictionarySetValue(attributes, kSecUseDataProtectionKeychain, kCFBooleanTrue);
|
||||
CFDictionarySetValue(attributes, kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow);
|
||||
// First, attempt with TouchID enabled
|
||||
CFDictionarySetValue(attributes, kSecAttrAccessControl, createAccessControl(true));
|
||||
|
|
@ -466,6 +467,28 @@ bool MacUtils::saveSecret(const QString& key, const QByteArray& secretData) cons
|
|||
return status == errSecSuccess;
|
||||
}
|
||||
|
||||
bool MacUtils::hasSecret(const QString& key) const
|
||||
{
|
||||
const auto keyName = s_touchIdKeyPrefix + key;
|
||||
|
||||
auto query = CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword);
|
||||
CFDictionarySetValue(query, kSecAttrAccount, static_cast<CFStringRef>(keyName.toNSString()));
|
||||
CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
|
||||
CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue);
|
||||
CFDictionarySetValue(query, kSecUseAuthenticationUI, kSecUseAuthenticationUIFail);
|
||||
|
||||
CFTypeRef result = NULL;
|
||||
OSStatus status = SecItemCopyMatching(query, &result);
|
||||
|
||||
if (result) {
|
||||
CFRelease(result);
|
||||
}
|
||||
CFRelease(query);
|
||||
|
||||
return status == errSecInteractionNotAllowed;
|
||||
}
|
||||
|
||||
bool MacUtils::getSecret(const QString& key, QByteArray& secretData) const
|
||||
{
|
||||
const auto keyName = s_touchIdKeyPrefix + key;
|
||||
|
|
@ -503,6 +526,7 @@ bool MacUtils::removeSecret(const QString& key) const
|
|||
CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword);
|
||||
CFDictionarySetValue(query, kSecAttrAccount, static_cast<CFStringRef>(keyName.toNSString()));
|
||||
CFDictionarySetValue(query, kSecReturnData, kCFBooleanFalse);
|
||||
CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue);
|
||||
// TODO: Log failure to delete?
|
||||
SecItemDelete(query);
|
||||
CFRelease(query);
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ public:
|
|||
// Key management API (TouchID)
|
||||
bool saveSecret(const QString& key, const QByteArray& secretData) const override;
|
||||
bool getSecret(const QString& key, QByteArray& secretData) const override;
|
||||
bool hasSecret(const QString& key) const override;
|
||||
bool removeSecret(const QString& key) const override;
|
||||
bool removeAllSecrets() const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -403,6 +403,12 @@ bool WinUtils::getSecret(const QString& key, QByteArray& secretData) const
|
|||
return !secretData.isEmpty();
|
||||
}
|
||||
|
||||
bool WinUtils::hasSecret(const QString& key) const
|
||||
{
|
||||
QByteArray tmp;
|
||||
return osUtils->getSecret(dbUuid.toString(), tmp);
|
||||
}
|
||||
|
||||
bool WinUtils::removeSecret(const QString& key) const
|
||||
{
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ public:
|
|||
|
||||
bool saveSecret(const QString& key, const QByteArray& secretData) const override;
|
||||
bool getSecret(const QString& key, QByteArray& secretData) const override;
|
||||
bool hasSecret(const QString& key) const override;
|
||||
bool removeSecret(const QString& key) const override;
|
||||
bool removeAllSecrets() const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,8 +50,7 @@ bool TouchID::getKey(const QUuid& dbUuid, QByteArray& key)
|
|||
|
||||
bool TouchID::hasKey(const QUuid& dbUuid) const
|
||||
{
|
||||
QByteArray tmp;
|
||||
return osUtils->getSecret(dbUuid.toString(), tmp);
|
||||
return osUtils->hasSecret(dbUuid.toString());
|
||||
}
|
||||
|
||||
bool TouchID::isAvailable() const
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue