diff --git a/Kerberos.NET/Client/ApplicationSessionContext.cs b/Kerberos.NET/Client/ApplicationSessionContext.cs index 2ec1f24..cd0b961 100644 --- a/Kerberos.NET/Client/ApplicationSessionContext.cs +++ b/Kerberos.NET/Client/ApplicationSessionContext.cs @@ -15,15 +15,19 @@ public class ApplicationSessionContext public KrbEncryptionKey SessionKey { get; set; } + public KrbEncryptionKey ClientSubSessionKey { get; set; } + + public KrbEncryptionKey ServerSubSessionKey { get; set; } + public int? SequenceNumber { get; set; } public int CuSec { get; set; } public DateTimeOffset CTime { get; set; } - public KrbEncryptionKey AuthenticateServiceResponse(string asRepEncoded) + public KrbEncryptionKey AuthenticateServiceResponse(string apRepEncoded) { - return AuthenticateServiceResponse(Convert.FromBase64String(asRepEncoded)); + return AuthenticateServiceResponse(Convert.FromBase64String(apRepEncoded)); } public KrbEncryptionKey AuthenticateServiceResponse(ReadOnlyMemory apRepBytes) @@ -37,11 +41,35 @@ public KrbEncryptionKey AuthenticateServiceResponse(ReadOnlyMemory apRepBy SequenceNumber = this.SequenceNumber }; - decrypted.Decrypt(this.SessionKey.AsKey()); + DecryptApRep(decrypted); decrypted.Validate(ValidationActions.TokenWindow); + ServerSubSessionKey = decrypted.Response.SubSessionKey; + + return ServerSubSessionKey ?? this.SessionKey; + } - return decrypted.Response.SubSessionKey ?? this.SessionKey; + private void DecryptApRep(DecryptedKrbApRep decrypted) + { + foreach(var key in new[] { + this.SessionKey, + this.ClientSubSessionKey + }) + { + if (key == null) continue; + try + { + decrypted.Decrypt(key.AsKey()); + return; + } + catch (Exception) + { + // Not this key, continue to the next one + } + } + + throw new InvalidOperationException("Failed to decrypt AP_REP with any of the provided keys."); } + } } diff --git a/Kerberos.NET/Client/KerberosClient.cs b/Kerberos.NET/Client/KerberosClient.cs index 1f22b2b..9102a42 100644 --- a/Kerberos.NET/Client/KerberosClient.cs +++ b/Kerberos.NET/Client/KerberosClient.cs @@ -882,7 +882,8 @@ public async Task GetServiceTicket( rst, out KrbAuthenticator authenticator ), - SessionKey = authenticator.Subkey ?? serviceTicketCacheEntry.SessionKey, + SessionKey = serviceTicketCacheEntry.SessionKey, + ClientSubSessionKey = authenticator.Subkey, CTime = authenticator.CTime, CuSec = authenticator.CuSec, SequenceNumber = authenticator.SequenceNumber diff --git a/Kerberos.NET/Crypto/DecryptedKrbApRep.cs b/Kerberos.NET/Crypto/DecryptedKrbApRep.cs index 13c67a9..f62df57 100644 --- a/Kerberos.NET/Crypto/DecryptedKrbApRep.cs +++ b/Kerberos.NET/Crypto/DecryptedKrbApRep.cs @@ -61,14 +61,6 @@ public override void Validate(ValidationActions validation) nameof(this.CuSec) ); } - - if (this.SequenceNumber != this.Response.SequenceNumber) - { - throw new KerberosValidationException( - $"SequenceNumber does not match. Sent: {this.SequenceNumber}; Received: {this.Response.SequenceNumber}", - nameof(this.SequenceNumber) - ); - } } } }