Closed ldapcoder closed 6 months ago
The Invalid Checksum
error means the key used to decrypt the incoming AP-REQ is wrong. Since it's pulling the key from KeyTable table = new KeyTable(File.ReadAllBytes())
that would suggest the keytable either has the wrong key or no key at all (though no key should trigger a different error).
You can test this by ruling out any oddities with KeyTable lookups with something like this:
foreach (var entry in keyTable.Entries)
{
KerberosAuthenticator authenticator = new KerberosAuthenticator(new KerberosValidator(entry.Key));
try
{
var identity = await authenticator.Authenticate(token);
}
catch (Exception ex)
{
// blah
}
}
If it is a key selection issue then I can make that logic a bit smarter based on what you happen to find with the above test.
Thanks for your quick reply. I put in the lines of code you suggested and am getting the following errors now:
System.InvalidOperationException: Key EType DES_CBC_CRC must match the encrypted data EType AES256_CTS_HMAC_SHA1_96
at Kerberos.NET.Entities.KrbEncryptedData.Decrypt[T](KerberosKey key, KeyUsage usage, Func2 func) in D:\a\1\s\Kerberos.NET\Entities\Krb\KrbEncryptedData.cs:line 27 at Kerberos.NET.Crypto.DecryptedKrbApReq.Decrypt(KerberosKey ticketEncryptingKey) in D:\a\1\s\Kerberos.NET\Crypto\DecryptedKrbApReq.cs:line 75 at Kerberos.NET.Entities.ContextToken.DecryptApReq(KrbApReq token, KeyTable keytab) in D:\a\1\s\Kerberos.NET\Entities\SpNego\ContextToken.cs:line 45 at Kerberos.NET.KerberosValidator.<Validate>d__15.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosValidator.cs:line 70 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Kerberos.NET.KerberosAuthenticator.<Authenticate>d__13.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 73 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Kerberos.NET.KerberosAuthenticator.<Authenticate>d__12.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 69 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()
at LdapSession.
System.InvalidOperationException: Key EType DES_CBC_MD5 must match the encrypted data EType AES256_CTS_HMAC_SHA1_96
at Kerberos.NET.Entities.KrbEncryptedData.Decrypt[T](KerberosKey key, KeyUsage usage, Func2 func) in D:\a\1\s\Kerberos.NET\Entities\Krb\KrbEncryptedData.cs:line 27 at Kerberos.NET.Crypto.DecryptedKrbApReq.Decrypt(KerberosKey ticketEncryptingKey) in D:\a\1\s\Kerberos.NET\Crypto\DecryptedKrbApReq.cs:line 75 at Kerberos.NET.Entities.ContextToken.DecryptApReq(KrbApReq token, KeyTable keytab) in D:\a\1\s\Kerberos.NET\Entities\SpNego\ContextToken.cs:line 45 at Kerberos.NET.KerberosValidator.<Validate>d__15.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosValidator.cs:line 70 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Kerberos.NET.KerberosAuthenticator.<Authenticate>d__13.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 73 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Kerberos.NET.KerberosAuthenticator.<Authenticate>d__12.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 69 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()
at LdapSession.
System.InvalidOperationException: Key EType RC4_HMAC_NT must match the encrypted data EType AES256_CTS_HMAC_SHA1_96
at Kerberos.NET.Entities.KrbEncryptedData.Decrypt[T](KerberosKey key, KeyUsage usage, Func2 func) in D:\a\1\s\Kerberos.NET\Entities\Krb\KrbEncryptedData.cs:line 27 at Kerberos.NET.Crypto.DecryptedKrbApReq.Decrypt(KerberosKey ticketEncryptingKey) in D:\a\1\s\Kerberos.NET\Crypto\DecryptedKrbApReq.cs:line 75 at Kerberos.NET.Entities.ContextToken.DecryptApReq(KrbApReq token, KeyTable keytab) in D:\a\1\s\Kerberos.NET\Entities\SpNego\ContextToken.cs:line 45 at Kerberos.NET.KerberosValidator.<Validate>d__15.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosValidator.cs:line 70 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Kerberos.NET.KerberosAuthenticator.<Authenticate>d__13.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 73 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Kerberos.NET.KerberosAuthenticator.<Authenticate>d__12.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 69 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()
at LdapSession.
System.Security.SecurityException: Invalid checksum
at Kerberos.NET.Crypto.AESTransformer.Decrypt(ReadOnlyMemory1 cipher, KerberosKey kerberosKey, KeyUsage usage) in D:\a\1\s\Kerberos.NET\Crypto\AES\AESTransformer.cs:line 112 at Kerberos.NET.Entities.KrbEncryptedData.Decrypt[T](KerberosKey key, KeyUsage usage, Func
2 func) in D:\a\1\s\Kerberos.NET\Entities\Krb\KrbEncryptedData.cs:line 39
at Kerberos.NET.Crypto.DecryptedKrbApReq.Decrypt(KerberosKey ticketEncryptingKey) in D:\a\1\s\Kerberos.NET\Crypto\DecryptedKrbApReq.cs:line 75
at Kerberos.NET.Entities.ContextToken.DecryptApReq(KrbApReq token, KeyTable keytab) in D:\a\1\s\Kerberos.NET\Entities\SpNego\ContextToken.cs:line 45
at Kerberos.NET.KerberosValidator.
System.InvalidOperationException: Key EType AES128_CTS_HMAC_SHA1_96 must match the encrypted data EType AES256_CTS_HMAC_SHA1_96
at Kerberos.NET.Entities.KrbEncryptedData.Decrypt[T](KerberosKey key, KeyUsage usage, Func2 func) in D:\a\1\s\Kerberos.NET\Entities\Krb\KrbEncryptedData.cs:line 27 at Kerberos.NET.Crypto.DecryptedKrbApReq.Decrypt(KerberosKey ticketEncryptingKey) in D:\a\1\s\Kerberos.NET\Crypto\DecryptedKrbApReq.cs:line 75 at Kerberos.NET.Entities.ContextToken.DecryptApReq(KrbApReq token, KeyTable keytab) in D:\a\1\s\Kerberos.NET\Entities\SpNego\ContextToken.cs:line 45 at Kerberos.NET.KerberosValidator.<Validate>d__15.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosValidator.cs:line 70 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Kerberos.NET.KerberosAuthenticator.<Authenticate>d__13.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 73 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Kerberos.NET.KerberosAuthenticator.<Authenticate>d__12.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 69 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()
at LdapSession.
Okay, not that surprising. The key in the keytab "just" isn't the correct key. How did you generate the keytab file?
I have 2 domains, which have a 2-way transitive trust. The LDAP server is running in domain A and I'm trying to authenticate users from domain B. I created the keytab file in domain B:
ktpass /princ host/krbsvt@B.local /mapuser B\krbsvt /pass password /out Bkeys.keytab /crypto all /PTYPE KRB5_NT_PRINCIPAL /mapop add
B\krbsvt has “This account supports Kerberos AES 256 bit encryption”, "Password never expires" and "User cannot change password" enabled. I have verified that the UPN for user B\krbsvt got changed to host/krbsvt@B.local after generating the keytab file. I also validated that I could log into domain B with B\krbsvt and password.
If the LDAP server is in domain A why are you giving it a service account from domain B?
What is the SPN you're using for the LDAP server? What is the name you're passing to the client to resolve that SPN? I would guess it's getting a referral to A
, and resolving an SPN from domain A.
I created the keytab file in domain B, which is where the accounts are that will be used for Kerberos authentications, and which is why I used the service account from domain B.
The SPN, registered on the LDAP server in domain A, is ldap/host.A.local:port. I connect to ldap://host.A.local:port from the client in domain B. Domain B does not have any SPNs registered for ldap/host.A.local:port. Should I have the SPN registered in domain B as well? And if so, to the same service account I'm using for the keytab file?
Thanks again.
There are two sides to this. Clients making outbound calls -- "hello, please get me a ticket to ldap/blah@domain", and servers that accept inbound calls -- "hello, I am ldap/blah@domain". The client must go ask AD for a ticket to "ldap/blah" and AD encrypts a ticket to the key that only "ldap/blah" can decrypt via the keytab. The call you have here is just the server accept side. If you're asking for ldap/host.A.local then the domain of the client is going to think it needs a referral to A.local, and then the A.local domain controller is going to resolve an SPN by that name. You definitely got a ticket, so that SPN exists explicitly or it's getting resolved through the wildcard "host/" SPN.
So it sounds like SPNs are OK. Did you see anything of concern with the way I'm creating the keytab file, since that seems the be the cause of the errors I'm seeing?
You have an SPN of ldap/host.a.local[:port]
registered to the krbsvt@b.local
account?
Yes, I added the SPN to the domain B krbsvt user, re-generated the keytab file and still no luck.
I also used Bruce with the verify flag to inspect the keytab file. I see the Principal Name is listed as host/krbsvt. Is that correct even though I set the principal to host/krbsvt@b.local?
From within bruce
what does klist get ldap/host.a.local --verbose
with or without the port get you? If you get Cannot request a service ticket until a user is authenticated
then please also do kinit
from there too.
I assume you wanted the output from bruce on server B:
`bruce>klist get ldap/host.A.local --verbose
[Info] A ticket was retrieved for ldap@host.A.local
Ticket Count: 3
Server : krbtgt@B.LOCAL @ B.LOCAL
Ticket EType : AES256-CTS-HMAC-SHA1-96 (18)
Flags : 0x40e10000 -> Encrypted Pre-Authentication, Pre-Auth
enticated, Initial, Renewable, Forwardable Start Time : End Time : 4/18/2024 1:59:46 AM -04:00 Renew Until : 4/18/2024 3:59:46 PM -04:00 Session Key Type : AES256-CTS-HMAC-SHA1-96 (18)
Server : krbtgt@A.LOCAL @ B.LOCAL
Ticket EType : AES256-CTS-HMAC-SHA1-96 (18)
Flags : 0x40a10000 -> Encrypted Pre-Authentication, Pre-Auth
enticated, Renewable, Forwardable Start Time : End Time : 4/18/2024 1:59:46 AM -04:00 Renew Until : 4/18/2024 3:59:46 PM -04:00 Session Key Type : AES256-CTS-HMAC-SHA1-96 (18)
Server : ldap@host.A.local @ A.LOCAL
Ticket EType : AES256-CTS-HMAC-SHA1-96 (18)
Flags : 0x40a50000 -> Encrypted Pre-Authentication, Ok as De
legate, Pre-Authenticated, Renewable, Forwardable Start Time : End Time : 4/18/2024 1:59:46 AM -04:00 Renew Until : 4/18/2024 3:59:46 PM -04:00 Session Key Type : AES256-CTS-HMAC-SHA1-96 (18)
bruce>`
There's your issue. If you walk the list you'll see the order of operations.
The SPN is not registered correctly in B.local so the KDC never finds it, and thinks it needs to go ask A.local instead.
Thanks again for all your help. Would this still be your explanation, knowing that I can authenticate via Kerberos from server B to server A AD (not my LDAP instance)?
Yes, because the Server A would have the key of host.A.local because that's its key.
I have written an LDAP server that, among other things, processes Kerberos authentications. I had been using an old C SSPI library to process these authentications, but would like to use Kerberos.NET for a multitude of reasons. My code looks like:
byte[] token = ... (parsed Kerberos request bytes from incoming request)
KeyTable table = new KeyTable(File.ReadAllBytes());
KerberosAuthenticator authenticator = new KerberosAuthenticator(table);
Task authenticateTask = authenticator.Authenticate(token);
authenticateTask.Wait();
KerberosIdentity claimsIdentity = (KerberosIdentity)authenticateTask.Result;
I am getting an exception with the following stacktrace when calling authenticateTask.Wait():
System.AggregateException: One or more errors occurred. ---> System.Security.SecurityException: Invalid checksum at Kerberos.NET.Crypto.AESTransformer.Decrypt(ReadOnlyMemoryd15.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosValidator.cs:line 75
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Kerberos.NET.KerberosAuthenticator.d 13.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 73
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Kerberos.NET.KerberosAuthenticator.d12.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 69
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at LdapSession.d 58.MoveNext() in LdapSession.cs:line 629
---> (Inner Exception #0) System.Security.SecurityException: Invalid checksum
at Kerberos.NET.Crypto.AESTransformer.Decrypt(ReadOnlyMemoryd15.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosValidator.cs:line 75
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Kerberos.NET.KerberosAuthenticator.d 13.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 73
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Kerberos.NET.KerberosAuthenticator.d__12.MoveNext() in D:\a\1\s\Kerberos.NET\KerberosAuthenticator.cs:line 69
The Zone of the assembly that failed was:
MyComputer<---
1 cipher, KerberosKey kerberosKey, KeyUsage usage) in D:\a\1\s\Kerberos.NET\Crypto\AES\AESTransformer.cs:line 112 at Kerberos.NET.Entities.KrbEncryptedData.Decrypt[T](KerberosKey key, KeyUsage usage, Func
2 func) in D:\a\1\s\Kerberos.NET\Entities\Krb\KrbEncryptedData.cs:line 39 at Kerberos.NET.Crypto.DecryptedKrbApReq.Decrypt(KerberosKey ticketEncryptingKey) in D:\a\1\s\Kerberos.NET\Crypto\DecryptedKrbApReq.cs:line 75 at Kerberos.NET.Entities.ContextToken.DecryptApReq(KrbApReq token, KeyTable keytab) in D:\a\1\s\Kerberos.NET\Entities\SpNego\ContextToken.cs:line 45 at Kerberos.NET.KerberosValidator.1 cipher, KerberosKey kerberosKey, KeyUsage usage) in D:\a\1\s\Kerberos.NET\Crypto\AES\AESTransformer.cs:line 112 at Kerberos.NET.Entities.KrbEncryptedData.Decrypt[T](KerberosKey key, KeyUsage usage, Func
2 func) in D:\a\1\s\Kerberos.NET\Entities\Krb\KrbEncryptedData.cs:line 39 at Kerberos.NET.Crypto.DecryptedKrbApReq.Decrypt(KerberosKey ticketEncryptingKey) in D:\a\1\s\Kerberos.NET\Crypto\DecryptedKrbApReq.cs:line 75 at Kerberos.NET.Entities.ContextToken.DecryptApReq(KrbApReq token, KeyTable keytab) in D:\a\1\s\Kerberos.NET\Entities\SpNego\ContextToken.cs:line 45 at Kerberos.NET.KerberosValidator.