diff --git a/pom.xml b/pom.xml
index a092906..34872fa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,8 +38,8 @@
5.11.0
- 9.1.0
- 1.6.13
+ 9.2.0
+ 1.6.14
@@ -116,7 +116,7 @@
org.apache.maven.plugins
maven-enforcer-plugin
- 3.4.1
+ 3.5.0
check-preconditions
@@ -145,7 +145,7 @@
org.codehaus.mojo
exec-maven-plugin
- 3.2.0
+ 3.3.0
@@ -203,7 +203,7 @@
maven-source-plugin
- 3.3.0
+ 3.3.1
attach-sources
@@ -215,7 +215,7 @@
maven-javadoc-plugin
- 3.6.3
+ 3.7.0
attach-javadocs
@@ -307,7 +307,7 @@
maven-gpg-plugin
- 3.2.2
+ 3.2.4
sign-artifacts
@@ -368,7 +368,7 @@
org.apache.maven.plugins
maven-deploy-plugin
- 3.1.1
+ 3.1.2
diff --git a/src/main/native/org_cryptomator_macos_keychain_MacKeychain_Native.m b/src/main/native/org_cryptomator_macos_keychain_MacKeychain_Native.m
index e04bb0a..5309050 100644
--- a/src/main/native/org_cryptomator_macos_keychain_MacKeychain_Native.m
+++ b/src/main/native/org_cryptomator_macos_keychain_MacKeychain_Native.m
@@ -7,117 +7,103 @@
//
#import "org_cryptomator_macos_keychain_MacKeychain_Native.h"
+#import
#import
JNIEXPORT jint JNICALL Java_org_cryptomator_macos_keychain_MacKeychain_00024Native_storePassword(JNIEnv *env, jobject thisObj, jbyteArray service, jbyteArray key, jbyteArray password) {
- const int serviceLen = (*env)->GetArrayLength(env, service);
jbyte *serviceStr = (*env)->GetByteArrayElements(env, service, NULL);
- const int keyLen = (*env)->GetArrayLength(env, key);
jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL);
- const int pwLen = (*env)->GetArrayLength(env, password);
jbyte *pwStr = (*env)->GetByteArrayElements(env, password, NULL);
+ jsize length = (*env)->GetArrayLength(env, password);
// find existing:
- SecKeychainItemRef itemRef = NULL;
- OSStatus status = SecKeychainFindGenericPassword(
- NULL, // default keychain
- serviceLen, // length of service name
- (char *)serviceStr, // service name
- keyLen, // length of account name
- (char *)keyStr, // account name
- NULL, // length of password
- NULL, // pointer to password data
- &itemRef // the item reference
- );
- if (status == errSecSuccess) {
+ NSDictionary *query = @{
+ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrService: [NSString stringWithCString:(char *)serviceStr encoding:NSUTF8StringEncoding],
+ (__bridge id)kSecAttrAccount: [NSString stringWithCString:(char *)keyStr encoding:NSUTF8StringEncoding],
+ (__bridge id)kSecReturnAttributes: @YES,
+ (__bridge id)kSecReturnData: @YES,
+ (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne
+ };
+ CFDictionaryRef result = NULL;
+ OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
+ if (status == errSecSuccess && result != NULL) {
// update existing:
- status = SecKeychainItemModifyAttributesAndData(
- itemRef, // the item reference
- NULL, // no change to attributes
- pwLen, // length of password
- pwStr // pointer to password data
- );
+ NSDictionary *attributesToUpdate = @{
+ (__bridge id)kSecValueData: [NSData dataWithBytes:pwStr length:length]
+ };
+ status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributesToUpdate);
} else if (status == errSecItemNotFound) {
// add new:
- status = SecKeychainAddGenericPassword(
- NULL, // default keychain
- serviceLen, // length of service name
- (char *)serviceStr, // service name
- keyLen, // length of account name
- (char *)keyStr, // account name
- pwLen, // length of password
- pwStr, // pointer to password data
- NULL // the item reference
- );
+ NSDictionary *attributes = @{
+ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrService: [NSString stringWithCString:(char *)serviceStr encoding:NSUTF8StringEncoding],
+ (__bridge id)kSecAttrAccount: [NSString stringWithCString:(char *)keyStr encoding:NSUTF8StringEncoding],
+ (__bridge id)kSecValueData: [NSData dataWithBytes:pwStr length:length]
+ };
+ status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);
+ } else {
+ NSLog(@"Error storing item in keychain. Status code: %d", (int)status);
}
+ (*env)->ReleaseByteArrayElements(env, service, serviceStr, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, key, keyStr, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, password, pwStr, JNI_ABORT);
- if (itemRef) {
- CFRelease(itemRef);
- }
return status;
}
JNIEXPORT jbyteArray JNICALL Java_org_cryptomator_macos_keychain_MacKeychain_00024Native_loadPassword(JNIEnv *env, jobject thisObj, jbyteArray service, jbyteArray key) {
- const int serviceLen = (*env)->GetArrayLength(env, service);
jbyte *serviceStr = (*env)->GetByteArrayElements(env, service, NULL);
- const int keyLen = (*env)->GetArrayLength(env, key);
jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL);
- void *pwStr = NULL;
- UInt32 pwLen;
- OSStatus status = SecKeychainFindGenericPassword(
- NULL, // default keychain
- serviceLen, // length of service name
- (char *)serviceStr, // service name
- keyLen, // length of account name
- (char *)keyStr, // account name
- &pwLen, // length of password
- &pwStr, // pointer to password data
- NULL // the item reference
- );
- jbyteArray result;
- if (status == errSecSuccess) {
- result = (*env)->NewByteArray(env, pwLen);
- (*env)->SetByteArrayRegion(env, result, 0, pwLen, pwStr);
- } else {
- result = NULL;
+ // find existing:
+ NSDictionary *query = @{
+ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrService: [NSString stringWithCString:(char *)serviceStr encoding:NSUTF8StringEncoding],
+ (__bridge id)kSecAttrAccount: [NSString stringWithCString:(char *)keyStr encoding:NSUTF8StringEncoding],
+ (__bridge id)kSecReturnAttributes: @YES,
+ (__bridge id)kSecReturnData: @YES,
+ (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne
+ };
+ CFDictionaryRef result = NULL;
+ OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
+ jbyteArray password = NULL;
+ if (status == errSecSuccess && result != NULL) {
+ // retrieve password:
+ NSDictionary *attributes = (__bridge_transfer NSDictionary *)result;
+ NSData *passwordData = attributes[(__bridge id)kSecValueData];
+ password = (*env)->NewByteArray(env, (int)passwordData.length);
+ (*env)->SetByteArrayRegion(env, password, 0, (int)passwordData.length, (jbyte *)passwordData.bytes);
+ } else if (status != errSecItemNotFound) {
+ NSLog(@"Error retrieving item from keychain. Status code: %d", (int)status);
}
+ (*env)->ReleaseByteArrayElements(env, service, serviceStr, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, key, keyStr, JNI_ABORT);
- if (pwStr) {
- SecKeychainItemFreeContent(NULL, pwStr);
- }
- return result;
+ return password;
}
JNIEXPORT jint JNICALL Java_org_cryptomator_macos_keychain_MacKeychain_00024Native_deletePassword(JNIEnv *env, jobject thisObj, jbyteArray service, jbyteArray key) {
- const int serviceLen = (*env)->GetArrayLength(env, service);
jbyte *serviceStr = (*env)->GetByteArrayElements(env, service, NULL);
- const int keyLen = (*env)->GetArrayLength(env, key);
jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL);
- SecKeychainItemRef itemRef = NULL;
- OSStatus status = SecKeychainFindGenericPassword(
- NULL, // default keychain
- serviceLen, // length of service name
- (char *)serviceStr, // service name
- keyLen, // length of account name
- (char *)keyStr, // account name
- NULL, // length of password
- NULL, // pointer to password data
- &itemRef // the item reference
- );
- if (status == errSecSuccess) {
- status = SecKeychainItemDelete(
- itemRef // the item reference
- );
+ // find existing:
+ NSDictionary *query = @{
+ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrService: [NSString stringWithCString:(char *)serviceStr encoding:NSUTF8StringEncoding],
+ (__bridge id)kSecAttrAccount: [NSString stringWithCString:(char *)keyStr encoding:NSUTF8StringEncoding],
+ (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne
+ };
+ CFDictionaryRef result = NULL;
+ OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
+ if (status == errSecSuccess && result != NULL) {
+ // delete:
+ status = SecItemDelete((__bridge CFDictionaryRef)query);
+ } else if (status != errSecItemNotFound) {
+ NSLog(@"Error deleting item from keychain. Status code: %d", (int)status);
}
+ (*env)->ReleaseByteArrayElements(env, service, serviceStr, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, key, keyStr, JNI_ABORT);
- if (itemRef) {
- CFRelease(itemRef);
- }
return status;
}