public void KrbErrorRoundtrip() { var err = new KrbError { CName = new KrbPrincipalName { Name = new[] { "krbtgt", "domain.com" }, Type = PrincipalNameType.NT_SRV_HST }, CRealm = "domain.com", CTime = DateTimeOffset.UtcNow, Cusec = 123, EData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }, ErrorCode = KerberosErrorCode.KRB_ERR_GENERIC, EText = "this is a test of the error roundtrip", Realm = "domain.com", SName = new KrbPrincipalName { Name = new[] { "krbtgt", "domain.com" }, Type = PrincipalNameType.NT_SRV_HST }, STime = DateTimeOffset.UtcNow, Susc = 2345356 }; var encoded = err.EncodeApplication(); var decoded = KrbError.DecodeApplication(encoded); Assert.IsNotNull(decoded); Assert.AreEqual(err.CRealm, decoded.CRealm); Assert.AreEqual(MessageType.KRB_ERROR, decoded.MessageType); Assert.AreEqual(5, decoded.ProtocolVersionNumber); Assert.AreEqual(err.CTime.ToString(), decoded.CTime.ToString()); Assert.AreEqual(err.ErrorCode, decoded.ErrorCode); Assert.AreEqual(err.Realm, decoded.Realm); }
public async Task ParseKdcProxyMessage_WithoutLength() { var req = KrbAsReq.CreateAsReq( new KerberosPasswordCredential("*****@*****.**", "P@ssw0rd!"), 0 ).EncodeApplication(); var domain = "corp.identityintervention.com"; var hint = DcLocatorHint.DS_AVOID_SELF; var message = KdcProxyMessage.WrapMessage(req, domain, hint, mode: KdcProxyMessageMode.NoPrefix); var kdc = new KdcServer(new KdcServerOptions { RealmLocator = realm => new FakeRealmService(realm) }); var response = await kdc.ProcessMessage(message.Encode()); Assert.IsTrue(response.Length > 0); Assert.IsFalse(KrbError.CanDecode(response)); var proxy = KdcProxyMessage.Decode(response); var preAuthReq = KrbError.DecodeApplication(proxy.UnwrapMessage(out KdcProxyMessageMode mode)); Assert.AreEqual(KdcProxyMessageMode.NoPrefix, mode); Assert.AreEqual(KerberosErrorCode.KDC_ERR_PREAUTH_REQUIRED, preAuthReq.ErrorCode); }
public void KrbErrorParseEtypeInfo() { var krbErrBin = ReadDataFile("messages\\krb-error-preauth-required").Skip(4).ToArray(); var err = KrbError.DecodeApplication(krbErrBin); var preauth = err.DecodePreAuthentication(); IEnumerable <KrbETypeInfo2Entry> etype = null; foreach (var auth in preauth) { if (auth.Type == PaDataType.PA_ETYPE_INFO2) { etype = auth.DecodeETypeInfo2(); } } Assert.IsNotNull(etype); Assert.AreEqual(2, etype.Count()); Assert.AreEqual(EncryptionType.AES256_CTS_HMAC_SHA1_96, etype.ElementAt(0).EType); Assert.AreEqual(EncryptionType.RC4_HMAC_NT, etype.ElementAt(1).EType); }
private void ProcessKdcProxy(KdcProxyMessage proxyMessage, string source) { var message = proxyMessage.UnwrapMessage(); var kdcBody = new { AsReq = TryDecode(message, m => KrbAsReq.DecodeApplication(m)), AsRep = TryDecode(message, m => KrbAsRep.DecodeApplication(m)), TgsReq = TryDecode(message, m => KrbTgsReq.DecodeApplication(m)), TgsRep = TryDecode(message, m => KrbTgsRep.DecodeApplication(m)), KrbError = TryDecode(message, m => KrbError.DecodeApplication(m)) }; if (kdcBody.AsReq != null) { ExplodeObject(kdcBody.AsReq, $"AS-REQ ({source})"); } else if (kdcBody.AsRep != null) { ExplodeObject(kdcBody.AsRep, $"AS-REP ({source})"); } else if (kdcBody.TgsReq != null) { ExplodeObject(kdcBody.TgsReq, $"TGS-REQ ({source})"); } else if (kdcBody.TgsRep != null) { ExplodeObject(kdcBody.TgsRep, $"TGS-REP ({source})"); } else if (kdcBody.KrbError != null) { ExplodeObject(kdcBody.KrbError, $"Krb-Error ({source})"); } }
private static string GetErrorMessage(KrbError error) { if (!string.IsNullOrWhiteSpace(error.EText)) { return(error.EText); } return($"KDC {error.ErrorCode}: {GetErrorMessage(error.ErrorCode)}"); }
private static string GetErrorMessage(KrbError error) { if (!string.IsNullOrWhiteSpace(error.EText)) { return(error.EText); } return(SR.Resource($"KRB_ERROR_{error.ErrorCode}")); }
public void ErrorPreAuthRoundtrip() { var krbErrBin = ReadDataFile("messages\\krb-error-preauth-required").Skip(4).ToArray(); var err = KrbError.DecodeApplication(krbErrBin); var bytes = err.EncodeApplication(); Assert.IsTrue(krbErrBin.SequenceEqual(bytes.ToArray())); }
private ReadOnlyMemory <byte> PreAuthFailed(PreAuthenticationContext context) { var err = new KrbError { ErrorCode = KerberosErrorCode.KDC_ERR_PREAUTH_FAILED, EText = context.Failure.Message, Realm = this.RealmService.Name, SName = KrbPrincipalName.FromPrincipal(context.Principal) }; return(err.EncodeApplication()); }
private ReadOnlyMemory <byte> PreAuthFailed(KerberosValidationException kex, IKerberosPrincipal principal) { var err = new KrbError { ErrorCode = KerberosErrorCode.KDC_ERR_PREAUTH_FAILED, EText = kex.Message, Realm = RealmService.Name, SName = KrbPrincipalName.FromPrincipal(principal) }; return(err.EncodeApplication()); }
public void Message_KrbErrorPreAuth() { var file = ReadDataFile("messages\\krb-error-preauth-required"); var decoded = TestSimpleRoundtrip( "krb-error-preauth-required", file.Skip(4).ToArray(), v => KrbError.DecodeApplication(v), t => t.EncodeApplication().ToArray() ); Assert.IsNotNull(decoded); }
public void ResourceManagerFormattedResource() { var asReq = ReadDataFile("messages\\as-req"); try { KrbError.DecodeApplication(asReq); } catch (Exception ex) { Assert.IsTrue(ex.Message.Contains("Expected Application-30")); throw; } }
protected static T Decode <T>(byte[] response) where T : IAsn1ApplicationEncoder <T>, new() { if (KrbError.CanDecode(response)) { var error = KrbError.DecodeApplication(response); if (error.ErrorCode == KerberosErrorCode.KRB_ERR_RESPONSE_TOO_BIG) { throw new KerberosTransportException(error); } throw new KerberosProtocolException(error); } return(new T().DecodeAsApplication(response)); }
private ReadOnlyMemory <byte> RequirePreAuth(IEnumerable <KrbPaData> preAuthRequests, IKerberosPrincipal principal) { var err = new KrbError { ErrorCode = KerberosErrorCode.KDC_ERR_PREAUTH_REQUIRED, EText = "", Realm = RealmService.Name, SName = KrbPrincipalName.FromPrincipal(principal), EData = new KrbMethodData { MethodData = preAuthRequests.ToArray() }.Encode().AsMemory() }; return(err.EncodeApplication()); }
public async Task KdcTagPeekFailureApplication() { var kdc = new KdcServer(new KdcServerOptions { DefaultRealm = "domain.com", IsDebug = true, Log = new FakeExceptionLoggerFactory() }); var checksum = new KrbChecksum { }; var response = await kdc.ProcessMessage(checksum.Encode()); var err = KrbError.DecodeApplication(response); Assert.IsNotNull(err); Assert.AreEqual(KerberosErrorCode.KRB_ERR_GENERIC, err.ErrorCode); }
private ReadOnlyMemory <byte> RequirePreAuth(PreAuthenticationContext context) { this.logger.LogTrace("AS-REQ requires pre-auth for user {User}", context.Principal.PrincipalName); var err = new KrbError { ErrorCode = KerberosErrorCode.KDC_ERR_PREAUTH_REQUIRED, EText = string.Empty, Realm = this.RealmService.Name, SName = KrbPrincipalName.FromPrincipal(context.Principal), EData = new KrbMethodData { MethodData = context.PaData.ToArray() }.Encode() }; return(err.EncodeApplication()); }
public async Task KdcTagPeekFailureUnknownHandler() { var kdc = new KdcServer(new KdcServerOptions { DefaultRealm = "domain.com", IsDebug = true }); var krbCred = new KrbCred { Tickets = Array.Empty <KrbTicket>() }; var response = await kdc.ProcessMessage(krbCred.EncodeApplication()); var err = KrbError.DecodeApplication(response); Assert.IsNotNull(err); Assert.AreEqual(KerberosErrorCode.KRB_ERR_GENERIC, err.ErrorCode); Assert.IsTrue(err.EText.Contains("doesn't have a message handler registered")); }
public async Task TestKdcTagPeekFailureApplication() { var kdc = new KdcServer(new ListenerOptions { DefaultRealm = "domain.com", IsDebug = true, Log = new ValidatorTests.TestLogger() }); var checksum = new KrbChecksum { }; ReadOnlySequence <byte> request = new ReadOnlySequence <byte>(checksum.Encode().ToArray()); var response = await kdc.ProcessMessage(request); var err = KrbError.DecodeApplication(response); Assert.IsNotNull(err); Assert.AreEqual(KerberosErrorCode.KRB_ERR_GENERIC, err.ErrorCode); Assert.IsTrue(err.EText.Contains("Unknown incoming tag")); }
public async Task TestKdcTagPeekFailureUnknownHandler() { var kdc = new KdcServer(new ListenerOptions { DefaultRealm = "domain.com", IsDebug = true }); var aprepPart = new KrbEncApRepPart { }; ReadOnlySequence <byte> request = new ReadOnlySequence <byte>(aprepPart.EncodeApplication().ToArray()); var response = await kdc.ProcessMessage(request); var err = KrbError.DecodeApplication(response); Assert.IsNotNull(err); Assert.AreEqual(KerberosErrorCode.KRB_ERR_GENERIC, err.ErrorCode); Assert.IsTrue(err.EText.Contains("doesn't have a message handler registered")); }
public async Task KdcTagPeekFailureNullBuilder() { var kdc = new KdcServer(new KdcServerOptions { DefaultRealm = "domain.com", IsDebug = true }); kdc.RegisterMessageHandler(MessageType.KRB_CRED, (b, o) => null); var krbCred = new KrbCred { Tickets = Array.Empty <KrbTicket>() }; var response = await kdc.ProcessMessage(krbCred.EncodeApplication()); var err = KrbError.DecodeApplication(response); Assert.IsNotNull(err); Assert.AreEqual(KerberosErrorCode.KRB_ERR_GENERIC, err.ErrorCode); Assert.IsTrue(err.EText.Contains("Message handler builder KRB_CRED must not return null")); }
internal static ReadOnlyMemory <byte> GenerateError(KerberosErrorCode code, string error, string realm, string sname) { var krbErr = new KrbError() { ErrorCode = code, EText = error, Realm = realm, SName = new KrbPrincipalName { Type = PrincipalNameType.NT_SRV_INST, Name = new[] { sname, realm } } }; krbErr.StampServerTime(); return(krbErr.EncodeApplication()); }
public async Task TestKdcTagPeekFailureNullBuilder() { var kdc = new KdcServer(new ListenerOptions { DefaultRealm = "domain.com", IsDebug = true }); kdc.RegisterMessageHandler((MessageType)27, (b, o) => null); var aprepPart = new KrbEncApRepPart { }; ReadOnlySequence <byte> request = new ReadOnlySequence <byte>(aprepPart.EncodeApplication().ToArray()); var response = await kdc.ProcessMessage(request); var err = KrbError.DecodeApplication(response); Assert.IsNotNull(err); Assert.AreEqual(KerberosErrorCode.KRB_ERR_GENERIC, err.ErrorCode); Assert.IsTrue(err.EText.Contains("Message handler builder 27 must not return null")); }
public async Task ParseKdcProxyMessage() { var req = KrbAsReq.CreateAsReq( new KerberosPasswordCredential("*****@*****.**", "P@ssw0rd!"), 0 ).EncodeApplication(); var domain = "corp.identityintervention.com"; var hint = DcLocatorHint.DS_AVOID_SELF; var messageBytes = new Memory <byte>(new byte[req.Length + 4]); Endian.ConvertToBigEndian(req.Length, messageBytes.Slice(0, 4)); req.CopyTo(messageBytes.Slice(4, req.Length)); var message = new KdcProxyMessage { TargetDomain = domain, KerbMessage = messageBytes, DcLocatorHint = hint }; var kdc = new KdcServer(new ListenerOptions { RealmLocator = LocateFakeRealm }); var response = await kdc.ProcessMessage(new ReadOnlySequence <byte>(message.Encode())); Assert.IsTrue(response.Length > 0); Assert.IsFalse(KrbError.CanDecode(response)); var proxy = KdcProxyMessage.Decode(response); var preAuthReq = KrbError.DecodeApplication(proxy.UnwrapMessage()); Assert.AreEqual(KerberosErrorCode.KDC_ERR_PREAUTH_REQUIRED, preAuthReq.ErrorCode); }
public KerberosProtocolException(KrbError error) : this(GetErrorMessage(error)) { Error = error; }
public void TestParseAllMessagesRoundtrip() { var allMessages = ReadDataFiles("messages\\"); foreach (var file in allMessages) { var key = file.Key.Substring(file.Key.LastIndexOf('\\') + 1); Debug.WriteLine(file.Value.HexDump()); switch (key) { case "as-rep": var asrep = TestSimpleRoundtrip( key, file.Value.Skip(4).ToArray(), v => new KrbAsRep().DecodeAsApplication(v), t => t.EncodeApplication().ToArray() ); break; case "as-req": TestSimpleRoundtrip( key, file.Value.Skip(4).ToArray(), v => KrbAsReq.DecodeApplication(v), t => t.EncodeApplication().ToArray()); break; case "as-req-preauth": TestSimpleRoundtrip( key, file.Value.Skip(4).ToArray(), v => KrbAsReq.DecodeApplication(v), t => t.EncodeApplication().ToArray()); break; case "krb-error-preauth-required": TestSimpleRoundtrip( key, file.Value.Skip(4).ToArray(), v => KrbError.DecodeApplication(v), t => t.EncodeApplication().ToArray()); break; case "tgs-rep-testuser-host-app03": TestSimpleRoundtrip( key, file.Value.Skip(4).ToArray(), v => KrbTgsRep.DecodeApplication(v), t => t.EncodeApplication().ToArray() ); break; case "tgs-rep-testuser-host-appservice": TestSimpleRoundtrip( key, file.Value.Skip(4).ToArray(), v => KrbTgsRep.DecodeApplication(v), t => t.EncodeApplication().ToArray() ); break; case "tgs-rep-testuser-krbtgt-renew": TestSimpleRoundtrip( key, file.Value.Skip(4).ToArray(), v => KrbTgsRep.DecodeApplication(v), t => t.EncodeApplication().ToArray() ); break; case "tgs-req-testuser-host-app03": var thing = TestSimpleRoundtrip( key, file.Value.Skip(4).ToArray(), v => KrbTgsReq.DecodeApplication(v), t => t.EncodeApplication().ToArray() ); break; case "tgs-req-testuser-host-appservice": TestSimpleRoundtrip( key, file.Value.Skip(4).ToArray(), v => KrbTgsReq.DecodeApplication(v), t => t.EncodeApplication().ToArray()); break; case "tgs-req-testuser-krbtgt-renew": TestSimpleRoundtrip( key, file.Value.Skip(4).ToArray(), v => KrbTgsReq.DecodeApplication(v), t => t.EncodeApplication().ToArray()); break; } } }
public static string ETextWithoutCode(this KrbError error) { return(error?.EText?.Replace(error?.ErrorCode.ToString() + ": ", "")); }
public KerberosTransportException(KrbError error) : base(error) { }
private void WritePreAuthRequirement(KerberosPasswordCredential credential, KrbError error, KrbAsReq asreq) { if (this.Verbose) { this.WriteLine(); } this.WriteLine(1, "{ErrorCode}: {ErrorText}", error.ErrorCode, error.ETextWithoutCode() ?? "(no message)"); this.WriteLine(); if (!string.IsNullOrWhiteSpace(error.Realm)) { this.WriteLine(1, " Realm: {Realm}", error.Realm); } if (error.CName != null) { this.WriteLine(1, " Client: {CName}", error.CName.FullyQualifiedName); } if (error.SName != null) { this.WriteLine(1, "Server: {SName}", error.SName.FullyQualifiedName); } this.WriteLine(); if (error.ErrorCode == KerberosErrorCode.KDC_ERR_ETYPE_NOSUPP) { this.IO.WriteAsColor(" Error: ", ConsoleColor.Red); this.WriteLine("Client requested the following ETypes but the KDC cannot support any of them."); this.WriteLine(); bool first = true; foreach (var etype in asreq.Body.EType) { var label = first ? "ETypes: " : " "; this.WriteLine(1, label + "{ETypes}", etype); first = false; } if (!asreq.Body.EType.Contains(EncryptionType.RC4_HMAC_NT)) { this.WriteLine(); this.IO.WriteAsColor(" Note: ", ConsoleColor.Green); this.WriteLine("RC4 is not enabled on the client. The KDC likely only supports RC4 for this user."); } return; } if (error.ErrorCode == KerberosErrorCode.KDC_ERR_POLICY && error.EData.HasValue && KrbErrorData.CanDecode(error.EData.Value)) { var decoded = KrbErrorData.Decode(error.EData.Value); var ext = decoded.DecodeExtendedError(); this.WriteLine(1, error.EText); this.WriteLine(); this.WriteLine(1, "Status: {Status}", ext.Status); this.WriteLine(1, " Flags: {Flags}", ext.Flags); return; } if (error.ErrorCode != KerberosErrorCode.KDC_ERR_PREAUTH_REQUIRED) { if (error.EData.HasValue) { this.WriteLine(1, "{EData}", error.EData); } return; } var paData = error?.DecodePreAuthentication(); if (paData != null) { int index = 0; foreach (var pa in paData.OrderBy(p => p.Type != PaDataType.PA_ETYPE_INFO2).ThenBy(p => p.Type)) { index++; this.WriteLine(2, "- PA-Data Type: {PAType} ({PATypeValue})", pa.Type, (int)pa.Type); var isEtype = pa.Type == PaDataType.PA_ETYPE_INFO2; if (isEtype) { var etypeData = pa.DecodeETypeInfo2(); this.WriteLine(3, "KDC Supported ETypes for principal {PrincipalName}", credential.UserName); this.WriteLine(); foreach (var etype in etypeData) { this.WriteLine(4, "Etype: {EType}", etype.EType); this.WriteLine(4, " Salt: {Salt}", etype.Salt); this.WriteLine(4, " S2K: {S2kParams}", etype.S2kParams ?? Array.Empty <byte>()); this.WriteLine(); } } if (!isEtype || this.Verbose) { if (pa.Value.Length > 0) { if (!isEtype) { this.WriteLine(); } this.WriteLine(3, pa.Value); } else { this.WriteLine(3, (object)null); if (index < paData.Count()) { this.WriteLine(); } } } } } }