Post not yet marked as solved
Post marked as unsolved with 1 replies, 468 views
I am working in Go code that manages x509 certs on the user's behalf. When I install or renew a cert in the user's login keychain, I want to set an identity preference so Safari will automatically select the cert for my domain.
I am writing CGO to use the Security framework to interact with the keychain. Basic functions such as searching, installing, and deleting work for me. But when I try to call SecIdentitySetPreferred, my application reports could not set identity preference for cert: code: 100013, message: UNIX[Permission denied].
The command-line security tool to set-identity-preference succeeds, and my code currently makes a system call to run that application as a workaround. I would really like to know why I cannot use the framework to set an identity preference.
Here's an example of my code:
// this is a method that searches the keychain and returns a C.SecCertificateRef if it finds an item that matches
certRef, err := k.findCertMatchingKey([]byte(commonName), matchCertSubjectCommonName)
if err != nil {
	 return err
}
if certRef == 0 {
	 return fmt.Errorf("could not find a cert matching subject CN '%s'; cannot set identity preference", commonName)
}
defer C.CFRelease(C.CFTypeRef(certRef))
var idRef C.SecIdentityRef
status := C.SecIdentityCreateWithCertificate((C.CFTypeRef)(k.impl), certRef, &idRef)
if status != C.errSecSuccess {
	 return fmt.Errorf("could not retrieve identity for cert: %s", getErrorMsg(status))
}
defer C.CFRelease(C.CFTypeRef(idRef))
cnStrRef, err := toCFString(commonName)
if err != nil {
	 return err
}
status = C.SecIdentitySetPreferred(idRef, cnStrRef, 0)
if status != C.errSecSuccess {
	 return fmt.Errorf("could not set identity preference for cert: %s", getErrorMsg(status))
}