예제 #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
        private async Task <DnsMessageBase> ProcessMessageAsync(DnsMessageBase query, ProtocolType protocolType, IPEndPoint remoteEndpoint)
        {
            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;

#pragma warning disable 4014
                    InvalidSignedMessageReceived.RaiseAsync(this, new InvalidSignedMessageEventArgs(query, protocolType, remoteEndpoint));
#pragma warning restore 4014

                    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);

#pragma warning disable 4014
                    InvalidSignedMessageReceived.RaiseAsync(this, new InvalidSignedMessageEventArgs(query, protocolType, remoteEndpoint));
#pragma warning restore 4014

                    return(query);
                }
            }

            QueryReceivedEventArgs eventArgs = new QueryReceivedEventArgs(query, protocolType, remoteEndpoint);
            await QueryReceived.RaiseAsync(this, eventArgs);

            return(eventArgs.Response);
        }
예제 #3
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));
        }
예제 #4
0
		internal void Parse(byte[] resultData, bool isRequest, DnsServer.SelectTsigKey tsigKeySelector, byte[] originalMac)
		{
			int currentPosition = 0;

			TransactionID = ParseUShort(resultData, ref currentPosition);
			_flags = ParseUShort(resultData, ref currentPosition);

			int questionCount = ParseUShort(resultData, ref currentPosition);
			int answerRecordCount = ParseUShort(resultData, ref currentPosition);
			int authorityRecordCount = ParseUShort(resultData, ref currentPosition);
			int additionalRecordCount = ParseUShort(resultData, ref currentPosition);

			ParseQuestions(resultData, ref currentPosition, questionCount);
			ParseSection(resultData, ref currentPosition, _answerRecords, answerRecordCount);
			ParseSection(resultData, ref currentPosition, _authorityRecords, authorityRecordCount);
			ParseSection(resultData, 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(resultData, tsigKeySelector, originalMac);
				}
			}

			FinishParsing();
		}
예제 #5
0
        internal int Encode(bool addLengthPrefix, byte[] originalTsigMac, bool isSubSequentResponse, out byte[] messageData, out byte[] newTSigMac)
        {
            PrepareEncoding();

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

            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 <DomainName, ushort> domainNames = new Dictionary <DomainName, 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);
            }
            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, null, false);
                    EncodeUShort(messageData, ref tsigVariablesPosition, (ushort)TSigOptions.RecordClass);
                    EncodeInt(messageData, ref tsigVariablesPosition, (ushort)TSigOptions.TimeToLive);
                    EncodeDomainName(messageData, offset, ref tsigVariablesPosition, TSigAlgorithmHelper.GetDomainName(TSigOptions.Algorithm), null, false);
                    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);
                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);
        }
예제 #6
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, null, false);
                EncodeUShort(validationBuffer, ref currentPosition, (ushort)TSigOptions.RecordClass);
                EncodeInt(validationBuffer, ref currentPosition, (ushort)TSigOptions.TimeToLive);
                EncodeDomainName(validationBuffer, 0, ref currentPosition, TSigAlgorithmHelper.GetDomainName(TSigOptions.Algorithm), null, false);
                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);
            }
        }
예제 #7
0
        internal int Encode(out byte[] messageData, bool addLengthPrefix, bool isRequest)
        {
            PrepareEncoding();

            int offset = (addLengthPrefix ? 2 : 0);

            int maxLength = offset;

            if (TSigOptions != null)
            {
                if (!isRequest)
                {
                    offset    += 2 + TSigOptions.OriginalMac.Length;
                    maxLength += 2 + TSigOptions.OriginalMac.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);
            }
            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)
            {
                int correctOffset = (addLengthPrefix ? 2 : 0);

                if (!isRequest)
                {
                    EncodeUShort(messageData, correctOffset, (ushort)TSigOptions.OriginalMac.Length);
                    Buffer.BlockCopy(TSigOptions.OriginalMac, 0, messageData, correctOffset + 2, TSigOptions.OriginalMac.Length);
                }

                EncodeUShort(messageData, offset, TSigOptions.OriginalID);

                int tsigVariablesPosition = currentPosition;

                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);
                if ((hashAlgorithm != null) && (TSigOptions.KeyData != null) && (TSigOptions.KeyData.Length > 0))
                {
                    hashAlgorithm.Key       = TSigOptions.KeyData;
                    TSigOptions.OriginalMac = hashAlgorithm.ComputeHash(messageData, correctOffset, tsigVariablesPosition - correctOffset);
                }
                else
                {
                    TSigOptions.OriginalMac = new byte[] { };
                }

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

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

                if (!isRequest)
                {
                    Buffer.BlockCopy(messageData, offset, messageData, correctOffset, (currentPosition - offset));

                    offset           = correctOffset;
                    currentPosition -= (2 + TSigOptions.OriginalMac.Length);
                }
            }

            if (addLengthPrefix)
            {
                int tmp = 0;
                EncodeUShort(messageData, ref tmp, (ushort)(currentPosition - offset));
            }

            return(currentPosition);
        }