public override async Task <T> SendMessage <T>(string domain, ReadOnlyMemory <byte> req, CancellationToken cancellation = default)
        {
            var kdc = LocateKdc(domain);

            var message = KdcProxyMessage.WrapMessage(req, domain, Hint);

            var response = await Client.PostAsync(kdc, new BinaryContent(message.Encode()));

            if (response.Content == null)
            {
                response.EnsureSuccessStatusCode();
            }

            var responseBody = await response.Content.ReadAsByteArrayAsync();

            if (!KdcProxyMessage.TryDecode(responseBody, out KdcProxyMessage kdcResponse))
            {
                response.EnsureSuccessStatusCode();

                string body = "";

                if (responseBody.Length > 0)
                {
                    body = Encoding.UTF8.GetString(responseBody);
                }

                throw new KerberosProtocolException($"Cannot process HTTP Response: {body}");
            }

            return(Decode <T>(kdcResponse.UnwrapMessage()));
        }
            protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                var realmService = new FakeRealmService(Realm);
                var principal    = await realmService.Principals.Find(UserUpn);

                var principalKey = await principal.RetrieveLongTermCredential();

                var rst = new ServiceTicketRequest
                {
                    Principal           = principal,
                    EncryptedPartKey    = principalKey,
                    ServicePrincipalKey = new KerberosKey(key: TgtKey, etype: EncryptionType.AES256_CTS_HMAC_SHA1_96)
                };

                var tgt = await KrbAsRep.GenerateTgt(rst, realmService);

                var encoded = tgt.EncodeApplication();

                var response = new Memory <byte>(new byte[encoded.Length + 4]);

                Endian.ConvertToBigEndian(encoded.Length, response.Slice(0, 4));
                encoded.CopyTo(response.Slice(4));

                var kdcMessage = new KdcProxyMessage
                {
                    KerbMessage = response
                };

                return(new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new ByteArrayContent(kdcMessage.Encode().ToArray())
                });
            }
Example #3
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);
        }
        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})");
            }
        }
        public override async Task <T> SendMessage <T>(string domain, ReadOnlyMemory <byte> req, CancellationToken cancellation = default)
        {
            var kdc = LocateKdc(domain);

            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 response = await Client.PostAsync(kdc, new BinaryContent(message.Encode()));

            response.EnsureSuccessStatusCode();

            var responseBody = await response.Content.ReadAsByteArrayAsync();

            var kdcResponse = KdcProxyMessage.Decode(responseBody);

            return(Decode <T>(kdcResponse.KerbMessage.Slice(4)));
        }
Example #6
0
 public static bool CanDecode(byte[] message)
 {
     try
     {
         return(KdcProxyMessage.TryDecode(message, out _));
     }
     catch
     {
         return(false);
     }
 }
Example #7
0
        private async Task <ReadOnlyMemory <byte> > ProcessProxyMessage(ReadOnlySequence <byte> request)
        {
            var proxyMessage = KdcProxyMessage.Decode(request.ToArray());

            var unwrapped = proxyMessage.UnwrapMessage();

            var tag = PeekTag(unwrapped);

            var response = await ProcessMessageCore(new ReadOnlySequence <byte>(unwrapped), tag);

            return(EncodeProxyResponse(response));
        }
        internal void ProcessMessage(byte[] message, string source = null)
        {
            if (messageParsed)
            {
                return;
            }

            ResetLayout();

            object parsedMessage = null;

            try
            {
                parsedMessage = MessageParser.Parse(message);
            }
            catch { }

            if (parsedMessage == null)
            {
                try
                {
                    var nego = NegotiationToken.Decode(message);

                    if (nego.ResponseToken != null)
                    {
                        parsedMessage = MessageParser.Parse(nego.ResponseToken.ResponseToken.Value);
                    }
                }
                catch { }
            }

            if (parsedMessage is NtlmContextToken ntlm)
            {
                ProcessNtlm(ntlm, source);
            }
            else if (parsedMessage is NegotiateContextToken nego)
            {
                ProcessNegotiate(nego.Token, source);
            }
            else if (parsedMessage is KerberosContextToken kerb)
            {
                ProcessKerberos(kerb, source);
            }

            try
            {
                if (KdcProxyMessage.TryDecode(message, out KdcProxyMessage proxyMessage))
                {
                    ProcessKdcProxy(proxyMessage, source);
                }
            }
            catch { }
        }
Example #9
0
        private async Task <ReadOnlyMemory <byte> > ProcessProxyMessageAsync(ReadOnlyMemory <byte> request)
        {
            var proxyMessage = KdcProxyMessage.Decode(request);

            var unwrapped = proxyMessage.UnwrapMessage(out KdcProxyMessageMode mode);

            var tag = KrbMessage.PeekTag(unwrapped);

            var response = await ProcessMessageCoreAsync(unwrapped, tag);

            return(EncodeProxyResponse(response, mode));
        }
Example #10
0
        private async Task <ReadOnlyMemory <byte> > ProcessProxyMessage(ReadOnlySequence <byte> request)
        {
            var proxyMessage = KdcProxyMessage.Decode(request.ToArray());

            var length  = proxyMessage.KerbMessage.Slice(0, 4).AsLong();
            var message = new ReadOnlySequence <byte>(proxyMessage.KerbMessage.Slice(4));

            if (length != message.Length)
            {
                throw new InvalidOperationException(
                          $"Proxy message length {length} doesn't match actual message length {message.Length}"
                          );
            }

            var tag = PeekTag(message);

            var response = await ProcessMessageCore(message, tag);

            return(new KdcProxyMessage
            {
                KerbMessage = response
            }.Encode());
        }
        private async Task <T> SendMessage <T>(string domain, ReadOnlyMemory <byte> req, Uri kdc)
            where T : IAsn1ApplicationEncoder <T>, new()
        {
            var message = KdcProxyMessage.WrapMessage(req, domain, this.Hint);

            using (var content = new BinaryContent(message.Encode()))
            {
                content.Headers.Add(CorrelationIdHeader, this.ScopeId.ToString());

                var response = await this.Client.PostAsync(kdc, content).ConfigureAwait(false);

                this.TryParseRequestId(response);

                if (response.Content == null)
                {
                    response.EnsureSuccessStatusCode();
                }

                var responseBody = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

                if (!KdcProxyMessage.TryDecode(responseBody, out KdcProxyMessage kdcResponse))
                {
                    response.EnsureSuccessStatusCode();

                    string body = string.Empty;

                    if (responseBody.Length > 0)
                    {
                        body = Encoding.UTF8.GetString(responseBody);
                    }

                    throw new KerberosProtocolException($"Cannot process HTTP Response: {body}");
                }

                return(Decode <T>(kdcResponse.UnwrapMessage()));
            }
        }
Example #12
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);
        }
Example #13
0
 private static ReadOnlyMemory <byte> EncodeProxyResponse(ReadOnlyMemory <byte> response)
 {
     return(KdcProxyMessage.WrapMessage(response).Encode());
 }