Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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})");
            }
        }
Пример #5
0
        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}"));
        }
Пример #7
0
        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()));
        }
Пример #8
0
        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());
        }
Пример #10
0
        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);
        }
Пример #11
0
        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;
            }
        }
Пример #12
0
        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());
        }
Пример #14
0
        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);
        }
Пример #15
0
        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());
        }
Пример #16
0
        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"));
        }
Пример #17
0
        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"));
        }
Пример #18
0
        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"));
        }
Пример #19
0
        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"));
        }
Пример #20
0
        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());
        }
Пример #21
0
        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"));
        }
Пример #22
0
        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;
 }
Пример #24
0
        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;
                }
            }
        }
Пример #25
0
 public static string ETextWithoutCode(this KrbError error)
 {
     return(error?.EText?.Replace(error?.ErrorCode.ToString() + ": ", ""));
 }
 public KerberosTransportException(KrbError error)
     : base(error)
 {
 }
Пример #27
0
        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();
                            }
                        }
                    }
                }
            }
        }