Example #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();
        }
Example #2
0
        private DnsMessageBase ProcessMessage(DnsMessageBase query, IPAddress ipAddress, ProtocolType protocolType)
        {
            if (query.TSigOptions != null)
            {
                switch (query.TSigOptions.ValidationResult)
                {
                case ReturnCode.BadKey:
                case ReturnCode.BadSig:
                    query.IsQuery             = false;
                    query.ReturnCode          = ReturnCode.NotAuthoritive;
                    query.TSigOptions.Error   = query.TSigOptions.ValidationResult;
                    query.TSigOptions.KeyData = null;

                    if (InvalidSignedMessageReceived != null)
                    {
                        InvalidSignedMessageReceived(this, new InvalidSignedMessageEventArgs(query));
                    }

                    return(query);

                case ReturnCode.BadTime:
                    query.IsQuery               = false;
                    query.ReturnCode            = ReturnCode.NotAuthoritive;
                    query.TSigOptions.Error     = query.TSigOptions.ValidationResult;
                    query.TSigOptions.OtherData = new byte[6];
                    int tmp = 0;
                    TSigRecord.EncodeDateTime(query.TSigOptions.OtherData, ref tmp, DateTime.Now);

                    if (InvalidSignedMessageReceived != null)
                    {
                        InvalidSignedMessageReceived(this, new InvalidSignedMessageEventArgs(query));
                    }

                    return(query);
                }
            }

            return(_processQueryDelegate(query, ipAddress, protocolType));
        }
Example #3
0
        public int Encode(bool addLengthPrefix, byte[] originalTsigMac, bool isSubSequentResponse, bool useCompressionMutation, out byte[] messageData, out byte[] newTSigMac)
        {
            PrepareEncoding();

            int offset        = 0;
            int messageOffset = offset;
            int maxLength     = addLengthPrefix ? 2 : 0;

            if (useCompressionMutation)
            {
                maxLength++;
            }

            originalTsigMac = originalTsigMac ?? new byte[] { };

            if (TSigOptions != null)
            {
                if (!IsQuery)
                {
                    offset    += 2 + originalTsigMac.Length;
                    maxLength += 2 + originalTsigMac.Length;
                }

                maxLength += TSigOptions.MaximumLength;
            }

            #region Get Message Length
            maxLength += 12;
            maxLength += Questions.Sum(question => question.MaximumLength);
            maxLength += AnswerRecords.Sum(record => record.MaximumLength);
            maxLength += AuthorityRecords.Sum(record => record.MaximumLength);
            maxLength += _additionalRecords.Sum(record => record.MaximumLength);
            #endregion

            messageData = new byte[maxLength];
            int currentPosition = offset;

            Dictionary <string, ushort> domainNames = new Dictionary <string, ushort>();

            EncodeUShort(messageData, ref currentPosition, TransactionID);
            EncodeUShort(messageData, ref currentPosition, Flags);
            EncodeUShort(messageData, ref currentPosition, (ushort)Questions.Count);
            EncodeUShort(messageData, ref currentPosition, (ushort)AnswerRecords.Count);
            EncodeUShort(messageData, ref currentPosition, (ushort)AuthorityRecords.Count);
            EncodeUShort(messageData, ref currentPosition, (ushort)_additionalRecords.Count);

            foreach (DnsQuestion question in Questions)
            {
                question.Encode(messageData, offset, ref currentPosition, domainNames, useCompressionMutation);
            }
            foreach (DnsRecordBase record in AnswerRecords)
            {
                record.Encode(messageData, offset, ref currentPosition, domainNames);
            }
            foreach (DnsRecordBase record in AuthorityRecords)
            {
                record.Encode(messageData, offset, ref currentPosition, domainNames);
            }
            foreach (DnsRecordBase record in _additionalRecords)
            {
                record.Encode(messageData, offset, ref currentPosition, domainNames);
            }

            if (TSigOptions == null)
            {
                newTSigMac = null;
            }
            else
            {
                if (!IsQuery)
                {
                    EncodeUShort(messageData, messageOffset, (ushort)originalTsigMac.Length);
                    Buffer.BlockCopy(originalTsigMac, 0, messageData, messageOffset + 2, originalTsigMac.Length);
                }

                EncodeUShort(messageData, offset, TSigOptions.OriginalID);

                int tsigVariablesPosition = currentPosition;

                if (isSubSequentResponse)
                {
                    TSigRecord.EncodeDateTime(messageData, ref tsigVariablesPosition, TSigOptions.TimeSigned);
                    EncodeUShort(messageData, ref tsigVariablesPosition, (ushort)TSigOptions.Fudge.TotalSeconds);
                }
                else
                {
                    EncodeDomainName(messageData, offset, ref tsigVariablesPosition, TSigOptions.Name, false, null);
                    EncodeUShort(messageData, ref tsigVariablesPosition, (ushort)TSigOptions.RecordClass);
                    EncodeInt(messageData, ref tsigVariablesPosition, (ushort)TSigOptions.TimeToLive);
                    EncodeDomainName(messageData, offset, ref tsigVariablesPosition, TSigAlgorithmHelper.GetDomainName(TSigOptions.Algorithm), false, null);
                    TSigRecord.EncodeDateTime(messageData, ref tsigVariablesPosition, TSigOptions.TimeSigned);
                    EncodeUShort(messageData, ref tsigVariablesPosition, (ushort)TSigOptions.Fudge.TotalSeconds);
                    EncodeUShort(messageData, ref tsigVariablesPosition, (ushort)TSigOptions.Error);
                    EncodeUShort(messageData, ref tsigVariablesPosition, (ushort)TSigOptions.OtherData.Length);
                    EncodeByteArray(messageData, ref tsigVariablesPosition, TSigOptions.OtherData);
                }

                KeyedHashAlgorithm hashAlgorithm = TSigAlgorithmHelper.GetHashAlgorithm(TSigOptions.Algorithm);
                //byte[] mac;
                if ((hashAlgorithm != null) && (TSigOptions.KeyData != null) && (TSigOptions.KeyData.Length > 0))
                {
                    hashAlgorithm.Key = TSigOptions.KeyData;
                    newTSigMac        = hashAlgorithm.ComputeHash(messageData, messageOffset, tsigVariablesPosition);
                }
                else
                {
                    newTSigMac = new byte[] { };
                }

                EncodeUShort(messageData, offset, TransactionID);
                EncodeUShort(messageData, offset + 10, (ushort)(_additionalRecords.Count + 1));

                TSigOptions.Encode(messageData, offset, ref currentPosition, domainNames, newTSigMac);

                if (!IsQuery)
                {
                    Buffer.BlockCopy(messageData, offset, messageData, messageOffset, (currentPosition - offset));
                    currentPosition -= (2 + originalTsigMac.Length);
                }
            }

            if (addLengthPrefix)
            {
                Buffer.BlockCopy(messageData, 0, messageData, 2, currentPosition);
                EncodeUShort(messageData, 0, (ushort)(currentPosition));
                currentPosition += 2;
            }

            return(currentPosition);
        }
Example #4
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);
            }
        }