Mac Launch Daemon was unable to get the password from the system keychain after saving it there

We have Launch Daemon, which (necessarily, for various reasons) works as root and which communicates with the server component through the network. It must authenticate with the service, so when it first receives the password, we store it in the system keychain. In subsequent launches, the idea is to extract the password from the key fob and use it for authentication using the network service.

This works fine, but on macOS 10.12 the existing code stops working, and we completely stopped on how to fix it. It comes down to the following:

Regardless of whether we save the new password or retrieve the old one, we get a link to the system keychain using this:

SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &system_keychain); 

We have also disabled user interaction for a good measure, although we expect it to already disconnect in the context of the daemon.

 SecKeychainSetUserInteractionAllowed(false); 

When saving a new password in the keychain, we use

 OSStatus status = SecKeychainAddInternetPassword( system_keychain, urlLength, server_base_url, 0, NULL, usernameLength, username, 0, NULL, 0, kSecProtocolTypeAny, kSecAuthenticationTypeAny, passwordLength, password, NULL); 

It works a lot. Success is reported, and I see an element in the "system" keychain in Keychain Access.app.

Retrieving it in subsequent runs of our daemon is performed using this line:

 status = SecKeychainFindInternetPassword( system_keychain, urlLength, url, 0, NULL, usernameLength, username, 0, NULL, 0, kSecProtocolTypeAny, kSecAuthenticationTypeAny, &passwordLength, &password_data, NULL); 

Unfortunately, this began to return errSecAuthFailed for reasons we errSecAuthFailed not understand.

A few additional data that we checked, and all that we tried, to no avail:

  • The daemon daemon file is signed with a developer identifier certificate.
  • The daemon file contains the built-in Info.plist section with the identifier and version of the package.
  • I see the daemon binary in the Always allow access by these applications list on the Access Control tab of the password item in Keychain Access.app.
  • If I manually switch to "Allow all applications access to this item" in Keychain Access, it works. However, this somewhat degrades the password storage point in the keychain.
  • We tried playing with the SecKeychainAddInternetPassword parameters, but that didn't seem to make any difference.
  • We tried to explicitly unlock the keychain using SecKeychainUnlock() , but, as the documentation suggests, this seems redundant.
  • Removing an item in Keychain Access.app causes SecKeychainFindInternetPassword() give errSecItemNotFound , as you would expect. That way, he can definitely find the saved item, he is simply not allowed to read it.

The keychain documentation is not so easy to read, but rather tautological in parts. ("To make Y, you need to make Y," without mentioning why you want to make Y.) However, I think I managed and understood most of this. Various aspects of our specific settings are not considered in detail (access from the daemon), but it seems pretty obvious that access to an element previously stored in the same application does not require special authorization or authentication. This directly contradicts the behavior that we observe.

Any ideas?

+5
source share
1 answer

After spending a few more hours on this for several days, we finally figured out what was going on.

At first I tried to create a minimal example that would reproduce the problem. This did not work with errSecAuthFailed and thus did not reproduce the problem. So, back to the first demons, there must be something special about this, which is not the case.

The next idea was to check the SecKeychainFindInternetPassword() for the duration of the SecKeychainFindInternetPassword() call. This caused some error messages:

 securityd CSSM Exception: -2147411889 CSSMERR_CL_UNKNOWN_TAG securityd MacOS error: -67063 securityd MacOS error: -67063 securityd code requirement check failed (-67063), client is not Apple-signed securityd CSSM Exception: 32 CSSM_ERRCODE_OPERATION_AUTH_DENIED OurDaemon subsystem: com.apple.securityd, category: security_exception, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 2, enable_private_data: 0 OurDaemon CSSM Exception: -2147416032 CSSMERR_CSP_OPERATION_AUTH_DENIED 

This suggests that the problem may be with code signing. It’s strange. Verifying the code signature of the binary with codesign -vv did not cause problems.

After searching the Internet for the various parts of the error messages, I found -67063 matches errSecCSGuestInvalid . The comment says: "The code ID was invalidated."

Well, definitely some kind of code assignment error, but what does this mean and why did this happen?

Hunting around a bit more, finally an explanation appeared, as well as a solution: http://lists.apple.com/archives/apple-cdsa/2010/Mar/msg00027.html

This means that at some point from the moment the program was launched, something happened to this, which made it invalid.

and

if you run the signed program, then replace it (for example, by creating a new version in place :-) and then starting the new version, the kernel will still store the old signature attached to the vnode executable. If this is your situation, simply deleting the executable file and re-creating it will clear the problem permanently (until you overwrite the file again :-). We recommend that the signed code is always replaced (mv (1), not cp (1) or equivalents).

This explains this. I copied new versions of the daemon into place using

 sudo cp path/to/built/daemon /usr/local/libexec/ 

Apparently, this overwrites the file in place, rather than creating a new vnode, writing it down, and then renaming it on top of the old file. Therefore, the solution should be either cp in the temp directory, and then mv in place. Or delete the destination file before using cp .

Once I have done that, it will work!

+8
source

Source: https://habr.com/ru/post/1259849/


All Articles