"kinit: Preauthentication failed while getting initial credentials" when using Active Directory or FreeIPA
addent -password -p <username> -k 0 -e aes256-cts
write_kt <username>.keytab
When the keytab is created, a "salt" is used to encrypt the contents of the keytab. The ktutil command always assume that the salt is the Kerberos realm concatenated with the short username, which is the MIT Kerberos default. For example, in the principal name "alice@EXAMPLE.COM", the short name is "alice", the realm is "EXAMPLE.COM" and the salt that ktutil uses to create the keytab is "EXAMPLE.COMalice".
The cause of the aforementioned error is that ActiveDirectory and FreeIPA use a different salt than what ktutil uses, which causes the Kerberos authentication to fail.
The salt used by Active Directory is also the realm name concatenated with the short name. However, Active Directory derives the short name from the user's "userPrincipalAttribute" attribute, which can cause it to differ from the login name. For example, an Active Directory user might have the login "alice" and a userPrincipalName attribute equals to "Alice@example.com". The login name differs from the user short name ("Alice") because the case of the initial "A" is different. In this example, the correct salt for user "alice" would've been "EXAMPLE.COMAlice", assuming the realm is "EXAMPLE.COM". If we use a ktutil-created keytab with the salt "EXAMPLE.COMalice", the authentication will fail.
In Active Directory it's also common to see compound short names in the userPrincipalName attribute, like "Alice.Smith@example.com", which will cause the same issue. It's also common to see variations on this convention from user to user. Some users might have the userPrincipalName to match their login, while others will have discrepancies between them. In these cases, the keytabs will work for some users but not for others.
The salt used by FreeIPA is a random sequence of bytes, which will lead to the same problem. Because of this, the problem is consistent across all users when using FreeIPA.
The correct salt used by the KDC can be found by enabling trace for the kinit command, as shown below:
KRB5_TRACE=/dev/stdout kinit -kt <user>.keytab <user>
The output of the trace will include a line like the one below with the expected salt:
[10824] 1638936111.249485: Selected etype info: etype aes256-cts, salt "*yQ7Ctv8B-FD=+w(", params ""
Newer versions of ktutil (1.16 and above, found natively on Centos 8 ) allow for the salt to be specified when creating the keytab. Unfortunately, though, the version of ktutil in Centos 7 is still 1.15 and lack that feature. If you have access to a newer version of ktutil you can use the following command to specify the correct salt:
addent -password -p <user>@<realm> -k 0 -e aes256-cts -s "<salt>"
write_kt <user>.keytab
To help me create keytabs correctly regardless of the environment, I created this Python script that generates keytabs without resorting to ktutil. It first tries creating the keytab with the default salt. After the keytab is created, it validates it using the kinit command. If the validation fails, it retrieves the correct salt from the kinit output and regenerates the keytab with it.
It has been tested with MIT KDC, Active Directory and FreeIPA and they all worked nicely (when running on Centos; it does not work on MacOS).
Workaround for Active Directory: The encryption type RC4-HMAC does not use salt for encryption. If this encryption type is enabled in the Active Directory KDC, one alternative that works is to create the keytab with this encryption type instead of AES.

