Пример #1
0
        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();
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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;
                    }
                }
            }
        }
Пример #6
0
        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;
            }
        }
Пример #7
0
        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);
            }
        }