private void ParseInternal(byte[] data, DnsServer.SelectTsigKey tsigKeySelector, byte[] originalMac) { int currentPosition = 0; TransactionID = ParseUShort(data, ref currentPosition); Flags = ParseUShort(data, ref currentPosition); int questionCount = ParseUShort(data, ref currentPosition); int answerRecordCount = ParseUShort(data, ref currentPosition); int authorityRecordCount = ParseUShort(data, ref currentPosition); int additionalRecordCount = ParseUShort(data, ref currentPosition); ParseQuestions(data, ref currentPosition, questionCount); ParseSection(data, ref currentPosition, AnswerRecords, answerRecordCount); ParseSection(data, ref currentPosition, AuthorityRecords, authorityRecordCount); ParseSection(data, ref currentPosition, _additionalRecords, additionalRecordCount); if (_additionalRecords.Count > 0) { int tSigPos = _additionalRecords.FindIndex(record => (record.RecordType == RecordType.TSig)); if (tSigPos == (_additionalRecords.Count - 1)) { TSigOptions = (TSigRecord)_additionalRecords[tSigPos]; _additionalRecords.RemoveAt(tSigPos); TSigOptions.ValidationResult = ValidateTSig(data, tsigKeySelector, originalMac); } } FinishParsing(); }
internal static TMessage Parse <TMessage>(byte[] data, DnsServer.SelectTsigKey tsigKeySelector, byte[] originalMac) where TMessage : DnsMessageBase, new() { TMessage result = new TMessage(); result.ParseInternal(data, tsigKeySelector, originalMac); return(result); }
internal static DnsMessageBase CreateByFlag(byte[] data, DnsServer.SelectTsigKey tsigKeySelector, byte[] originalMac) { int flagPosition = 2; ushort flags = ParseUShort(data, ref flagPosition); DnsMessageBase res; switch ((OperationCode)((flags & 0x7800) >> 11)) { case OperationCode.Update: res = new DnsUpdateMessage(); break; default: res = new DnsMessage(); break; } res.ParseInternal(data, tsigKeySelector, originalMac); return(res); }
public static DnsMessageBase Create(byte[] resultData, bool isRequest, DnsServer.SelectTsigKey tsigKeySelector, byte[] originalMac) { int flagPosition = 2; ushort flags = ParseUShort(resultData, ref flagPosition); DnsMessageBase res; switch ((OperationCode)(flags & 0x7800)) { case OperationCode.Update: res = new DnsUpdateMessage(); break; default: res = new DnsMessage(); break; } res.Parse(resultData, isRequest, tsigKeySelector, originalMac); return(res); }
private async Task SendMessageParallelAsync <TMessage>(DnsClientEndpointInfo endpointInfo, TMessage message, byte[] messageData, int messageLength, DnsServer.SelectTsigKey tsigKeySelector, byte[] tsigOriginalMac, BlockingCollection <TMessage> results, CancellationToken token) where TMessage : DnsMessageBase, new() { using (UdpClient udpClient = new UdpClient(new IPEndPoint(endpointInfo.LocalAddress, 0))) { IPEndPoint serverEndpoint = new IPEndPoint(endpointInfo.ServerAddress, _port); await udpClient.SendAsync(messageData, messageLength, serverEndpoint); udpClient.Client.SendTimeout = QueryTimeout; udpClient.Client.ReceiveTimeout = QueryTimeout; while (true) { TMessage result; UdpReceiveResult response = await udpClient.ReceiveAsync(Int32.MaxValue, token); try { result = DnsMessageBase.Parse <TMessage>(response.Buffer, tsigKeySelector, tsigOriginalMac); } catch (Exception e) { Trace.TraceError("Error on dns query: " + e); continue; } if (!ValidateResponse(message, result)) { continue; } if (result.ReturnCode == ReturnCode.ServerFailure) { continue; } results.Add(result, token); if (token.IsCancellationRequested) { break; } } } }
private void PrepareMessage <TMessage>(TMessage message, out int messageLength, out byte[] messageData, out DnsServer.SelectTsigKey tsigKeySelector, out byte[] tsigOriginalMac) where TMessage : DnsMessageBase, new() { if (message.TransactionID == 0) { message.TransactionID = (ushort)_secureRandom.Next(1, 0xffff); } if (Is0x20ValidationEnabled) { message.Questions.ForEach(q => q.Name = q.Name.Add0x20Bits()); } messageLength = message.Encode(false, out messageData); if (message.TSigOptions != null) { tsigKeySelector = (n, a) => message.TSigOptions.KeyData; tsigOriginalMac = message.TSigOptions.Mac; } else { tsigKeySelector = null; tsigOriginalMac = null; } }
private ReturnCode ValidateTSig(byte[] resultData, DnsServer.SelectTsigKey tsigKeySelector, byte[] originalMac) { byte[] keyData; if ((TSigOptions.Algorithm == TSigAlgorithm.Unknown) || (tsigKeySelector == null) || ((keyData = tsigKeySelector(TSigOptions.Algorithm, TSigOptions.Name)) == null)) { return(ReturnCode.BadKey); } else if (((TSigOptions.TimeSigned - TSigOptions.Fudge) > DateTime.Now) || ((TSigOptions.TimeSigned + TSigOptions.Fudge) < DateTime.Now)) { return(ReturnCode.BadTime); } else if ((TSigOptions.Mac == null) || (TSigOptions.Mac.Length == 0)) { return(ReturnCode.BadSig); } else { TSigOptions.KeyData = keyData; // maxLength for the buffer to validate: Original (unsigned) dns message and encoded TSigOptions // because of compression of keyname, the size of the signed message can not be used int maxLength = TSigOptions.StartPosition + TSigOptions.MaximumLength; if (originalMac != null) { // add length of mac on responses. MacSize not neccessary, this field is allready included in the size of the tsig options maxLength += originalMac.Length; } byte[] validationBuffer = new byte[maxLength]; int currentPosition = 0; // original mac if neccessary if ((originalMac != null) && (originalMac.Length > 0)) { EncodeUShort(validationBuffer, ref currentPosition, (ushort)originalMac.Length); EncodeByteArray(validationBuffer, ref currentPosition, originalMac); } // original unsiged buffer Buffer.BlockCopy(resultData, 0, validationBuffer, currentPosition, TSigOptions.StartPosition); // update original transaction id and ar count in message EncodeUShort(validationBuffer, currentPosition, TSigOptions.OriginalID); EncodeUShort(validationBuffer, currentPosition + 10, (ushort)_additionalRecords.Count); currentPosition += TSigOptions.StartPosition; // TSig Variables EncodeDomainName(validationBuffer, 0, ref currentPosition, TSigOptions.Name, false, null); EncodeUShort(validationBuffer, ref currentPosition, (ushort)TSigOptions.RecordClass); EncodeInt(validationBuffer, ref currentPosition, (ushort)TSigOptions.TimeToLive); EncodeDomainName(validationBuffer, 0, ref currentPosition, TSigAlgorithmHelper.GetDomainName(TSigOptions.Algorithm), false, null); TSigRecord.EncodeDateTime(validationBuffer, ref currentPosition, TSigOptions.TimeSigned); EncodeUShort(validationBuffer, ref currentPosition, (ushort)TSigOptions.Fudge.TotalSeconds); EncodeUShort(validationBuffer, ref currentPosition, (ushort)TSigOptions.Error); EncodeUShort(validationBuffer, ref currentPosition, (ushort)TSigOptions.OtherData.Length); EncodeByteArray(validationBuffer, ref currentPosition, TSigOptions.OtherData); // Validate MAC KeyedHashAlgorithm hashAlgorithm = TSigAlgorithmHelper.GetHashAlgorithm(TSigOptions.Algorithm); hashAlgorithm.Key = keyData; return((hashAlgorithm.ComputeHash(validationBuffer, 0, currentPosition).SequenceEqual(TSigOptions.Mac)) ? ReturnCode.NoError : ReturnCode.BadSig); } }