TL;DR: What JNA type do I use for a void**
pointer (that is really a char**
), and how do I access the result from it?
I'm trying to get a password from macOS Keychain in Java using this C function:
OSStatus SecKeychainFindGenericPassword(CFTypeRef keychainOrArray,
UInt32 serviceNameLength,
const char *serviceName,
UInt32 accountNameLength,
const char *accountName,
UInt32 *passwordLength,
void * _Nullable *passwordData,
SecKeychainItemRef _Nullable *itemRef);
The problem is, I'm not sure how to handle the passwordData
parameter. I managed to call it from C (see bottom of post). But, in Java, I'm getting nondeterministic and incorrect results for the passwordData
parameter. Here's my attempt to call it from Java:
import com.sun.jna.*;
import com.sun.jna.ptr.*;
public class JnaTest {
public interface Security extends Library {
int SecKeychainFindGenericPassword(
Object keychainOrArray,
int serviceNameLength,
String serviceName,
int accountNameLength,
String accountName,
IntByReference passwordLength,
// I've also tried char[][] and Pointer, which both give errors
PointerByReference passwordData,
Object itemRef);
}
public static void main(String[] args) {
Security sec = Native.loadLibrary("Security", Security.class);
PointerByReference pass = new PointerByReference();
IntByReference len = new IntByReference();
int rc = sec.SecKeychainFindGenericPassword(
null,
10, "SurfWriter",
10, "MyUserAcct",
len, pass,
null);
System.out.println(rc); // 0, good
System.out.println(len.getValue()); // 11, same as in C
// This prints Unicode characters nondeterministically; buffer overrun?
System.out.println(new String(pass.getValue().getCharArray(0, len.getValue())));
}
}
I was able to write this C program to do the same thing, and it works fine, so the problem is almost definitely with reading passwordData
in JNA:
#include <Security/Security.h>
int main() {
unsigned int len;
void* pass;
int rc = SecKeychainFindGenericPassword(
NULL,
10, "SurfWriter",
10, "MyUserAcct",
&len, &pass,
NULL);
printf("%d %s\n", len, pass);
}