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()) }); }
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))); }
public static bool CanDecode(byte[] message) { try { return(KdcProxyMessage.TryDecode(message, out _)); } catch { return(false); } }
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 { } }
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)); }
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())); } }
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); }
private static ReadOnlyMemory <byte> EncodeProxyResponse(ReadOnlyMemory <byte> response) { return(KdcProxyMessage.WrapMessage(response).Encode()); }