macOS API ccache, kinit for multiple principals gives internal credentials cache error
A. Karl Kornel
karl at kornel.us
Tue Feb 18 16:39:43 EST 2025
On 2025-02-17 06:36 PM, Ken Hornstein wrote:
> <<<snip>>>
>
> First, do you have a default_realm set in /etc/krb5.conf ? Maybe that
> would fix it, and that would explain why it works for me.
I did not actually have a krb5.conf installed on my computer. Stanford
has the necessary SRV records in DNS for domain-to-realm lookup, KDC
lookup, etc.. Plus, my normal workflow involves using bash aliases to
do `kinit`, and those `kinit` commands include the realm name. So, I've
never been hurt (until now?) by not having a default realm set.
Plus, I didn't know that later macOS even supported putting something at
path /etc/krb5.conf! I thought that pretty much everything under / was
locked down now.
Stanford's canonical krb5.conf is at
https://web.stanford.edu/dept/its/support/kerberos/dist/krb5.conf -- I
just downloaded it, and was able to install it to /etc/krb5.conf.
With the krb5.conf installed, I repeated my original test. Here are the
results:
* MacPorts MIT Kerberos `kdestroy -A`
* MacPorts MIT Kerberos `kinit -F akkornel at stanford.edu` -- works
* MacPorts MIT Kerberos `kinit -F akkornel/root at stanford.edu` -- works!
* MacPorts MIT Kerberos `klist -l` -- lists two credential caches!
To confirm your hypothesis, I edited the downloaded /etc/krb5.conf,
removing the default_realm entry. I then re-ran the tests with MIT
Kerberos:
* MacPorts MIT Kerberos `kdestroy -A`
* MacPorts MIT Kerberos `kinit -F akkornel at stanford.edu` -- works
* MacPorts MIT Kerberos `kinit -F akkornel/root at stanford.edu` -- fails
* MacPorts MIT Kerberos `klist -l` -- lists a single credentials cache,
for akkornel at stanford.edu
And I then did the same tests with the MIT Kerberos that I built:
* `~/bin/krb5/bin/kdestroy -A`
* `~/bin/krb5/bin/kinit -F akkornel at stanford.edu` -- works
* `~/bin/krb5/bin/kinit -F akkornel/root at stanford.edu` -- fails
* `~/bin/krb5/bin/klist -l` -- lists a single credentials cache, for
akkornel at stanford.edu
So, I think your hypothesis is confirmed:
If you already have a credentials cache (created against one principal),
and you use `kinit` with a different principal, and you do not have a
default realm set, then `kinit` will fail with an "Internal credentials
cache error while generating new ccache" error.
Still, I would like to get confirmation by looking at the syslog. And
it's been a heck of a time trying to figure out how to enable logging.
> It looks like this is in the MITKerberosShim package, specifically
> ccache.c. And it looks like it calls the macro LOG_FAILURE(), which
> calls the function mshim_failure(), in misc.c. It looks like THAT
> might
> turn on logging if you create the preference file
>
> /Library/Preferences/com.apple.MITKerberosShim
In init_log(), it looks like CopyKeyFromFile() is defined up in misc.c,
starting at line 60. It ends up looking for the file at path
"/Library/Preferences/com.apple.MITKerberosShim.plist". So, I used
these two commands to create the plist and populate it:
sudo plutil -create xml1
/Library/Preferences/com.apple.MITKerberosShim.plist
sudo plutil -insert EnableDebugging -bool True
/Library/Preferences/com.apple.MITKerberosShim.plist
Even so, when I check in the Console app, I do not see anything being
logged. I do see that mshim_failure() calls init_log(), and it seems to
have a mechanism to ensure that log init is only performed once. Maybe
I need to reboot?
I do have an OS update to do, so I'll leave the plist file created, and
see if I start getting debug logs after a reboot.
> In api_macos_gen_new(), we call cc_context_create_new_ccache() with:
>
> err = cc_context_create_new_ccache(cc_context, cc_credentials_v5,
> "",
> &cc_ccache);
>
> The third argument is supposed to be the principal name, and I thought
> "" was valid, but maybe technically it isn't, especially if you don't
> have a principal name defined?
I had a look through https://github.com/apple-oss-distributions/Heimdal,
looking for calls to `create_new_ccache`. I found create_new_ccache was
called at three places:
* In acc_get_name(): The code calls _krb5_get_default_principal_local(),
uses the resulting principal to call krb5_unparse_name(), and then uses
the resulting name in create_new_ccache().
* In acc_initialize(): A principal is provided as a function parameter,
which is passed to krb5_unparse_name(), and the resulting name is sent
to create_new_ccache().
* In acc_move(): The call is only used if the destination cache does not
exist. get_principal() is called with the source cache, and the
resulting name is sent to create_new_ccache().
So, at least in Heimdal, all of the call sites for create_new_ccache do
provide a principal name.
I wonder, maybe there's an alternate path for creating a credentials
cache?
~ Karl
More information about the Kerberos
mailing list